diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c index 39c80b773a2..a1cd34acd23 100644 --- a/innobase/data/data0type.c +++ b/innobase/data/data0type.c @@ -18,8 +18,9 @@ column definitions, or records in the insert buffer, we use this charset-collation code for them. */ ulint data_mysql_default_charset_coll = 99999999; +ulint data_mysql_latin1_swedish_charset_coll = 99999999; -dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0}; +dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0}; dtype_t* dtype_binary = &dtype_binary_val; /************************************************************************* diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h index 0b8d77ee542..00a0845ace8 100644 --- a/innobase/include/data0type.h +++ b/innobase/include/data0type.h @@ -12,6 +12,7 @@ Created 1/16/1996 Heikki Tuuri #include "univ.i" extern ulint data_mysql_default_charset_coll; +extern ulint data_mysql_latin1_swedish_charset_coll; /* SQL data type struct */ typedef struct dtype_struct dtype_t; @@ -30,8 +31,8 @@ extern dtype_t* dtype_binary; #define DATA_BINARY 4 /* binary string */ #define DATA_BLOB 5 /* binary large object, or a TEXT type; if prtype & DATA_BINARY_TYPE == 0, then this is - actually a TEXT column; see also below about - the flag DATA_NONLATIN1 */ + actually a TEXT column (or a BLOB created + with < 4.0.14) */ #define DATA_INT 6 /* integer: can be any size 1 - 8 bytes */ #define DATA_SYS_CHILD 7 /* address of the child page in node pointer */ #define DATA_SYS 8 /* system column */ @@ -59,7 +60,7 @@ Tables created by a MySQL user have the following convention: code (not applicable for system columns). - In the second least significant byte we OR flags DATA_NOT_NULL, -DATA_UNSIGNED, DATA_BINARY_TYPE, DATA_NONLATIN1. +DATA_UNSIGNED, DATA_BINARY_TYPE. - In the third least significant byte of the precise type of string types we store the MySQL charset-collation code. In DATA_BLOB columns created with @@ -73,6 +74,23 @@ installation. If the stored charset code is 0 in the system table SYS_COLUMNS of InnoDB, that means that the default charset of this MySQL installation should be used. +When loading a table definition from the system tables to the InnoDB data +dictionary cache in main memory, InnoDB versions >= 4.1.2 and >= 5.0.1 check +if the stored charset-collation is 0, and if that is the case and the type is +a non-binary string, replace that 0 by the default charset-collation code of +this MySQL installation. In short, in old tables, the charset-collation code +in the system tables on disk can be 0, but in in-memory data structures +(dtype_t), the charset-collation code is always != 0 for non-binary string +types. + +In new tables, in binary string types, the charset-collation code is the +MySQL code for the 'binary charset', that is, != 0. + +For binary string types and for DATA_CHAR, DATA_VARCHAR, and for those +DATA_BLOB which are binary or have the charset-collation latin1_swedish_ci, +InnoDB performs all comparisons internally, without resorting to the MySQL +comparison functions. This is to save CPU time. + InnoDB's own internal system tables have different precise types for their columns, and for them the precise type is usually not used at all. */ @@ -112,14 +130,10 @@ be less than 256 */ string, this is ORed to the precise type: this only holds for tables created with >= MySQL-4.0.14 */ -#define DATA_NONLATIN1 2048 /* If the data type is DATA_BLOB with - the prtype & DATA_BINARY_TYPE == 0, that is, - TEXT, then in versions 4.0.14 - 4.0.xx this - flag is set to 1, if the charset is not - latin1. In version 4.1.1 this was set - to 1 for all TEXT columns. In versions >= 4.1.2 - this is set to 1 if the charset-collation of a - TEXT column is not latin1_swedish_ci. */ +/* #define DATA_NONLATIN1 2048 This is a relic from < 4.1.2 and < 5.0.1. + In earlier versions this was set for some + BLOB columns. +*/ /*-------------------------------------------*/ /* This many bytes we need to store the type information affecting the @@ -154,7 +168,7 @@ dtype_is_binary_string_type( Checks if a type is a non-binary string type. That is, dtype_is_string_type is TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. -For those DATA_BLOB columns this function currently returns FALSE. */ +For those DATA_BLOB columns this function currently returns TRUE. */ UNIV_INLINE ibool @@ -210,7 +224,7 @@ ulint dtype_form_prtype( /*==============*/ ulint old_prtype, /* in: the MySQL type code and the flags - DATA_NONLATIN1 etc. */ + DATA_BINARY_TYPE etc. */ ulint charset_coll); /* in: MySQL charset-collation code */ /************************************************************************* Gets the type length. */ diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic index 51a1d593d4b..41127a65183 100644 --- a/innobase/include/data0type.ic +++ b/innobase/include/data0type.ic @@ -54,7 +54,7 @@ dtype_is_binary_string_type( Checks if a type is a non-binary string type. That is, dtype_is_string_type is TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. -For those DATA_BLOB columns this function currently returns FALSE. */ +For those DATA_BLOB columns this function currently returns TRUE. */ UNIV_INLINE ibool dtype_is_non_binary_string_type( @@ -143,7 +143,7 @@ dtype_get_charset_coll( /*===================*/ ulint prtype) /* in: precise data type */ { - return((prtype >> 16) & 0xFF); + return((prtype >> 16) & 0xFFUL); } /************************************************************************* @@ -153,7 +153,7 @@ ulint dtype_form_prtype( /*==============*/ ulint old_prtype, /* in: the MySQL type code and the flags - DATA_NONLATIN1 etc. */ + DATA_BINARY_TYPE etc. */ ulint charset_coll) /* in: MySQL charset-collation code */ { ut_a(old_prtype < 256 * 256); @@ -237,9 +237,10 @@ dtype_new_store_for_order_and_null_size( buf[0] = buf[0] | 128; } - if (type->prtype & DATA_NONLATIN1) { - buf[0] = buf[0] | 64; - } + /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { + buf[0] = buf[0] | 64; + } + */ buf[1] = (byte)(type->prtype & 0xFFUL); @@ -271,10 +272,6 @@ dtype_read_for_order_and_null_size( type->prtype = type->prtype | DATA_BINARY_TYPE; } - if (buf[0] & 64) { - type->prtype = type->prtype | DATA_NONLATIN1; - } - type->len = mach_read_from_2(buf + 2); type->prtype = dtype_form_prtype(type->prtype, @@ -303,10 +300,6 @@ dtype_new_read_for_order_and_null_size( type->prtype = type->prtype | DATA_BINARY_TYPE; } - if (buf[0] & 64) { - type->prtype = type->prtype | DATA_NONLATIN1; - } - type->len = mach_read_from_2(buf + 2); mach_read_from_2(buf + 4); diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c index b6f32c83b35..86818168db9 100644 --- a/innobase/rem/rem0cmp.c +++ b/innobase/rem/rem0cmp.c @@ -331,7 +331,9 @@ cmp_data_data_slow( if (cur_type->mtype >= DATA_FLOAT || (cur_type->mtype == DATA_BLOB - && (cur_type->prtype & DATA_NONLATIN1))) { + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != + data_mysql_latin1_swedish_charset_coll)) { return(cmp_whole_field(cur_type, data1, len1, data2, len2)); } @@ -532,8 +534,10 @@ cmp_dtuple_rec_with_match( } if (cur_type->mtype >= DATA_FLOAT - || (cur_type->mtype == DATA_BLOB - && (cur_type->prtype & DATA_NONLATIN1))) { + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != + data_mysql_latin1_swedish_charset_coll)) { ret = cmp_whole_field(cur_type, dfield_get_data(dtuple_field), dtuple_f_len, @@ -854,8 +858,10 @@ cmp_rec_rec_with_match( } if (cur_type->mtype >= DATA_FLOAT - || (cur_type->mtype == DATA_BLOB - && (cur_type->prtype & DATA_NONLATIN1))) { + || (cur_type->mtype == DATA_BLOB + && 0 == (cur_type->prtype & DATA_BINARY_TYPE) + && dtype_get_charset_coll(cur_type->prtype) != + data_mysql_latin1_swedish_charset_coll)) { ret = cmp_whole_field(cur_type, rec1_b_ptr, rec1_f_len, diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 4558f0f2abe..5ce0e021782 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -22,7 +22,7 @@ extern my_string mysql_unix_port; CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) sig_handler pipe_sig_handler(int sig __attribute__((unused))); -my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free); void read_user_name(char *name); my_bool send_file_to_server(MYSQL *mysql, const char *filename); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8da695c5a9d..d9b01caf0ea 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -89,7 +89,7 @@ static void append_wild(char *to,char *end,const char *wild); sig_handler pipe_sig_handler(int sig); static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, const char *from, ulong length); -my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free); static my_bool mysql_client_init= 0; static my_bool org_my_init_done= 0; @@ -1666,14 +1666,14 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length) } if (simple_command(mysql, COM_PREPARE, query, length, 1)) { - stmt_close(stmt, 1); + stmt_close(stmt, 1, 0); DBUG_RETURN(0); } init_alloc_root(&stmt->mem_root,8192,0); if ((*mysql->methods->read_prepare_result)(mysql, stmt)) { - stmt_close(stmt, 1); + stmt_close(stmt, 1, 0); DBUG_RETURN(0); } @@ -3312,7 +3312,7 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) } -my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) +my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list, my_bool skip_free) { MYSQL *mysql; DBUG_ENTER("mysql_stmt_close"); @@ -3321,7 +3321,8 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) if (!(mysql= stmt->mysql)) { - my_free((gptr) stmt, MYF(MY_WME)); + if (!skip_free) + my_free((gptr) stmt, MYF(MY_WME)); DBUG_RETURN(0); } mysql_stmt_free_result(stmt); @@ -3329,7 +3330,7 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) { char buff[4]; int4store(buff, stmt->stmt_id); - if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)) + if (skip_free || simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1)) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, mysql->net.sqlstate); @@ -3350,7 +3351,7 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list) my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) { - return stmt_close(stmt, 0); + return stmt_close(stmt, 0, 0); } /* diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 4f6aa0b46d4..4d29838ecd0 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -409,7 +409,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff, &keys, param->key_crc+key,1)) DBUG_RETURN(-1); - if(!(keyinfo->flag & HA_FULLTEXT)) + if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL))) { if (keys != info->state->records) { @@ -558,6 +558,10 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, DBUG_ENTER("chk_index"); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); + /* TODO: implement appropriate check for RTree keys */ + if (keyinfo->flag & HA_SPATIAL) + DBUG_RETURN(0); + if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length))) { mi_check_print_error(param,"Not enough memory for keyblock"); @@ -1073,7 +1077,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) for (key=0 ; key < info->s->base.keys; key++) { if (key_checksum[key] != param->key_crc[key] && - !(info->s->keyinfo[key].flag & HA_FULLTEXT)) + !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL))) { mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records", key+1); diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index 2a47d0c048d..ab5338d383b 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -710,3 +710,43 @@ SELECT count(*) FROM t2; count(*) 0 DROP TABLE t2; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 (a geometry NOT NULL, SPATIAL (a)); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +drop table t1; diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 08ba8329b48..629a07a4913 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -67,3 +67,39 @@ while ($1) } DROP TABLE t2; + +drop table if exists t1; +CREATE TABLE t1 (a geometry NOT NULL, SPATIAL (a)); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)")); +check table t1; +analyze table t1; +drop table t1; + diff --git a/sql-common/client.c b/sql-common/client.c index 36b2c6122dd..a4ec7db6515 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2197,7 +2197,7 @@ void STDCALL mysql_close(MYSQL *mysql) for (element= mysql->stmts; element; element= next_element) { next_element= element->next; - stmt_close((MYSQL_STMT *)element->data, 0); + stmt_close((MYSQL_STMT *)element->data, 0, 1); } mysql->stmts= 0; } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 53e0d5aca61..40ba7ab1cef 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -755,11 +755,6 @@ innobase_init(void) srv_set_thread_priorities = TRUE; srv_query_thread_priority = QUERY_PRIOR; } - - /* Store the default charset-collation number of this MySQL - installation */ - - data_mysql_default_charset_coll = (ulint)default_charset_info->number; /* Set InnoDB initialization parameters according to the values read from MySQL .cnf file */ @@ -875,6 +870,14 @@ innobase_init(void) srv_print_verbose_log = mysql_embedded ? 0 : 1; + /* Store the default charset-collation number of this MySQL + installation */ + + data_mysql_default_charset_coll = (ulint)default_charset_info->number; + + data_mysql_latin1_swedish_charset_coll = + (ulint)my_charset_latin1.number; + /* Store the latin1_swedish_ci character ordering table to InnoDB. For non-latin1_swedish_ci charsets we use the MySQL comparison functions, and consequently we do not need to know the ordering internally in @@ -3260,7 +3263,6 @@ create_table_def( ulint nulls_allowed; ulint unsigned_type; ulint binary_type; - ulint nonlatin1_type; ulint charset_no; ulint i; @@ -3290,17 +3292,8 @@ create_table_def( unsigned_type = 0; } - if (col_type == DATA_BLOB - && strcmp(field->charset()->name, - "latin1_swedish_ci") != 0) { - nonlatin1_type = DATA_NONLATIN1; - } else { - nonlatin1_type = 0; - } - if (field->binary()) { binary_type = DATA_BINARY_TYPE; - nonlatin1_type = 0; } else { binary_type = 0; } @@ -3319,7 +3312,7 @@ create_table_def( col_type, dtype_form_prtype( (ulint)field->type() | nulls_allowed | unsigned_type - | nonlatin1_type | binary_type, + | binary_type, + charset_no), field->pack_length(), 0); }