diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 221015f8c7d..ba030379792 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -18,7 +18,6 @@ #undef MYSQL_SERVER #include "client_priv.h" #include -#include #include "log_event.h" #define BIN_LOG_HEADER_SIZE 4 diff --git a/client/mysqldump.c b/client/mysqldump.c index 9c64e2d1b3a..218a97c252e 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -43,7 +43,6 @@ #include #include #include -#include #include "client_priv.h" #include "mysql.h" diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 1f36f9b3059..2014b2b0adc 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -18,7 +18,6 @@ #include "heapdef.h" #include -#include diff --git a/include/m_ctype.h b/include/m_ctype.h index 87b45bd4954..9be5538b48a 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -53,7 +53,6 @@ typedef struct unicase_info_st #define MY_SEQ_SPACES 2 /* My charsets_list flags */ -#define MY_NO_SETS 0 #define MY_CS_COMPILED 1 /* compiled-in sets */ #define MY_CS_CONFIG 2 /* sets that have a *.conf file */ #define MY_CS_INDEX 4 /* sets listed in the Index file */ @@ -62,7 +61,7 @@ typedef struct unicase_info_st #define MY_CS_PRIMARY 32 /* if primary collation */ #define MY_CS_STRNXFRM 64 /* if strnxfrm is used for sort */ #define MY_CS_UNICODE 128 /* is a charset is full unicode */ -#define MY_CS_NONTEXT 256 /* if a charset is not sprintf() compatible */ +#define MY_CS_READY 256 /* if a charset is initialized */ #define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/ #define MY_CHARSET_UNDEFINED 0 @@ -102,6 +101,7 @@ struct charset_info_st; typedef struct my_collation_handler_st { + my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint)); /* Collation routines */ int (*strnncoll)(struct charset_info_st *, const uchar *, uint, const uchar *, uint); @@ -140,6 +140,7 @@ extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler; typedef struct my_charset_handler_st { + my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint)); /* Multibyte routines */ int (*ismbchar)(struct charset_info_st *, const char *, const char *); int (*mbcharlen)(struct charset_info_st *, uint); @@ -208,8 +209,8 @@ typedef struct charset_info_st uint16 **sort_order_big; uint16 *tab_to_uni; MY_UNI_IDX *tab_from_uni; - uchar state_map[256]; - uchar ident_map[256]; + uchar *state_map; + uchar *ident_map; uint strxfrm_multiply; uint mbminlen; uint mbmaxlen; diff --git a/include/m_string.h b/include/m_string.h index 7fc35dc2e48..0709dbaffb4 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -123,7 +123,6 @@ extern void bmove_align(gptr dst,const gptr src,uint len); #endif #ifdef HAVE_purify -#include #define memcpy_overlap(A,B,C) \ DBUG_ASSERT((A) <= (B) || ((B)+(C)) <= (A)); \ bmove((byte*) (A),(byte*) (B),(size_t) (C)); diff --git a/include/my_dbug.h b/include/my_dbug.h index 5c88e2e42db..d02ea5bf050 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -16,6 +16,7 @@ #ifndef _dbug_h #define _dbug_h +#include #ifdef __cplusplus extern "C" { #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index b77fc5fd6fd..eb8368977e9 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -27,7 +27,6 @@ #include #include #include -#include /* for DBUG_ASSERT() */ #ifdef HAVE_PWD_H #include #endif @@ -2502,6 +2501,13 @@ static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, mysql->net.sqlstate); + /* + If there was an error, there are no more pending rows: + reset statement status to not hang up in following + mysql_stmt_close (it will try to flush result set before + closing the statement). + */ + mysql->status= MYSQL_STATUS_READY; goto error; } if (!*row) diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h index a97485ec021..e23bc3b75ac 100644 --- a/myisam/ftdefs.h +++ b/myisam/ftdefs.h @@ -22,7 +22,6 @@ #include #include #include -#include #define true_word_char(s,X) (my_isalnum(s,X) || (X)=='_') #define misc_word_char(X) ((X)=='\'') diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 3eb8e9a7226..c19f2582b9c 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -18,7 +18,6 @@ #include "fulltext.h" #include "rt_index.h" -#include static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag, uchar *key,uint key_length,my_off_t page,uchar *anc_buff); diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index f64e774810d..0b8d3c97872 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -25,7 +25,6 @@ */ #include "myisamdef.h" -#include /* Enough for comparing if number is zero */ static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 4aebba041f8..d19a3130a86 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -19,7 +19,6 @@ #include "myisamdef.h" #include "m_ctype.h" #include "sp_defs.h" -#include #ifdef HAVE_IEEEFP_H #include #endif diff --git a/myisam/mi_open.c b/myisam/mi_open.c index d03c18091aa..562227d2f03 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -20,7 +20,6 @@ #include "sp_defs.h" #include "rt_index.h" #include -#include #if defined(MSDOS) || defined(__WIN__) #ifdef __WIN__ diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 51ced6fa15a..1b03acddbc1 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -18,7 +18,6 @@ #include "fulltext.h" #include "m_ctype.h" -#include static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, diff --git a/myisam/mi_write.c b/myisam/mi_write.c index c17f47fc1ae..dc596672a84 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -18,7 +18,6 @@ #include "fulltext.h" #include "rt_index.h" -#include #define MAX_POINTER_LENGTH 8 diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index bd5646f4068..06259ff4931 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -656,3 +656,31 @@ select stddev(2) from t1; stddev(2) NULL drop table t1; +create table t1 (a int); +insert into t1 values (1),(2); +prepare stmt1 from 'SELECT COUNT(*) FROM t1'; +execute stmt1; +COUNT(*) +2 +execute stmt1; +COUNT(*) +2 +execute stmt1; +COUNT(*) +2 +deallocate prepare stmt1; +drop table t1; +create table t1 (a int, primary key(a)); +insert into t1 values (1),(2); +prepare stmt1 from 'SELECT max(a) FROM t1'; +execute stmt1; +max(a) +2 +execute stmt1; +max(a) +2 +execute stmt1; +max(a) +2 +deallocate prepare stmt1; +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a6ff608ab66..b8b899f4850 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -328,10 +328,10 @@ patient_uq clinic_uq explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where -2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 +2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index Warnings: Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1 -Note 1003 select test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select test.t7.uq AS `uq`,test.t7.name AS `name` from test.t7 where (test.t7.uq = test.t6.clinic_uq)) +Note 1003 select test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select 1 AS `Not_used` from test.t7 where (test.t7.uq = test.t6.clinic_uq)) select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); ERROR 23000: Column: 'a' in field list is ambiguous drop table t1,t2,t3; @@ -1817,3 +1817,17 @@ a 1 3 DROP TABLE t1; +create table t1 (a int, b int); +insert into t1 values (1,2),(3,4); +select * from t1 up where exists (select * from t1 where t1.a=up.a); +a b +1 2 +3 4 +explain extended select * from t1 up where exists (select * from t1 where t1.a=up.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY up ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1 +Note 1003 select test.up.a AS `a`,test.up.b AS `b` from test.t1 up where exists(select 1 AS `Not_used` from test.t1 where (test.t1.a = test.up.a)) +drop table t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 7966a2262f4..74f4c1bad44 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -396,3 +396,25 @@ create table t1 (a int); select variance(2) from t1; select stddev(2) from t1; drop table t1; + + +# +# cleunup() of optimized away count(*) and max/min +# +create table t1 (a int); +insert into t1 values (1),(2); +prepare stmt1 from 'SELECT COUNT(*) FROM t1'; +execute stmt1; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; +drop table t1; + +create table t1 (a int, primary key(a)); +insert into t1 values (1),(2); +prepare stmt1 from 'SELECT max(a) FROM t1'; +execute stmt1; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index bdefc87b3fd..4b2fd33abfd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1158,3 +1158,12 @@ SELECT a FROM t1 WHERE a >= ALL ( SELECT a FROM t1 WHERE b = 2 ); SELECT a FROM t1 WHERE a <= ALL ( SELECT a FROM t1 WHERE b = 2 ); SELECT a FROM t1 WHERE a <> ALL ( SELECT a FROM t1 WHERE b = 2 ); DROP TABLE t1; + +# +# SELECT(EXISTS * ...)optimisation +# +create table t1 (a int, b int); +insert into t1 values (1,2),(3,4); +select * from t1 up where exists (select * from t1 where t1.a=up.a); +explain extended select * from t1 up where exists (select * from t1 where t1.a=up.a); +drop table t1; diff --git a/mysys/charset-def.c b/mysys/charset-def.c index a89cf866933..4f988608d13 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -22,6 +22,19 @@ init_compiled_charsets() that only adds those that he wants */ +#ifdef HAVE_CHARSET_ucs2 +extern CHARSET_INFO my_charset_ucs2_general_uca; +extern CHARSET_INFO my_charset_ucs2_icelandic_uca_ci; +extern CHARSET_INFO my_charset_ucs2_latvian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_romanian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_slovenian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_polish_uca_ci; +extern CHARSET_INFO my_charset_ucs2_estonian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_spanish_uca_ci; +extern CHARSET_INFO my_charset_ucs2_swedish_uca_ci; +extern CHARSET_INFO my_charset_ucs2_turkish_uca_ci; +#endif + my_bool init_compiled_charsets(myf flags __attribute__((unused))) { CHARSET_INFO *cs; @@ -74,6 +87,16 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_general_ci); add_compiled_collation(&my_charset_ucs2_bin); add_compiled_collation(&my_charset_ucs2_general_uca); + add_compiled_collation(&my_charset_ucs2_general_uca); + add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci); + add_compiled_collation(&my_charset_ucs2_latvian_uca_ci); + add_compiled_collation(&my_charset_ucs2_romanian_uca_ci); + add_compiled_collation(&my_charset_ucs2_slovenian_uca_ci); + add_compiled_collation(&my_charset_ucs2_polish_uca_ci); + add_compiled_collation(&my_charset_ucs2_estonian_uca_ci); + add_compiled_collation(&my_charset_ucs2_spanish_uca_ci); + add_compiled_collation(&my_charset_ucs2_swedish_uca_ci); + add_compiled_collation(&my_charset_ucs2_turkish_uca_ci); #endif #ifdef HAVE_CHARSET_ujis diff --git a/mysys/charset.c b/mysys/charset.c index a9c733e25cf..72f102a2296 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -22,354 +22,6 @@ #include -/* - Collation language is implemented according to - subset of ICU Collation Customization (tailorings): - http://oss.software.ibm.com/icu/userguide/Collate_Customization.html - - Collation language elements: - Delimiters: - space - skipped - - := A-Z | a-z | \uXXXX - - Shift command: - := & - reset at this letter. - - Diff command: - := < - Identifies a primary difference. - := << - Identifies a secondary difference. - := <<< - Idenfifies a tertiary difference. - - - Collation rules: - := { } - - := - | - | - | - - := [ ] - - An example, Polish collation: - - &A < \u0105 <<< \u0104 - &C < \u0107 <<< \u0106 - &E < \u0119 <<< \u0118 - &L < \u0142 <<< \u0141 - &N < \u0144 <<< \u0143 - &O < \u00F3 <<< \u00D3 - &S < \u015B <<< \u015A - &Z < \u017A <<< \u017B -*/ - - -typedef enum my_coll_lexem_num_en -{ - MY_COLL_LEXEM_EOF = 0, - MY_COLL_LEXEM_DIFF = 1, - MY_COLL_LEXEM_SHIFT = 4, - MY_COLL_LEXEM_CHAR = 5, - MY_COLL_LEXEM_ERROR = 6 -} my_coll_lexem_num; - - -typedef struct my_coll_lexem_st -{ - const char *beg; - const char *end; - const char *prev; - int diff; - int code; -} MY_COLL_LEXEM; - - -/* - Initialize collation rule lexical anilizer - - SYNOPSIS - my_coll_lexem_init - lexem Lex analizer to init - str Const string to parse - strend End of the string - USAGE - - RETURN VALUES - N/A -*/ - -static void my_coll_lexem_init(MY_COLL_LEXEM *lexem, - const char *str, const char *strend) -{ - lexem->beg= str; - lexem->prev= str; - lexem->end= strend; - lexem->diff= 0; - lexem->code= 0; -} - - -/* - Print collation customization expression parse error, with context. - - SYNOPSIS - my_coll_lexem_print_error - lexem Lex analizer to take context from - errstr sting to write error to - errsize errstr size - txt error message - USAGE - - RETURN VALUES - N/A -*/ - -static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem, - char *errstr, size_t errsize, - const char *txt) -{ - char tail[30]; - size_t len= lexem->end - lexem->prev; - strmake (tail, lexem->prev, min(len, sizeof(tail)-1)); - errstr[errsize-1]= '\0'; - my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail); -} - - -/* - Convert a hex digit into its numeric value - - SYNOPSIS - ch2x - ch hex digit to convert - USAGE - - RETURN VALUES - an integer value in the range 0..15 - -1 on error -*/ - -static int ch2x(int ch) -{ - if (ch >= '0' && ch <= '9') - return ch - '0'; - - if (ch >= 'a' && ch <= 'f') - return 10 + ch - 'a'; - - if (ch >= 'A' && ch <= 'F') - return 10 + ch - 'A'; - - return -1; -} - - -/* - Collation language lexical parser: - Scans the next lexem. - - SYNOPSIS - my_coll_lexem_next - lexem Lex analizer, previously initialized by - my_coll_lexem_init. - USAGE - Call this function in a loop - - RETURN VALUES - Lexem number: eof, diff, shift, char or error. -*/ - -static my_coll_lexem_num my_coll_lexem_next(MY_COLL_LEXEM *lexem) -{ - for ( ;lexem->beg < lexem->end ; lexem->beg++) - { - lexem->prev= lexem->beg; - if (lexem->beg[0] == ' ' || lexem->beg[0] == '\t' || - lexem->beg[0] == '\r' || lexem->beg[0] == '\n') - continue; - - if (lexem->beg[0] == '&') - { - lexem->beg++; - return MY_COLL_LEXEM_SHIFT; - } - - if (lexem->beg[0] == '<') - { - for (lexem->beg++, lexem->diff=1; - (lexem->beg < lexem->end) && - (lexem->beg[0] == '<') && (lexem->diff<3); - lexem->beg++, lexem->diff++); - return MY_COLL_LEXEM_DIFF; - } - - if ((lexem->beg[0] >= 'a' && lexem->beg[0] <= 'z') || - (lexem->beg[0] >= 'A' && lexem->beg[0] <= 'Z')) - { - lexem->code= lexem->beg[0]; - lexem->beg++; - return MY_COLL_LEXEM_CHAR; - } - - if ((lexem->beg[0] == '\\') && - (lexem->beg+2 < lexem->end) && - (lexem->beg[1] == 'u')) - { - int ch; - - lexem->code= 0; - for (lexem->beg+=2; - (lexem->beg < lexem->end) && ((ch= ch2x(lexem->beg[0])) >= 0) ; - lexem->beg++) - { - lexem->code= (lexem->code << 4) + ch; - } - return MY_COLL_LEXEM_CHAR; - } - - return MY_COLL_LEXEM_ERROR; - } - return MY_COLL_LEXEM_EOF; -} - - -/* - Collation rule item -*/ - -typedef struct my_coll_rule_item_st -{ - uint base; /* Base character */ - uint curr; /* Current character */ - int diff[3]; /* Primary, Secondary and Tertiary difference */ -} MY_COLL_RULE; - - -/* - Collation language syntax parser. - Uses lexical parser. - - SYNOPSIS - my_coll_rule_parse - rule Collation rule list to load to. - str A string containin collation language expression. - strend End of the string. - USAGE - - RETURN VALUES - 0 - OK - 1 - ERROR, e.g. too many items. -*/ - -static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems, - const char *str, const char *strend, - char *errstr, size_t errsize) -{ - MY_COLL_LEXEM lexem; - my_coll_lexem_num lexnum; - my_coll_lexem_num prevlexnum= MY_COLL_LEXEM_ERROR; - MY_COLL_RULE item; - int state= 0; - size_t nitems= 0; - - /* Init all variables */ - errstr[0]= '\0'; - bzero(&item, sizeof(item)); - my_coll_lexem_init(&lexem, str, strend); - - while ((lexnum= my_coll_lexem_next(&lexem))) - { - if (lexnum == MY_COLL_LEXEM_ERROR) - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Unknown character"); - return -1; - } - - switch (state) { - case 0: - if (lexnum != MY_COLL_LEXEM_SHIFT) - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& expected"); - return -1; - } - prevlexnum= lexnum; - state= 2; - continue; - - case 1: - if (lexnum != MY_COLL_LEXEM_SHIFT && lexnum != MY_COLL_LEXEM_DIFF) - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& or < expected"); - return -1; - } - prevlexnum= lexnum; - state= 2; - continue; - - case 2: - if (lexnum != MY_COLL_LEXEM_CHAR) - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"character expected"); - return -1; - } - - if (prevlexnum == MY_COLL_LEXEM_SHIFT) - { - item.base= lexem.code; - item.diff[0]= 0; - item.diff[1]= 0; - item.diff[2]= 0; - } - else if (prevlexnum == MY_COLL_LEXEM_DIFF) - { - item.curr= lexem.code; - if (lexem.diff == 3) - { - item.diff[2]++; - } - else if (lexem.diff == 2) - { - item.diff[1]++; - item.diff[2]= 0; - } - else if (lexem.diff == 1) - { - item.diff[0]++; - item.diff[1]= 0; - item.diff[2]= 0; - } - if (nitems >= mitems) - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Too many rules"); - return -1; - } - rule[nitems++]= item; - } - else - { - my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Should never happen"); - return -1; - } - state= 1; - continue; - } - } - return (size_t) nitems; -} - - -typedef struct -{ - int nchars; - MY_UNI_IDX uidx; -} uni_idx; - -#define PLANE_SIZE 0x100 -#define PLANE_NUM 0x100 -#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM) - - /* The code below implements this functionality: @@ -386,32 +38,21 @@ my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2) } -static void set_max_sort_char(CHARSET_INFO *cs) -{ - uchar max_char; - uint i; - - if (!cs->sort_order) - return; - - max_char=cs->sort_order[(uchar) cs->max_sort_char]; - for (i= 0; i < 256; i++) - { - if ((uchar) cs->sort_order[i] > max_char) - { - max_char=(uchar) cs->sort_order[i]; - cs->max_sort_char= i; - } - } -} - - -static void init_state_maps(CHARSET_INFO *cs) +static my_bool init_state_maps(CHARSET_INFO *cs) { uint i; - uchar *state_map= cs->state_map; - uchar *ident_map= cs->ident_map; + uchar *state_map; + uchar *ident_map; + if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME)))) + return 1; + + if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME)))) + return 1; + + state_map= cs->state_map; + ident_map= cs->ident_map; + /* Fill state_map with states to get a faster parser */ for (i=0; i < 256 ; i++) { @@ -458,6 +99,7 @@ static void init_state_maps(CHARSET_INFO *cs) state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX; state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) MY_LEX_IDENT_OR_BIN; state_map[(uchar)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR; + return 0; } @@ -469,98 +111,11 @@ static void simple_cs_init_functions(CHARSET_INFO *cs) cs->coll= &my_collation_8bit_simple_ci_handler; cs->cset= &my_charset_8bit_handler; - cs->mbminlen= 1; - cs->mbmaxlen= 1; } -static int pcmp(const void * f, const void * s) -{ - const uni_idx *F= (const uni_idx*) f; - const uni_idx *S= (const uni_idx*) s; - int res; - if (!(res=((S->nchars)-(F->nchars)))) - res=((F->uidx.from)-(S->uidx.to)); - return res; -} - - -static my_bool create_fromuni(CHARSET_INFO *cs) -{ - uni_idx idx[PLANE_NUM]; - int i,n; - - /* Clear plane statistics */ - bzero(idx,sizeof(idx)); - - /* Count number of characters in each plane */ - for (i=0; i< 0x100; i++) - { - uint16 wc=cs->tab_to_uni[i]; - int pl= PLANE_NUMBER(wc); - - if (wc || !i) - { - if (!idx[pl].nchars) - { - idx[pl].uidx.from=wc; - idx[pl].uidx.to=wc; - }else - { - idx[pl].uidx.from=wcidx[pl].uidx.to?wc:idx[pl].uidx.to; - } - idx[pl].nchars++; - } - } - - /* Sort planes in descending order */ - qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp); - - for (i=0; i < PLANE_NUM; i++) - { - int ch,numchars; - - /* Skip empty plane */ - if (!idx[i].nchars) - break; - - numchars=idx[i].uidx.to-idx[i].uidx.from+1; - if (!(idx[i].uidx.tab=(uchar*) my_once_alloc(numchars * - sizeof(*idx[i].uidx.tab), - MYF(MY_WME)))) - return TRUE; - - bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab)); - - for (ch=1; ch < PLANE_SIZE; ch++) - { - uint16 wc=cs->tab_to_uni[ch]; - if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc) - { - int ofs= wc - idx[i].uidx.from; - idx[i].uidx.tab[ofs]= ch; - } - } - } - - /* Allocate and fill reverse table for each plane */ - n=i; - if (!(cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1), - MYF(MY_WME)))) - return TRUE; - - for (i=0; i< n; i++) - cs->tab_from_uni[i]= idx[i].uidx; - - /* Set end-of-list marker */ - bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX)); - return FALSE; -} - - -static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) +static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) { to->number= from->number ? from->number : to->number; @@ -582,7 +137,8 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) MY_CS_CTYPE_TABLE_SIZE, MYF(MY_WME)))) goto err; - init_state_maps(to); + if (init_state_maps(to)) + goto err; } if (from->to_lower) if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower, @@ -601,7 +157,7 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) MY_CS_SORT_ORDER_TABLE_SIZE, MYF(MY_WME)))) goto err; - set_max_sort_char(to); + } if (from->tab_to_uni) { @@ -609,284 +165,17 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) if (!(to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, sz, MYF(MY_WME)))) goto err; - if (create_fromuni(to)) - goto err; } - to->mbminlen= 1; - to->mbmaxlen= 1; - - return 0; - -err: - return 1; -} - - -#ifdef HAVE_CHARSET_ucs2 - -typedef struct my_tailoring_st -{ - uint number; - const char *name; - const char *tailoring; -} my_tailoring; - -static my_tailoring tailoring[]= -{ - { - 0, "icelandic", - /* - Some sources treat LETTER A WITH DIARESIS (00E4,00C4) - secondary greater than LETTER AE (00E6,00C6). - http://www.evertype.com/alphabets/icelandic.pdf - http://developer.mimer.com/collations/charts/icelandic.htm - - Other sources do not provide any special rules - for LETTER A WITH DIARESIS: - http://www.omniglot.com/writing/icelandic.htm - http://en.wikipedia.org/wiki/Icelandic_alphabet - http://oss.software.ibm.com/icu/charts/collation/is.html - - Let's go the first way. - */ - "& A < \\u00E1 <<< \\u00C1 " - "& D < \\u00F0 <<< \\u00D0 " - "& E < \\u00E9 <<< \\u00C9 " - "& I < \\u00ED <<< \\u00CD " - "& O < \\u00F3 <<< \\u00D3 " - "& U < \\u00FA <<< \\u00DA " - "& Y < \\u00FD <<< \\u00DD " - "& Z < \\u00FE <<< \\u00DE " - "< \\u00E6 <<< \\u00C6 << \\u00E4 <<< \\u00C4 " - "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 " - "< \\u00E5 <<< \\u00C5 " - }, - { - 1, "latvian", - /* - Some sources treat I and Y primary different. - Other sources treat I and Y the same on primary level. - We'll go the first way. - */ - "& C < \\u010D <<< \\u010C " - "& G < \\u0123 <<< \\u0122 " - "& I < \\u0079 <<< \\u0059 " - "& K < \\u0137 <<< \\u0136 " - "& L < \\u013C <<< \\u013B " - "& N < \\u0146 <<< \\u0145 " - "& R < \\u0157 <<< \\u0156 " - "& S < \\u0161 <<< \\u0160 " - "& Z < \\u017E <<< \\u017D " - }, - { - 2, "romanian", - "& A < \\u0103 <<< \\u0102 < \\u00E2 <<< \\u00C2 " - "& I < \\u00EE <<< \\u00CE " - "& S < \\u0219 <<< \\u0218 << \\u015F <<< \\u015E " - "& T < \\u021B <<< \\u021A << \\u0163 <<< \\u0162 " - }, - { - 3, "slovenian", - "& C < \\u010D <<< \\u010C " - "& S < \\u0161 <<< \\u0160 " - "& Z < \\u017E <<< \\u017D " - }, - { - 4, "polish", - "& A < \\u0105 <<< \\u0104 " - "& C < \\u0107 <<< \\u0106 " - "& E < \\u0119 <<< \\u0118 " - "& L < \\u0142 <<< \\u0141 " - "& N < \\u0144 <<< \\u0143 " - "& O < \\u00F3 <<< \\u00D3 " - "& S < \\u015B <<< \\u015A " - "& Z < \\u017A <<< \\u017B " - }, - { - 5, "estonian", - "& S < \\u0161 <<< \\u0160 " - " < \\u007A <<< \\u005A " - " < \\u017E <<< \\u017D " - "& W < \\u00F5 <<< \\u00D5 " - "< \\u00E4 <<< \\u00C4 " - "< \\u00F6 <<< \\u00D6 " - "< \\u00FC <<< \\u00DC " - }, - { - 6, "spanish", - "& N < \\u00F1 <<< \\u00D1 " - }, - { - 7, "swedish", - /* - Some sources treat V and W as similar on primary level. - We'll treat V and W as different on primary level. - */ - "& Y <<\\u00FC <<< \\u00DC " - "& Z < \\u00E5 <<< \\u00C5 " - "< \\u00E4 <<< \\u00C4 << \\u00E6 <<< \\u00C6 " - "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 " - }, - { - 8, "turkish", - "& C < \\u00E7 <<< \\u00C7 " - "& G < \\u011F <<< \\u011E " - "& H < \\u0131 <<< \\u0049 " - "& O < \\u00F6 <<< \\u00D6 " - "& S < \\u015F <<< \\u015E " - "& U < \\u00FC <<< \\u00DC " - }, - { - 0, NULL, NULL - } -}; - -#define MY_MAX_COLL_RULE 64 - -/* - This function copies an UCS2 collation from - the default Unicode Collation Algorithm (UCA) - weights applying tailorings, i.e. a set of - alternative weights for some characters. - - The default UCA weights are stored in my_charset_ucs2_general_uca. - They consist of 256 pages, 256 character each. - - If a page is not overwritten by tailoring rules, - it is copies as is from UCA as is. - - If a page contains some overwritten characters, it is - allocated. Untouched characters are copied from the - default weights. -*/ - -static my_bool create_tailoring(CHARSET_INFO *cs) -{ - MY_COLL_RULE rule[MY_MAX_COLL_RULE]; - char errstr[128]; - uchar *newlengths; - uint16 **newweights; - const uchar *deflengths= my_charset_ucs2_general_uca.sort_order; - uint16 **defweights= my_charset_ucs2_general_uca.sort_order_big; - int rc, i; - - if (!cs->tailoring) - return 1; - - /* Parse ICU Collation Customization expression */ - if ((rc= my_coll_rule_parse(rule, MY_MAX_COLL_RULE, - cs->tailoring, - cs->tailoring + strlen(cs->tailoring), - errstr, sizeof(errstr))) <= 0) - { - /* - TODO: add error message reporting. - printf("Error: %d '%s'\n", rc, errstr); - */ - return 1; - } - - if (!(newweights= (uint16**) my_once_alloc(256*sizeof(uint16*),MYF(MY_WME)))) - return 1; - bzero(newweights, 256*sizeof(uint16*)); - - if (!(newlengths= (uchar*) my_once_memdup(deflengths,256,MYF(MY_WME)))) - return 1; - - /* - Calculate maximum lenghts for the pages - which will be overwritten. - */ - for (i=0; i < rc; i++) - { - uint pageb= (rule[i].base >> 8) & 0xFF; - uint pagec= (rule[i].curr >> 8) & 0xFF; - - if (newlengths[pagec] < deflengths[pageb]) - newlengths[pagec]= deflengths[pageb]; - } - - for (i=0; i < rc; i++) - { - uint pageb= (rule[i].base >> 8) & 0xFF; - uint pagec= (rule[i].curr >> 8) & 0xFF; - uint chb, chc; - - if (!newweights[pagec]) - { - /* Alloc new page and copy the default UCA weights */ - uint size= 256*newlengths[pagec]*sizeof(uint16); - - if (!(newweights[pagec]= (uint16*) my_once_alloc(size,MYF(MY_WME)))) - return 1; - bzero((void*) newweights[pagec], size); - - for (chc=0 ; chc < 256; chc++) - { - memcpy(newweights[pagec] + chc*newlengths[pagec], - defweights[pagec] + chc*deflengths[pagec], - deflengths[pagec]*sizeof(uint16)); - } - } - - /* - Aply the alternative rule: - shift to the base character and primary difference. - */ - chc= rule[i].curr & 0xFF; - chb= rule[i].base & 0xFF; - memcpy(newweights[pagec] + chc*newlengths[pagec], - defweights[pageb] + chb*deflengths[pageb], - deflengths[pageb]*sizeof(uint16)); - /* Apply primary difference */ - newweights[pagec][chc*newlengths[pagec]]+= rule[i].diff[0]; - } - - /* Copy non-overwritten pages from the default UCA weights */ - for (i= 0; i < 256 ; i++) - if (!newweights[i]) - newweights[i]= defweights[i]; - - cs->sort_order= newlengths; - cs->sort_order_big= newweights; - - return 0; -} - - -static int ucs2_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) -{ - - to->number= from->number ? from->number : to->number; - - if (from->csname) - if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME)))) - goto err; - - if (from->name) - if (!(to->name= my_once_strdup(from->name,MYF(MY_WME)))) - goto err; - - if (from->comment) - if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME)))) - goto err; - if (from->tailoring) if (!(to->tailoring= my_once_strdup(from->tailoring,MYF(MY_WME)))) goto err; - - to->strxfrm_multiply= my_charset_ucs2_general_uca.strxfrm_multiply; - to->min_sort_char= my_charset_ucs2_general_uca.min_sort_char; - to->max_sort_char= my_charset_ucs2_general_uca.max_sort_char; - to->mbminlen= 2; - to->mbmaxlen= 2; - - return create_tailoring(to); - + + return 0; + err: return 1; } -#endif + static my_bool simple_cs_is_full(CHARSET_INFO *cs) @@ -920,22 +209,28 @@ static int add_collation(CHARSET_INFO *cs) if (!(all_charsets[cs->number]->state & MY_CS_COMPILED)) { + CHARSET_INFO *new= all_charsets[cs->number]; + if (cs_copy_data(all_charsets[cs->number],cs)) + return MY_XML_ERROR; + if (!strcmp(cs->csname,"ucs2") ) { #ifdef HAVE_CHARSET_ucs2 - CHARSET_INFO *new= all_charsets[cs->number]; new->cset= my_charset_ucs2_general_uca.cset; new->coll= my_charset_ucs2_general_uca.coll; - if (ucs2_copy_data(new, cs)) - return MY_XML_ERROR; + new->strxfrm_multiply= my_charset_ucs2_general_uca.strxfrm_multiply; + new->min_sort_char= my_charset_ucs2_general_uca.min_sort_char; + new->max_sort_char= my_charset_ucs2_general_uca.max_sort_char; + new->mbminlen= 2; + new->mbmaxlen= 2; new->state |= MY_CS_AVAILABLE | MY_CS_LOADED; #endif } else { simple_cs_init_functions(all_charsets[cs->number]); - if (simple_cs_copy_data(all_charsets[cs->number],cs)) - return MY_XML_ERROR; + new->mbminlen= 1; + new->mbmaxlen= 1; if (simple_cs_is_full(all_charsets[cs->number])) { all_charsets[cs->number]->state |= MY_CS_LOADED; @@ -977,25 +272,6 @@ static int add_collation(CHARSET_INFO *cs) return MY_XML_OK; } -#ifdef HAVE_CHARSET_ucs2 -static my_bool init_uca_charsets() -{ - my_tailoring *t; - CHARSET_INFO cs= my_charset_ucs2_general_uca; - char name[64]; - - cs.state= MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT; - for (t= tailoring; t->tailoring; t++) - { - cs.number= 128 + t->number; - cs.tailoring= t->tailoring; - cs.name= name; - sprintf(name, "ucs2_%s_ci", t->name); - add_collation(&cs); - } - return 0; -} -#endif #define MY_MAX_ALLOWED_BUF 1024*1024 #define MY_CHARSET_INDEX "Index.xml" @@ -1070,6 +346,10 @@ void add_compiled_collation(CHARSET_INFO *cs) cs->state|= MY_CS_AVAILABLE; } +static void *cs_alloc(uint size) +{ + return my_once_alloc(size, MYF(MY_WME)); +} #ifdef __NETWARE__ @@ -1095,9 +375,6 @@ static my_bool init_available_charsets(myf myflags) bzero(&all_charsets,sizeof(all_charsets)); init_compiled_charsets(myflags); -#ifdef HAVE_CHARSET_ucs2 - init_uca_charsets(); -#endif /* Copy compiled charsets */ for (cs=all_charsets; @@ -1106,9 +383,9 @@ static my_bool init_available_charsets(myf myflags) { if (*cs) { - set_max_sort_char(*cs); if (cs[0]->ctype) - init_state_maps(*cs); + if (init_state_maps(*cs)) + *cs= NULL; } } @@ -1193,6 +470,14 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; } pthread_mutex_unlock(&THR_LOCK_charset); + if (cs && !(cs->state & MY_CS_READY)) + { + if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || + (cs->coll->init && cs->coll->init(cs, cs_alloc))) + cs= NULL; + else + cs->state|= MY_CS_READY; + } return cs; } diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 7b5371c4289..f16f2b7ab72 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -55,7 +55,6 @@ TODO: #include "mysys_err.h" static void my_aiowait(my_aio_result *result); #endif -#include #include #ifdef THREAD diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 70b2f288538..3755bcdb53d 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -23,7 +23,6 @@ #include #include #include -#include my_off_t my_b_append_tell(IO_CACHE* info) { diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 168483f276b..32b3154b8ed 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -44,7 +44,6 @@ #include "my_static.h" #include #include -#include #include /* diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 0f8984e6b3d..3a09255b0b0 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -35,7 +35,6 @@ #include "mysys_priv.h" #include -#include #include diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c index 5044a505054..27281f3489d 100644 --- a/mysys/my_gethostbyname.c +++ b/mysys/my_gethostbyname.c @@ -18,7 +18,6 @@ /* Thread safe version of gethostbyname_r() */ #include "mysys_priv.h" -#include #if !defined(MSDOS) && !defined(__WIN__) #include #endif diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 8d0b05d55f7..d7a9babe5e7 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index d721418ffa1..37517fb8327 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -23,7 +23,6 @@ #include #include #include -#include #if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread) #define SCHED_POLICY SCHED_RR diff --git a/mysys/my_seek.c b/mysys/my_seek.c index ec24a26b3d9..6af65d70fd0 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -15,7 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysys_priv.h" -#include /* Seek to position in file */ /*ARGSUSED*/ diff --git a/mysys/rijndael.c b/mysys/rijndael.c index dd0c45445d5..43cd14101ca 100644 --- a/mysys/rijndael.c +++ b/mysys/rijndael.c @@ -26,7 +26,6 @@ */ #include -#include #include "rijndael.h" /* diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 54aa4d421f6..84a8e779ae1 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -27,7 +27,6 @@ #include #include #include "thr_alarm.h" -#include #ifdef HAVE_SYS_SELECT_H #include /* AIX needs this for fd_set */ diff --git a/ndb/include/kernel/signaldata/TcKeyConf.hpp b/ndb/include/kernel/signaldata/TcKeyConf.hpp index c133368bcbc..27ff344f793 100644 --- a/ndb/include/kernel/signaldata/TcKeyConf.hpp +++ b/ndb/include/kernel/signaldata/TcKeyConf.hpp @@ -111,7 +111,7 @@ inline void TcKeyConf::setNoOfOperations(Uint32 & confInfo, Uint32 noOfOps){ ASSERT_MAX(noOfOps, 65535, "TcKeyConf::setNoOfOperations"); - confInfo = (confInfo & 0xFFFF) | noOfOps; + confInfo = (confInfo & 0xFFFF0000) | noOfOps; } inline diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h index 9ad0967854f..d3bb44c1523 100644 --- a/ndb/include/mgmapi/mgmapi_config_parameters.h +++ b/ndb/include/mgmapi/mgmapi_config_parameters.h @@ -74,6 +74,8 @@ #define CFG_LOGLEVEL_GREP 146 #define CFG_LOG_DESTINATION 147 +#define CFG_DB_DISCLESS 148 + #define CFG_NODE_ARBIT_RANK 200 #define CFG_NODE_ARBIT_DELAY 201 diff --git a/ndb/src/common/mgmcommon/ConfigInfo.cpp b/ndb/src/common/mgmcommon/ConfigInfo.cpp index 1766fbe967f..c3e10dd3448 100644 --- a/ndb/src/common/mgmcommon/ConfigInfo.cpp +++ b/ndb/src/common/mgmcommon/ConfigInfo.cpp @@ -888,6 +888,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { 1, 0x7FFFFFFF }, + + { + CFG_DB_DISCLESS, + "Discless", + "DB", + "Run wo/ disk", + ConfigInfo::USED, + true, + ConfigInfo::BOOL, + 0, + 0, + 1}, + { CFG_DB_ARBIT_TIMEOUT, "ArbitrationTimeout", diff --git a/ndb/src/kernel/SimBlockList.cpp b/ndb/src/kernel/SimBlockList.cpp index bc6262e0723..c41b17e1919 100644 --- a/ndb/src/kernel/SimBlockList.cpp +++ b/ndb/src/kernel/SimBlockList.cpp @@ -72,14 +72,15 @@ SimBlockList::load(const Configuration & conf){ SimulatedBlock * fs = 0; { - char buf[100]; - if(NdbEnv_GetEnv("NDB_NOFS", buf, 100) == 0){ - fs = new (A_VALUE) Ndbfs(conf); - } else { + Uint32 dl; + const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator(); + if(p && !ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl){ fs = new (A_VALUE) VoidFs(conf); + } else { + fs = new (A_VALUE) Ndbfs(conf); } } - + theList[0] = new (A_VALUE) Dbacc(conf); theList[1] = new (A_VALUE) Cmvmi(conf); theList[2] = fs; diff --git a/sql-common/client.c b/sql-common/client.c index 962faf5cbe1..61ffd2b52e6 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -63,7 +63,6 @@ my_bool net_flush(NET *net); #include "mysqld_error.h" #include "errmsg.h" #include -#include #if defined(THREAD) && !defined(__WIN__) #include /* because of signal() */ #endif /* defined(THREAD) && !defined(__WIN__) */ diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 619c05711c4..133ebc87377 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1748,14 +1748,14 @@ innobase_mysql_cmp( } } - /* Starting from 4.1.3 we use strnncollsp() in comparisons of - non-latin1_swedish_ci strings. NOTE that the collation order - changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users - having indexes on such data need to rebuild their tables! */ + /* Starting from 4.1.3, we use strnncollsp() in comparisons of + non-latin1_swedish_ci strings. NOTE that the collation order + changes then: 'b\0\0...' is ordered BEFORE 'b ...'. Users + having indexes on such data need to rebuild their tables! */ ret = charset->coll->strnncollsp(charset, - a, a_length, - b, b_length); + a, a_length, + b, b_length); if (ret < 0) { return(-1); } else if (ret > 0) { @@ -4336,9 +4336,8 @@ ha_innobase::analyze( } /************************************************************************** -This is currently mapped to ::analyze. A better option would be to map this -to "ALTER TABLE tablename TYPE=InnoDB", which seems to rebuild the table in -MySQL. */ +This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds +the table in MySQL. */ int ha_innobase::optimize( @@ -4346,7 +4345,7 @@ ha_innobase::optimize( THD* thd, /* in: connection thread handle */ HA_CHECK_OPT* check_opt) /* in: currently ignored */ { - return(ha_innobase::analyze(thd, check_opt)); + return(HA_ADMIN_TRY_ALTER); } /*********************************************************************** @@ -4663,22 +4662,22 @@ ha_innobase::start_stmt( prepared for an update of a row */ prebuilt->select_lock_type = LOCK_X; - } else { - if (thd->lex->sql_command == SQLCOM_SELECT - && thd->lex->lock_option == TL_READ) { - - /* For other than temporary tables, we obtain - no lock for consistent read (plain SELECT) */ + } else { + if (thd->lex->sql_command == SQLCOM_SELECT + && thd->lex->lock_option == TL_READ) { + + /* For other than temporary tables, we obtain + no lock for consistent read (plain SELECT) */ + + prebuilt->select_lock_type = LOCK_NONE; + } else { + /* Not a consistent read: use LOCK_X as the + select_lock_type value (TODO: how could we know + whether it should be LOCK_S, LOCK_X, or LOCK_NONE?) */ - prebuilt->select_lock_type = LOCK_NONE; - } else { - /* Not a consistent read: use LOCK_X as the - select_lock_type value (TODO: how could we know - whether it should be LOCK_S, LOCK_X, or LOCK_NONE?) */ - - prebuilt->select_lock_type = LOCK_X; - } - } + prebuilt->select_lock_type = LOCK_X; + } + } /* Set the MySQL flag to mark that there is an active transaction */ thd->transaction.all.innodb_active_trans = 1; @@ -5057,7 +5056,7 @@ ha_innobase::store_lock( /*********************************************************************** This function initializes the auto-inc counter if it has not been initialized yet. This function does not change the value of the auto-inc -counter if it already has been initialized. In parameter ret returns +counter if it already has been initialized. In paramete ret returns the value of the auto-inc counter. */ int @@ -5189,7 +5188,7 @@ This function stores binlog offset and flushes logs */ void innobase_store_binlog_offset_and_flush_log( /*=============================*/ - char *binlog_name, /* in: binlog name */ + char *binlog_name, /* in: binlog name */ longlong offset /* in: binlog offset */ ) { @@ -5214,5 +5213,4 @@ innobase_store_binlog_offset_and_flush_log( /* Syncronous flush of the log buffer to disk */ log_buffer_flush_to_disk(); } - #endif /* HAVE_INNOBASE_DB */ diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index c585fd9c463..4ad7633f9c3 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -239,3 +239,5 @@ int innodb_show_status(THD* thd); my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name, uint full_name_len); void innobase_release_temporary_latches(void* innobase_tid); + +void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset); diff --git a/sql/handler.h b/sql/handler.h index e7dcb97f0e8..c8d3d30aa23 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -43,6 +43,7 @@ #define HA_ADMIN_INTERNAL_ERROR -4 #define HA_ADMIN_INVALID -5 #define HA_ADMIN_REJECT -6 +#define HA_ADMIN_TRY_ALTER -7 /* Bits in table_flags() to show what database can do */ #define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record diff --git a/sql/item_create.cc b/sql/item_create.cc index 74f36de11ac..53d4f14d1ee 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -373,7 +373,7 @@ Item *create_func_space(Item *a) CHARSET_INFO *cs= current_thd->variables.collation_connection; Item *sp; - if (cs->state & MY_CS_NONTEXT) + if (cs->mbminlen > 1) { sp= new Item_string("",0,cs); if (sp) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0c5b29fc069..098ccf70861 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -361,6 +361,16 @@ longlong Item_sum_count::val_int() return (longlong) count; } + +void Item_sum_count::cleanup() +{ + DBUG_ENTER("Item_sum_count::cleanup"); + Item_sum_int::cleanup(); + used_table_cache= ~(table_map) 0; + DBUG_VOID_RETURN; +} + + /* Avgerage */ @@ -575,6 +585,15 @@ Item_sum_hybrid::val_str(String *str) } +void Item_sum_hybrid::cleanup() +{ + DBUG_ENTER("Item_sum_hybrid::cleanup"); + Item_sum::cleanup(); + used_table_cache= ~(table_map) 0; + DBUG_VOID_RETURN; +} + + Item *Item_sum_min::copy_or_same(THD* thd) { return new (&thd->mem_root) Item_sum_min(thd, this); diff --git a/sql/item_sum.h b/sql/item_sum.h index ef947900fd2..be8bb28e16b 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -172,6 +172,7 @@ class Item_sum_count :public Item_sum_int void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; } longlong val_int(); void reset_field(); + void cleanup(); void update_field(); const char *func_name() const { return "count"; } Item *copy_or_same(THD* thd); @@ -428,6 +429,7 @@ class Item_sum_hybrid :public Item_sum void min_max_update_str_field(); void min_max_update_real_field(); void min_max_update_int_field(); + void cleanup(); }; diff --git a/sql/log.cc b/sql/log.cc index e7a142230b1..47a6a4a9b4c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -31,6 +31,7 @@ #include // For test_if_number MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; +ulong sync_binlog_counter= 0; static bool test_if_number(const char *str, long *res, bool allow_wildcards); @@ -1164,6 +1165,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, } +inline bool sync_binlog(IO_CACHE *cache) +{ + return (sync_binlog_period && + (sync_binlog_period == ++sync_binlog_counter) && + (sync_binlog_counter= 0, my_sync(cache->file, MYF(MY_WME)))); +} + /* Write an event to the binary log */ @@ -1369,9 +1377,9 @@ COLLATION_CONNECTION=%lu,COLLATION_DATABASE=%lu,COLLATION_SERVER=%lu", if (file == &log_file) // we are writing to the real log (disk) { - if (flush_io_cache(file)) + if (flush_io_cache(file) || sync_binlog(file)) goto err; - + if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log)) { /* @@ -1529,7 +1537,8 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) commit_or_rollback ? 6 : 8, TRUE); qinfo.set_log_pos(this); - if (qinfo.write(&log_file) || flush_io_cache(&log_file)) + if (qinfo.write(&log_file) || flush_io_cache(&log_file) || + sync_binlog(&log_file)) goto err; } if (cache->error) // Error on read diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f9dd4ded94a..b2d21c3fb55 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -15,7 +15,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include @@ -531,7 +530,8 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, List &keys, uint order_num, ORDER *order, enum enum_duplicates handle_duplicates, - ALTER_INFO *alter_info); + ALTER_INFO *alter_info, bool do_send_ok=1); +int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); int mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, Table_ident *src_table); @@ -858,7 +858,7 @@ extern ulong max_binlog_size, max_relay_log_size; extern ulong rpl_recovery_rank, thread_cache_size; extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log; extern ulong specialflag, current_pid; -extern ulong expire_logs_days; +extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter; extern my_bool relay_log_purge; extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version, mysqld_port, dropping_tables; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7f91466bb3d..841898ac505 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -306,7 +306,7 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong max_connections,max_used_connections, max_connect_errors, max_user_connections = 0; ulong thread_id=1L,current_pid; -ulong slow_launch_threads = 0; +ulong slow_launch_threads = 0, sync_binlog_period; ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; ulong my_bind_addr; /* the address we bind to */ @@ -329,7 +329,7 @@ char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN]; char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], - max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file, + *mysqld_user,*mysqld_chroot, *opt_init_file, *opt_init_connect, *opt_init_slave, def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; @@ -3884,7 +3884,7 @@ enum options_mysqld OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, - OPT_SYNC_FRM, OPT_BDB_NOSYNC, + OPT_SYNC_FRM, OPT_SYNC_BINLOG, OPT_BDB_NOSYNC, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, @@ -4866,6 +4866,12 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1, 0}, + {"sync-binlog", OPT_SYNC_BINLOG, + "Sync the binlog to disk after every #th event. \ +#=0 (the default) does no sync. Syncing slows MySQL down", + (gptr*) &sync_binlog_period, + (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, + 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L, @@ -5243,7 +5249,6 @@ static void mysql_init_variables(void) specialflag= opened_tables= created_tmp_tables= created_tmp_disk_tables= 0; binlog_cache_use= binlog_cache_disk_use= 0; max_used_connections= slow_launch_threads = 0; - max_sort_char= 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; errmesg= 0; mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 2a5381ae478..4feb24f06b2 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -63,6 +63,11 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, static int init_failsafe_rpl_thread(THD* thd) { DBUG_ENTER("init_failsafe_rpl_thread"); + /* + thd->bootstrap is to report errors barely to stderr; if this code is + enable again one day, one should check if bootstrap is still needed (maybe + this thread has no other error reporting method). + */ thd->system_thread = thd->bootstrap = 1; thd->host_or_ip= ""; thd->client_capabilities = 0; diff --git a/sql/set_var.cc b/sql/set_var.cc index 35bcbc9ce34..590b550ac3a 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -325,6 +325,10 @@ sys_var_thd_table_type sys_table_type("table_type", &SV::table_type); sys_var_thd_storage_engine sys_storage_engine("storage_engine", &SV::table_type); +#ifdef HAVE_REPLICATION +sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period); +#endif +sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm); sys_var_long_ptr sys_table_cache_size("table_cache", &table_cache_size); sys_var_long_ptr sys_thread_cache_size("thread_cache_size", @@ -573,6 +577,10 @@ sys_var *sys_variables[]= &sys_sql_mode, &sys_sql_warnings, &sys_storage_engine, +#ifdef HAVE_REPLICATION + &sys_sync_binlog_period, +#endif + &sys_sync_frm, &sys_table_cache_size, &sys_table_type, &sys_thread_cache_size, @@ -788,6 +796,10 @@ struct show_var_st init_vars[]= { {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS}, {sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS}, +#ifdef HAVE_REPLICATION + {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS}, +#endif + {sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS}, {"table_cache", (char*) &table_cache_size, SHOW_LONG}, {sys_table_type.name, (char*) &sys_table_type, SHOW_SYS}, {sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS}, @@ -2309,6 +2321,22 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) pthread_mutex_unlock(&LOCK_active_mi); return 0; } + + +bool sys_var_sync_binlog_period::update(THD *thd, set_var *var) +{ + pthread_mutex_t *lock_log= mysql_bin_log.get_log_lock(); + sync_binlog_period= var->save_result.ulong_value; + /* + Must reset the counter otherwise it may already be beyond the new period + and so the new period will not be taken into account. Need mutex otherwise + might be cancelled by a simultanate ++ in MYSQL_LOG::write(). + */ + pthread_mutex_lock(lock_log); + sync_binlog_counter= 0; + pthread_mutex_unlock(lock_log); + return 0; +} #endif /* HAVE_REPLICATION */ bool sys_var_rand_seed1::update(THD *thd, set_var *var) diff --git a/sql/set_var.h b/sql/set_var.h index 64bdfdb718b..9bed6f01dcc 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -462,7 +462,7 @@ public: }; -#ifndef EMBEDDED_LIBRARY +#ifdef HAVE_REPLICATION class sys_var_slave_skip_counter :public sys_var { public: @@ -475,6 +475,14 @@ public: type() or value_ptr() */ }; + +class sys_var_sync_binlog_period :public sys_var_long_ptr +{ +public: + sys_var_sync_binlog_period(const char *name_arg, ulong *value_ptr) + :sys_var_long_ptr(name_arg,value_ptr) {} + bool update(THD *thd, set_var *var); +}; #endif class sys_var_rand_seed1 :public sys_var diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index b117587eb9c..29659930579 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -308,7 +308,5 @@ character-set=latin2 "Incorrect table definition; There can only be one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" "Invalid ON UPDATE clause for '%-.64s' field", "This command is not supported in the prepared statement protocol yet", -"Got NDB error %d '%-.100s'", -"Got temporary NDB error %d '%-.100s'", "Got error %d '%-.100s' from %s", "Got temporary error %d '%-.100s' from %s", diff --git a/sql/slave.cc b/sql/slave.cc index a9b598d73db..1a59e5b2b5b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2516,7 +2516,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) DBUG_ENTER("init_slave_thread"); thd->system_thread = (thd_type == SLAVE_THD_SQL) ? SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; - thd->bootstrap= 1; thd->host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e3fbfb2d0e3..889c95125c5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2184,8 +2184,19 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, !((Item_field*) item)->field) { uint elem= fields.elements; - if (insert_fields(thd,tables,((Item_field*) item)->db_name, - ((Item_field*) item)->table_name, &it)) + Item_subselect *subsel= thd->lex->current_select->master_unit()->item; + if (subsel && + subsel->substype() == Item_subselect::EXISTS_SUBS) + { + /* + It is EXISTS(SELECT * ...) and we can replace * by any constant. + + Item_int do not need fix_fields() because it is basic constant. + */ + it.replace(new Item_int("Not_used", (longlong) 1, 21)); + } + else if (insert_fields(thd,tables,((Item_field*) item)->db_name, + ((Item_field*) item)->table_name, &it)) { if (stmt) thd->restore_backup_item_arena(stmt, &backup); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f98a6b43846..b6cb61fe10e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -41,13 +41,6 @@ pthread_key(LEX*,THR_LEX); /* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 -/* - Map to default keyword characters. This is used to test if an identifer - is 'simple', in which case we don't have to do any character set conversions - on it -*/ -uchar *bin_ident_map= my_charset_bin.ident_map; - /* The following data is based on the latin1 character set, and is only used when comparing keywords @@ -566,13 +559,9 @@ int yylex(void *arg, void *yythd) else #endif { - result_state= bin_ident_map[c] ? IDENT : IDENT_QUOTED; - while (ident_map[c=yyGet()]) - { - /* If not simple character, mark that we must convert it */ - if (!bin_ident_map[c]) - result_state= IDENT_QUOTED; - } + for (result_state= c; ident_map[c= yyGet()]; result_state|= c); + /* If there were non-ASCII characters, mark that we must convert */ + result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; } length= (uint) (lex->ptr - lex->tok_start)-1; if (lex->ignore_space) @@ -674,12 +663,11 @@ int yylex(void *arg, void *yythd) } else #endif - while (ident_map[c = yyGet()]) - { - /* If not simple character, mark that we must convert it */ - if (!bin_ident_map[c]) - result_state= IDENT_QUOTED; - } + { + for (result_state=0; ident_map[c= yyGet()]; result_state|= c); + /* If there were non-ASCII characters, mark that we must convert */ + result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; + } if (c == '.' && ident_map[yyPeek()]) lex->next_state=MY_LEX_IDENT_SEP;// Next is '.' @@ -953,13 +941,11 @@ int yylex(void *arg, void *yythd) We should now be able to handle: [(global | local | session) .]variable_name */ - result_state= IDENT; - while (ident_map[c=yyGet()]) - { - /* If not simple character, mark that we must convert it */ - if (!bin_ident_map[c]) - result_state= IDENT_QUOTED; - } + + for (result_state= 0; ident_map[c= yyGet()]; result_state|= c); + /* If there were non-ASCII characters, mark that we must convert */ + result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; + if (c == '.') lex->next_state=MY_LEX_IDENT_SEP; length= (uint) (lex->ptr - lex->tok_start)-1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 384d05ad94e..f11bc9c3475 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2598,24 +2598,9 @@ unsent_create_error: check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - if (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) - { - /* Use ALTER TABLE */ - lex->create_list.empty(); - lex->key_list.empty(); - lex->col_list.empty(); - lex->alter_info.reset(); - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type=DB_TYPE_DEFAULT; - create_info.row_type=ROW_TYPE_DEFAULT; - create_info.default_table_charset=default_charset_info; - res= mysql_alter_table(thd, NullS, NullS, &create_info, - tables, lex->create_list, - lex->key_list, 0, (ORDER *) 0, - DUP_ERROR, &lex->alter_info); - } - else - res = mysql_optimize_table(thd, tables, &lex->check_opt); + res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? + mysql_recreate_table(thd, tables, 1) : + mysql_optimize_table(thd, tables, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 991fb4d5c5a..cf4f94ba966 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -24,7 +24,6 @@ #include #include #include -#include #ifdef HAVE_FCONVERT #include #endif @@ -371,7 +370,7 @@ bool String::copy(const char *str, uint32 arg_length, bool String::set_ascii(const char *str, uint32 arg_length) { - if (!(str_charset->state & MY_CS_NONTEXT)) + if (!(str_charset->mbminlen > 1)) { set(str, arg_length, str_charset); return 0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bdff1f52d04..dc838f0e685 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -858,7 +858,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->sql_type != FIELD_TYPE_VAR_STRING && !f_is_blob(sql_field->pack_flag)) || sql_field->charset == &my_charset_bin || - sql_field->charset->state & MY_CS_NONTEXT || // ucs2 doesn't work yet + sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet (ft_key_charset && sql_field->charset != ft_key_charset)) { my_printf_error(ER_BAD_FT_COLUMN,ER(ER_BAD_FT_COLUMN),MYF(0), @@ -1804,6 +1804,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->store(table_name, system_charset_info); protocol->store(operator_name, system_charset_info); +send_result_message: + + DBUG_PRINT("info", ("result_code: %d", result_code)); switch (result_code) { case HA_ADMIN_NOT_IMPLEMENTED: { @@ -1847,6 +1850,29 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, protocol->store("Invalid argument",16, system_charset_info); break; + case HA_ADMIN_TRY_ALTER: + { + /* + This is currently used only by InnoDB. ha_innobase::optimize() answers + "try with alter", so here we close the table, do an ALTER TABLE, + reopen the table and do ha_innobase::analyze() on it. + */ + close_thread_tables(thd); + TABLE_LIST *save_next= table->next; + table->next= 0; + result_code= mysql_recreate_table(thd, table, 0); + close_thread_tables(thd); + if (!result_code) // recreation went ok + { + if ((table->table= open_ltable(thd, table, lock_type)) && + ((result_code= table->table->file->analyze(thd, check_opt)) > 0)) + result_code= 0; // analyze went ok + } + result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; + table->next= save_next; + goto send_result_message; + } + default: // Probably HA_ADMIN_INTERNAL_ERROR protocol->store("error", 5, system_charset_info); protocol->store("Unknown - internal error during operation", 41 @@ -2476,7 +2502,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, List &fields, List &keys, uint order_num, ORDER *order, enum enum_duplicates handle_duplicates, - ALTER_INFO *alter_info) + ALTER_INFO *alter_info, bool do_send_ok) { TABLE *table,*new_table; int error; @@ -2633,7 +2659,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } - send_ok(thd); + if (do_send_ok) + send_ok(thd); } else { @@ -3196,7 +3223,8 @@ end_temporary: my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), (ulong) (copied + deleted), (ulong) deleted, (ulong) thd->cuted_fields); - send_ok(thd,copied+deleted,0L,tmp_name); + if (do_send_ok) + send_ok(thd,copied+deleted,0L,tmp_name); thd->some_tables_deleted=0; DBUG_RETURN(0); @@ -3346,6 +3374,39 @@ copy_data_between_tables(TABLE *from,TABLE *to, } +/* + Recreates tables by calling mysql_alter_table(). + + SYNOPSIS + mysql_recreate_table() + thd Thread handler + tables Tables to recreate + do_send_ok If we should send_ok() or leave it to caller + + RETURN + Like mysql_alter_table(). +*/ +int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, + bool do_send_ok) +{ + DBUG_ENTER("mysql_recreate_table"); + LEX *lex= thd->lex; + HA_CREATE_INFO create_info; + lex->create_list.empty(); + lex->key_list.empty(); + lex->col_list.empty(); + lex->alter_info.reset(); + bzero((char*) &create_info,sizeof(create_info)); + create_info.db_type=DB_TYPE_DEFAULT; + create_info.row_type=ROW_TYPE_DEFAULT; + create_info.default_table_charset=default_charset_info; + DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, + table_list, lex->create_list, + lex->key_list, 0, (ORDER *) 0, + DUP_ERROR, &lex->alter_info, do_send_ok)); +} + + int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) { TABLE_LIST *table; diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 7a3c4503d74..33c686677f1 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6269,6 +6269,7 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler = { + NULL, /* init */ my_strnncoll_big5, my_strnncollsp_big5, my_strnxfrm_big5, @@ -6281,6 +6282,7 @@ static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler = static MY_CHARSET_HANDLER my_charset_big5_handler= { + NULL, /* init */ ismbchar_big5, mbcharlen_big5, my_numchars_mb, @@ -6321,13 +6323,13 @@ CHARSET_INFO my_charset_big5_chinese_ci= NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_big5_handler, &my_collation_big5_chinese_ci_handler }; @@ -6348,13 +6350,13 @@ CHARSET_INFO my_charset_big5_bin= NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_big5_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 48323018cca..54fe4476ae6 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -333,6 +333,7 @@ skip: MY_COLLATION_HANDLER my_collation_8bit_bin_handler = { + NULL, /* init */ my_strnncoll_binary, my_strnncoll_binary, my_strnxfrm_bin, @@ -346,6 +347,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, @@ -386,8 +388,8 @@ CHARSET_INFO my_charset_bin = NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index dede737f361..8fde9498ed9 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -572,6 +572,7 @@ static MY_UNI_IDX idx_uni_8859_2[]={ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler = { + NULL, /* init */ my_strnncoll_czech, my_strnncollsp_czech, my_strnxfrm_czech, @@ -597,7 +598,8 @@ CHARSET_INFO my_charset_latin2_czech_ci = NULL, /* sort_order_big*/ tab_8859_2_uni, /* tab_to_uni */ idx_uni_8859_2, /* tab_from_uni */ - "","", + NULL, /* state_map */ + NULL, /* ident_map */ 4, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 2d4c68978a3..1e6931244d2 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8637,6 +8637,7 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_simple, /* strnncoll */ my_strnncollsp_simple, my_strnxfrm_simple, /* strnxfrm */ @@ -8649,6 +8650,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ ismbchar_euc_kr, mbcharlen_euc_kr, my_numchars_mb, @@ -8689,13 +8691,13 @@ CHARSET_INFO my_charset_euckr_korean_ci= NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -8716,13 +8718,13 @@ CHARSET_INFO my_charset_euckr_bin= NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c index 51a9531fbf5..baf1d319b00 100644 --- a/strings/ctype-extra.c +++ b/strings/ctype-extra.c @@ -24,20 +24,22 @@ CHARSET_INFO compiled_charsets[] = { NullS, /* cs name */ NullS, /* name */ NullS, /* comment */ - NULL, - NULL, - NULL, - NULL, + NULL, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", - 0, - 0, - 0, - 0, - 0, - NULL, - NULL + NULL, /* state_map */ + NULL, /* ident_map */ + 0, /* strxfrm_mul */ + 0, /* mbminlen */ + 0, /* mbmaxlen */ + 0, /* min_sort_ord */ + 0, /* max_sort_ord */ + NULL, /* cset handler */ + NULL /* coll handler */ } }; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 49ca736a3c2..2c5aae83769 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5688,6 +5688,7 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_simple, /* strnncoll */ my_strnncollsp_simple, my_strnxfrm_simple, /* strnxfrm */ @@ -5700,6 +5701,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ ismbchar_gb2312, mbcharlen_gb2312, my_numchars_mb, @@ -5740,13 +5742,13 @@ CHARSET_INFO my_charset_gb2312_chinese_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -5766,13 +5768,13 @@ CHARSET_INFO my_charset_gb2312_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 0273feb4c2c..aec23366ea5 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9918,6 +9918,7 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_gbk, my_strnncollsp_gbk, my_strnxfrm_gbk, @@ -9930,6 +9931,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ ismbchar_gbk, mbcharlen_gbk, my_numchars_mb, @@ -9970,13 +9972,13 @@ CHARSET_INFO my_charset_gbk_chinese_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -9996,13 +9998,13 @@ CHARSET_INFO my_charset_gbk_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index fe39303e2ac..f5e7fd8baa4 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -380,6 +380,7 @@ int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)), static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ NULL, my_mbcharlen_8bit, my_numchars_8bit, @@ -420,12 +421,13 @@ CHARSET_INFO my_charset_latin1= NULL, /* sort_order_big*/ cs_to_uni, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_8bit_simple_ci_handler }; @@ -673,6 +675,7 @@ void my_hash_sort_latin1_de(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_german2_ci_handler= { + NULL, /* init */ my_strnncoll_latin1_de, my_strnncollsp_latin1_de, my_strnxfrm_latin1_de, @@ -699,12 +702,13 @@ CHARSET_INFO my_charset_latin1_german2_ci= NULL, /* sort_order_big*/ cs_to_uni, /* tab_to_uni */ NULL, /* tab_from_uni */ - "","", + NULL, /* state_map */ + NULL, /* ident_map */ 2, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 247, /* max_sort_char */ &my_charset_handler, &my_collation_german2_ci_handler }; @@ -725,13 +729,13 @@ CHARSET_INFO my_charset_latin1_bin= NULL, /* sort_order_big*/ cs_to_uni, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_8bit_bin_handler }; diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 9b02cd3b3da..c143994dbc3 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -512,6 +512,7 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs, MY_COLLATION_HANDLER my_collation_mb_bin_handler = { + NULL, /* init */ my_strnncoll_mb_bin, my_strnncoll_mb_bin, my_strnxfrm_mb_bin, diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index ba1fc1c424a..0d30ad28a20 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -20,7 +20,6 @@ #include #include "stdarg.h" -#include "assert.h" int my_strnxfrm_simple(CHARSET_INFO * cs, @@ -1143,8 +1142,133 @@ skip: } +typedef struct +{ + int nchars; + MY_UNI_IDX uidx; +} uni_idx; + +#define PLANE_SIZE 0x100 +#define PLANE_NUM 0x100 +#define PLANE_NUMBER(x) (((x)>>8) % PLANE_NUM) + +static int pcmp(const void * f, const void * s) +{ + const uni_idx *F= (const uni_idx*) f; + const uni_idx *S= (const uni_idx*) s; + int res; + + if (!(res=((S->nchars)-(F->nchars)))) + res=((F->uidx.from)-(S->uidx.to)); + return res; +} + +static my_bool create_fromuni(CHARSET_INFO *cs, void *(*alloc)(uint)) +{ + uni_idx idx[PLANE_NUM]; + int i,n; + + /* Clear plane statistics */ + bzero(idx,sizeof(idx)); + + /* Count number of characters in each plane */ + for (i=0; i< 0x100; i++) + { + uint16 wc=cs->tab_to_uni[i]; + int pl= PLANE_NUMBER(wc); + + if (wc || !i) + { + if (!idx[pl].nchars) + { + idx[pl].uidx.from=wc; + idx[pl].uidx.to=wc; + }else + { + idx[pl].uidx.from=wcidx[pl].uidx.to?wc:idx[pl].uidx.to; + } + idx[pl].nchars++; + } + } + + /* Sort planes in descending order */ + qsort(&idx,PLANE_NUM,sizeof(uni_idx),&pcmp); + + for (i=0; i < PLANE_NUM; i++) + { + int ch,numchars; + + /* Skip empty plane */ + if (!idx[i].nchars) + break; + + numchars=idx[i].uidx.to-idx[i].uidx.from+1; + if (!(idx[i].uidx.tab=(uchar*) alloc(numchars * sizeof(*idx[i].uidx.tab)))) + return TRUE; + + bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab)); + + for (ch=1; ch < PLANE_SIZE; ch++) + { + uint16 wc=cs->tab_to_uni[ch]; + if (wc >= idx[i].uidx.from && wc <= idx[i].uidx.to && wc) + { + int ofs= wc - idx[i].uidx.from; + idx[i].uidx.tab[ofs]= ch; + } + } + } + + /* Allocate and fill reverse table for each plane */ + n=i; + if (!(cs->tab_from_uni= (MY_UNI_IDX*) alloc(sizeof(MY_UNI_IDX)*(n+1)))) + return TRUE; + + for (i=0; i< n; i++) + cs->tab_from_uni[i]= idx[i].uidx; + + /* Set end-of-list marker */ + bzero(&cs->tab_from_uni[i],sizeof(MY_UNI_IDX)); + return FALSE; +} + +static my_bool my_cset_init_8bit(CHARSET_INFO *cs, void *(*alloc)(uint)) +{ + return create_fromuni(cs, alloc); +} + +static void set_max_sort_char(CHARSET_INFO *cs) +{ + uchar max_char; + uint i; + + if (!cs->sort_order) + return; + + max_char=cs->sort_order[(uchar) cs->max_sort_char]; + for (i= 0; i < 256; i++) + { + if ((uchar) cs->sort_order[i] > max_char) + { + max_char=(uchar) cs->sort_order[i]; + cs->max_sort_char= i; + } + } +} + +static my_bool my_coll_init_simple(CHARSET_INFO *cs, + void *(*alloc)(uint) __attribute__((unused))) +{ + set_max_sort_char(cs); + return FALSE; +} + + + MY_CHARSET_HANDLER my_charset_8bit_handler= { + my_cset_init_8bit, NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, @@ -1171,6 +1295,7 @@ MY_CHARSET_HANDLER my_charset_8bit_handler= MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler = { + my_coll_init_simple, /* init */ my_strnncoll_simple, my_strnncollsp_simple, my_strnxfrm_simple, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 22c58360348..656c903c7a1 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4534,6 +4534,7 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_sjis, my_strnncollsp_sjis, my_strnxfrm_sjis, @@ -4547,6 +4548,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ ismbchar_sjis, mbcharlen_sjis, my_numchars_mb, @@ -4587,13 +4589,13 @@ CHARSET_INFO my_charset_sjis_japanese_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -4613,13 +4615,13 @@ CHARSET_INFO my_charset_sjis_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index b2b1ab98352..a0ba1a266ea 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -906,6 +906,7 @@ int my_wc_mb_tis620(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_tis620, my_strnncollsp_tis620, my_strnxfrm_tis620, @@ -918,6 +919,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, @@ -959,8 +961,8 @@ CHARSET_INFO my_charset_tis620_thai_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 4, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ @@ -985,8 +987,8 @@ CHARSET_INFO my_charset_tis620_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 75e2c06eec2..9997e2772e2 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -6521,6 +6521,104 @@ NULL ,page0F9data,page0FAdata,page0FBdata, page0FCdata,page0FDdata,page0FEdata,page0FFdata }; +/* + Some sources treat LETTER A WITH DIARESIS (00E4,00C4) + secondary greater than LETTER AE (00E6,00C6). + http://www.evertype.com/alphabets/icelandic.pdf + http://developer.mimer.com/collations/charts/icelandic.htm + + Other sources do not provide any special rules + for LETTER A WITH DIARESIS: + http://www.omniglot.com/writing/icelandic.htm + http://en.wikipedia.org/wiki/Icelandic_alphabet + http://oss.software.ibm.com/icu/charts/collation/is.html + + Let's go the first way. +*/ + +static const char icelandic[]= + "& A < \\u00E1 <<< \\u00C1 " + "& D < \\u00F0 <<< \\u00D0 " + "& E < \\u00E9 <<< \\u00C9 " + "& I < \\u00ED <<< \\u00CD " + "& O < \\u00F3 <<< \\u00D3 " + "& U < \\u00FA <<< \\u00DA " + "& Y < \\u00FD <<< \\u00DD " + "& Z < \\u00FE <<< \\u00DE " + "< \\u00E6 <<< \\u00C6 << \\u00E4 <<< \\u00C4 " + "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 " + "< \\u00E5 <<< \\u00C5 "; + +/* + Some sources treat I and Y primary different. + Other sources treat I and Y the same on primary level. + We'll go the first way. +*/ + +static const char latvian[]= + "& C < \\u010D <<< \\u010C " + "& G < \\u0123 <<< \\u0122 " + "& I < \\u0079 <<< \\u0059 " + "& K < \\u0137 <<< \\u0136 " + "& L < \\u013C <<< \\u013B " + "& N < \\u0146 <<< \\u0145 " + "& R < \\u0157 <<< \\u0156 " + "& S < \\u0161 <<< \\u0160 " + "& Z < \\u017E <<< \\u017D "; + + +static const char romanian[]= + "& A < \\u0103 <<< \\u0102 < \\u00E2 <<< \\u00C2 " + "& I < \\u00EE <<< \\u00CE " + "& S < \\u0219 <<< \\u0218 << \\u015F <<< \\u015E " + "& T < \\u021B <<< \\u021A << \\u0163 <<< \\u0162 "; + +static const char slovenian[]= + "& C < \\u010D <<< \\u010C " + "& S < \\u0161 <<< \\u0160 " + "& Z < \\u017E <<< \\u017D "; + + +static const char polish[]= + "& A < \\u0105 <<< \\u0104 " + "& C < \\u0107 <<< \\u0106 " + "& E < \\u0119 <<< \\u0118 " + "& L < \\u0142 <<< \\u0141 " + "& N < \\u0144 <<< \\u0143 " + "& O < \\u00F3 <<< \\u00D3 " + "& S < \\u015B <<< \\u015A " + "& Z < \\u017A <<< \\u017B "; + +static const char estonian[]= + "& S < \\u0161 <<< \\u0160 " + " < \\u007A <<< \\u005A " + " < \\u017E <<< \\u017D " + "& W < \\u00F5 <<< \\u00D5 " + "< \\u00E4 <<< \\u00C4 " + "< \\u00F6 <<< \\u00D6 " + "< \\u00FC <<< \\u00DC "; + +static const char spanish[]= "& N < \\u00F1 <<< \\u00D1 "; + +/* + Some sources treat V and W as similar on primary level. + We'll treat V and W as different on primary level. +*/ + +static const char swedish[]= + "& Y <<\\u00FC <<< \\u00DC " + "& Z < \\u00E5 <<< \\u00C5 " + "< \\u00E4 <<< \\u00C4 << \\u00E6 <<< \\u00C6 " + "< \\u00F6 <<< \\u00D6 << \\u00F8 <<< \\u00D8 "; + +static const char turkish[]= + "& C < \\u00E7 <<< \\u00C7 " + "& G < \\u011F <<< \\u011E " + "& H < \\u0131 <<< \\u0049 " + "& O < \\u00F6 <<< \\u00D6 " + "& S < \\u015F <<< \\u015E " + "& U < \\u00FC <<< \\u00DC "; + /* Unicode Collation Algorithm: @@ -7036,8 +7134,464 @@ int my_wildcmp_uca(CHARSET_INFO *cs, } +/* + Collation language is implemented according to + subset of ICU Collation Customization (tailorings): + http://oss.software.ibm.com/icu/userguide/Collate_Customization.html + + Collation language elements: + Delimiters: + space - skipped + + := A-Z | a-z | \uXXXX + + Shift command: + := & - reset at this letter. + + Diff command: + := < - Identifies a primary difference. + := << - Identifies a secondary difference. + := <<< - Idenfifies a tertiary difference. + + + Collation rules: + := { } + + := + | + | + | + + := [ ] + + An example, Polish collation: + + &A < \u0105 <<< \u0104 + &C < \u0107 <<< \u0106 + &E < \u0119 <<< \u0118 + &L < \u0142 <<< \u0141 + &N < \u0144 <<< \u0143 + &O < \u00F3 <<< \u00D3 + &S < \u015B <<< \u015A + &Z < \u017A <<< \u017B +*/ + + +typedef enum my_coll_lexem_num_en +{ + MY_COLL_LEXEM_EOF = 0, + MY_COLL_LEXEM_DIFF = 1, + MY_COLL_LEXEM_SHIFT = 4, + MY_COLL_LEXEM_CHAR = 5, + MY_COLL_LEXEM_ERROR = 6 +} my_coll_lexem_num; + + +typedef struct my_coll_lexem_st +{ + const char *beg; + const char *end; + const char *prev; + int diff; + int code; +} MY_COLL_LEXEM; + + +/* + Initialize collation rule lexical anilizer + + SYNOPSIS + my_coll_lexem_init + lexem Lex analizer to init + str Const string to parse + strend End of the string + USAGE + + RETURN VALUES + N/A +*/ + +static void my_coll_lexem_init(MY_COLL_LEXEM *lexem, + const char *str, const char *strend) +{ + lexem->beg= str; + lexem->prev= str; + lexem->end= strend; + lexem->diff= 0; + lexem->code= 0; +} + + +/* + Print collation customization expression parse error, with context. + + SYNOPSIS + my_coll_lexem_print_error + lexem Lex analizer to take context from + errstr sting to write error to + errsize errstr size + txt error message + USAGE + + RETURN VALUES + N/A +*/ + +static void my_coll_lexem_print_error(MY_COLL_LEXEM *lexem, + char *errstr, size_t errsize, + const char *txt) +{ + char tail[30]; + size_t len= lexem->end - lexem->prev; + strmake (tail, lexem->prev, min(len, sizeof(tail)-1)); + errstr[errsize-1]= '\0'; + my_snprintf(errstr,errsize-1,"%s at '%s'", txt, tail); +} + + +/* + Convert a hex digit into its numeric value + + SYNOPSIS + ch2x + ch hex digit to convert + USAGE + + RETURN VALUES + an integer value in the range 0..15 + -1 on error +*/ + +static int ch2x(int ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + + if (ch >= 'a' && ch <= 'f') + return 10 + ch - 'a'; + + if (ch >= 'A' && ch <= 'F') + return 10 + ch - 'A'; + + return -1; +} + + +/* + Collation language lexical parser: + Scans the next lexem. + + SYNOPSIS + my_coll_lexem_next + lexem Lex analizer, previously initialized by + my_coll_lexem_init. + USAGE + Call this function in a loop + + RETURN VALUES + Lexem number: eof, diff, shift, char or error. +*/ + +static my_coll_lexem_num my_coll_lexem_next(MY_COLL_LEXEM *lexem) +{ + for ( ;lexem->beg < lexem->end ; lexem->beg++) + { + lexem->prev= lexem->beg; + if (lexem->beg[0] == ' ' || lexem->beg[0] == '\t' || + lexem->beg[0] == '\r' || lexem->beg[0] == '\n') + continue; + + if (lexem->beg[0] == '&') + { + lexem->beg++; + return MY_COLL_LEXEM_SHIFT; + } + + if (lexem->beg[0] == '<') + { + for (lexem->beg++, lexem->diff=1; + (lexem->beg < lexem->end) && + (lexem->beg[0] == '<') && (lexem->diff<3); + lexem->beg++, lexem->diff++); + return MY_COLL_LEXEM_DIFF; + } + + if ((lexem->beg[0] >= 'a' && lexem->beg[0] <= 'z') || + (lexem->beg[0] >= 'A' && lexem->beg[0] <= 'Z')) + { + lexem->code= lexem->beg[0]; + lexem->beg++; + return MY_COLL_LEXEM_CHAR; + } + + if ((lexem->beg[0] == '\\') && + (lexem->beg+2 < lexem->end) && + (lexem->beg[1] == 'u')) + { + int ch; + + lexem->code= 0; + for (lexem->beg+=2; + (lexem->beg < lexem->end) && ((ch= ch2x(lexem->beg[0])) >= 0) ; + lexem->beg++) + { + lexem->code= (lexem->code << 4) + ch; + } + return MY_COLL_LEXEM_CHAR; + } + + return MY_COLL_LEXEM_ERROR; + } + return MY_COLL_LEXEM_EOF; +} + + +/* + Collation rule item +*/ + +typedef struct my_coll_rule_item_st +{ + uint base; /* Base character */ + uint curr; /* Current character */ + int diff[3]; /* Primary, Secondary and Tertiary difference */ +} MY_COLL_RULE; + + +/* + Collation language syntax parser. + Uses lexical parser. + + SYNOPSIS + my_coll_rule_parse + rule Collation rule list to load to. + str A string containin collation language expression. + strend End of the string. + USAGE + + RETURN VALUES + 0 - OK + 1 - ERROR, e.g. too many items. +*/ + +static int my_coll_rule_parse(MY_COLL_RULE *rule, size_t mitems, + const char *str, const char *strend, + char *errstr, size_t errsize) +{ + MY_COLL_LEXEM lexem; + my_coll_lexem_num lexnum; + my_coll_lexem_num prevlexnum= MY_COLL_LEXEM_ERROR; + MY_COLL_RULE item; + int state= 0; + size_t nitems= 0; + + /* Init all variables */ + errstr[0]= '\0'; + bzero(&item, sizeof(item)); + my_coll_lexem_init(&lexem, str, strend); + + while ((lexnum= my_coll_lexem_next(&lexem))) + { + if (lexnum == MY_COLL_LEXEM_ERROR) + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Unknown character"); + return -1; + } + + switch (state) { + case 0: + if (lexnum != MY_COLL_LEXEM_SHIFT) + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& expected"); + return -1; + } + prevlexnum= lexnum; + state= 2; + continue; + + case 1: + if (lexnum != MY_COLL_LEXEM_SHIFT && lexnum != MY_COLL_LEXEM_DIFF) + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"& or < expected"); + return -1; + } + prevlexnum= lexnum; + state= 2; + continue; + + case 2: + if (lexnum != MY_COLL_LEXEM_CHAR) + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"character expected"); + return -1; + } + + if (prevlexnum == MY_COLL_LEXEM_SHIFT) + { + item.base= lexem.code; + item.diff[0]= 0; + item.diff[1]= 0; + item.diff[2]= 0; + } + else if (prevlexnum == MY_COLL_LEXEM_DIFF) + { + item.curr= lexem.code; + if (lexem.diff == 3) + { + item.diff[2]++; + } + else if (lexem.diff == 2) + { + item.diff[1]++; + item.diff[2]= 0; + } + else if (lexem.diff == 1) + { + item.diff[0]++; + item.diff[1]= 0; + item.diff[2]= 0; + } + if (nitems >= mitems) + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Too many rules"); + return -1; + } + rule[nitems++]= item; + } + else + { + my_coll_lexem_print_error(&lexem,errstr,errsize-1,"Should never happen"); + return -1; + } + state= 1; + continue; + } + } + return (size_t) nitems; +} + +#define MY_MAX_COLL_RULE 64 + +/* + This function copies an UCS2 collation from + the default Unicode Collation Algorithm (UCA) + weights applying tailorings, i.e. a set of + alternative weights for some characters. + + The default UCA weights are stored in my_charset_ucs2_general_uca. + They consist of 256 pages, 256 character each. + + If a page is not overwritten by tailoring rules, + it is copies as is from UCA as is. + + If a page contains some overwritten characters, it is + allocated. Untouched characters are copied from the + default weights. +*/ + +static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(uint)) +{ + MY_COLL_RULE rule[MY_MAX_COLL_RULE]; + char errstr[128]; + uchar *newlengths; + uint16 **newweights; + const uchar *deflengths= my_charset_ucs2_general_uca.sort_order; + uint16 **defweights= my_charset_ucs2_general_uca.sort_order_big; + int rc, i; + + if (!cs->tailoring) + return 1; + + /* Parse ICU Collation Customization expression */ + if ((rc= my_coll_rule_parse(rule, MY_MAX_COLL_RULE, + cs->tailoring, + cs->tailoring + strlen(cs->tailoring), + errstr, sizeof(errstr))) <= 0) + { + /* + TODO: add error message reporting. + printf("Error: %d '%s'\n", rc, errstr); + */ + return 1; + } + + if (!(newweights= (uint16**) alloc(256*sizeof(uint16*)))) + return 1; + bzero(newweights, 256*sizeof(uint16*)); + + if (!(newlengths= (uchar*) alloc(256))) + return 1; + + memcpy(newlengths, deflengths, 256); + + /* + Calculate maximum lenghts for the pages + which will be overwritten. + */ + for (i=0; i < rc; i++) + { + uint pageb= (rule[i].base >> 8) & 0xFF; + uint pagec= (rule[i].curr >> 8) & 0xFF; + + if (newlengths[pagec] < deflengths[pageb]) + newlengths[pagec]= deflengths[pageb]; + } + + for (i=0; i < rc; i++) + { + uint pageb= (rule[i].base >> 8) & 0xFF; + uint pagec= (rule[i].curr >> 8) & 0xFF; + uint chb, chc; + + if (!newweights[pagec]) + { + /* Alloc new page and copy the default UCA weights */ + uint size= 256*newlengths[pagec]*sizeof(uint16); + + if (!(newweights[pagec]= (uint16*) alloc(size))) + return 1; + bzero((void*) newweights[pagec], size); + + for (chc=0 ; chc < 256; chc++) + { + memcpy(newweights[pagec] + chc*newlengths[pagec], + defweights[pagec] + chc*deflengths[pagec], + deflengths[pagec]*sizeof(uint16)); + } + } + + /* + Aply the alternative rule: + shift to the base character and primary difference. + */ + chc= rule[i].curr & 0xFF; + chb= rule[i].base & 0xFF; + memcpy(newweights[pagec] + chc*newlengths[pagec], + defweights[pageb] + chb*deflengths[pageb], + deflengths[pageb]*sizeof(uint16)); + /* Apply primary difference */ + newweights[pagec][chc*newlengths[pagec]]+= rule[i].diff[0]; + } + + /* Copy non-overwritten pages from the default UCA weights */ + for (i= 0; i < 256 ; i++) + if (!newweights[i]) + newweights[i]= defweights[i]; + + cs->sort_order= newlengths; + cs->sort_order_big= newweights; + + return 0; +} + +static my_bool my_coll_init_uca(CHARSET_INFO *cs, void *(*alloc)(uint)) +{ + return create_tailoring(cs, alloc); +} + MY_COLLATION_HANDLER my_collation_ucs2_uca_handler = { + my_coll_init_uca, /* init */ my_strnncoll_uca, my_strnncollsp_uca, my_strnxfrm_uca, @@ -7051,9 +7605,9 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler = CHARSET_INFO my_charset_ucs2_general_uca= { 45,0,0, /* number */ - MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT, + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, "ucs2", /* cs name */ - "ucs2_general_uca", /* name */ + "ucs2_uca_ci", /* name */ "", /* comment */ NULL, /* tailoring */ NULL, /* ctype */ @@ -7063,8 +7617,8 @@ CHARSET_INFO my_charset_ucs2_general_uca= uca_weight, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 8, /* strxfrm_multiply */ 2, /* mbminlen */ 2, /* mbmaxlen */ @@ -7075,4 +7629,238 @@ CHARSET_INFO my_charset_ucs2_general_uca= }; +CHARSET_INFO my_charset_ucs2_icelandic_uca_ci= +{ + 128,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_icelandic_ci",/* name */ + "", /* comment */ + icelandic, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_latvian_uca_ci= +{ + 129,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_latvian_ci", /* name */ + "", /* comment */ + latvian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_romanian_uca_ci= +{ + 130,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_romanian_ci", /* name */ + "", /* comment */ + romanian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_slovenian_uca_ci= +{ + 131,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_slovenian_ci",/* name */ + "", /* comment */ + slovenian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_polish_uca_ci= +{ + 132,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_polish_ci", /* name */ + "", /* comment */ + polish, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_estonian_uca_ci= +{ + 133,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_estonian_ci", /* name */ + "", /* comment */ + estonian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_spanish_uca_ci= +{ + 134,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_spanish_ci", /* name */ + "", /* comment */ + spanish, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_swedish_uca_ci= +{ + 135,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_swedish_ci", /* name */ + "", /* comment */ + swedish, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + +CHARSET_INFO my_charset_ucs2_turkish_uca_ci= +{ + 136,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_turkish_ci", /* name */ + "", /* comment */ + turkish, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + #endif diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index d1ba63b8b84..f05e85a9d88 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -312,7 +312,6 @@ static int my_mbcharlen_ucs2(CHARSET_INFO *cs __attribute__((unused)) , #include #include -#include static int my_vsnprintf_ucs2(char *dst, uint n, const char* fmt, va_list ap) { @@ -1373,6 +1372,7 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs, static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler = { + NULL, /* init */ my_strnncoll_ucs2, my_strnncoll_ucs2, my_strnxfrm_ucs2, @@ -1386,6 +1386,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler = static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = { + NULL, /* init */ my_strnncoll_ucs2_bin, my_strnncoll_ucs2_bin, my_strnxfrm_ucs2_bin, @@ -1399,6 +1400,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = MY_CHARSET_HANDLER my_charset_ucs2_handler= { + NULL, /* init */ my_ismbchar_ucs2, /* ismbchar */ my_mbcharlen_ucs2, /* mbcharlen */ my_numchars_ucs2, @@ -1427,7 +1429,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler= CHARSET_INFO my_charset_ucs2_general_ci= { 35,0,0, /* number */ - MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONTEXT, + MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE, "ucs2", /* cs name */ "ucs2_general_ci", /* name */ "", /* comment */ @@ -1439,8 +1441,8 @@ CHARSET_INFO my_charset_ucs2_general_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 2, /* mbminlen */ 2, /* mbmaxlen */ @@ -1453,7 +1455,7 @@ CHARSET_INFO my_charset_ucs2_general_ci= CHARSET_INFO my_charset_ucs2_bin= { 90,0,0, /* number */ - MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE|MY_CS_NONTEXT, + MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE, "ucs2", /* cs name */ "ucs2_bin", /* name */ "", /* comment */ @@ -1465,8 +1467,8 @@ CHARSET_INFO my_charset_ucs2_bin= NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 2, /* mbminlen */ 2, /* mbmaxlen */ diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 668dc7beb8b..7f88a16cac6 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8423,6 +8423,7 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e) static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple, my_strnxfrm_simple, /* strnxfrm */ @@ -8435,14 +8436,15 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ ismbchar_ujis, mbcharlen_ujis, my_numchars_mb, my_charpos_mb, my_well_formed_len_mb, my_lengthsp_8bit, - my_mb_wc_euc_jp, /* mb_wc */ - my_wc_mb_euc_jp, /* wc_mb */ + my_mb_wc_euc_jp, /* mb_wc */ + my_wc_mb_euc_jp, /* wc_mb */ my_caseup_str_mb, my_casedn_str_mb, my_caseup_mb, @@ -8476,13 +8478,13 @@ CHARSET_INFO my_charset_ujis_japanese_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 3, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -8503,13 +8505,13 @@ CHARSET_INFO my_charset_ujis_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 3, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 2d0feb1c890..02918fcd10f 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2045,6 +2045,7 @@ static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c) static MY_COLLATION_HANDLER my_collation_ci_handler = { + NULL, /* init */ my_strnncoll_utf8, my_strnncollsp_utf8, my_strnxfrm_utf8, @@ -2057,6 +2058,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { + NULL, /* init */ my_ismbchar_utf8, my_mbcharlen_utf8, my_numchars_mb, @@ -2098,13 +2100,13 @@ CHARSET_INFO my_charset_utf8_general_ci= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 3, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_ci_handler }; @@ -2125,13 +2127,13 @@ CHARSET_INFO my_charset_utf8_bin= NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ NULL, /* sort_order_big*/ - "", - "", + NULL, /* state_map */ + NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* mbminlen */ 3, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ &my_charset_handler, &my_collation_mb_bin_handler }; diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index bb287eb695e..a2c5768b16c 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -605,6 +605,7 @@ my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)), static MY_COLLATION_HANDLER my_collation_czech_ci_handler = { + NULL, /* init */ my_strnncoll_win1250ch, my_strnncollsp_win1250ch, my_strnxfrm_win1250ch, @@ -631,7 +632,8 @@ CHARSET_INFO my_charset_cp1250_czech_ci = NULL, /* sort_order_big*/ tab_cp1250_uni, /* tab_to_uni */ idx_uni_cp1250, /* tab_from_uni */ - "","", + NULL, /* state_map */ + NULL, /* ident_map */ 2, /* strxfrm_multiply */ 1, /* mbminlen */ 1, /* mbmaxlen */ diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index dc03c130dcd..784c4762724 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -18,7 +18,6 @@ #include #include #include -#include /* Limited snprintf() implementations diff --git a/tests/client_test.c b/tests/client_test.c index a2703478036..223f9edeebf 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -9869,6 +9869,49 @@ static void test_bug4026() mysql_stmt_close(stmt); } + +static void test_bug4079() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + const char *stmt_text; + unsigned long res; + int rc; + + myheader("test_bug4079"); + + /* Create and fill table */ + mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + mysql_query(mysql, "CREATE TABLE t1 (a int)"); + mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2)"); + + /* Prepare erroneous statement */ + stmt= mysql_stmt_init(mysql); + stmt_text= "SELECT 1 < (SELECT a FROM t1)"; + + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + /* Execute the select statement */ + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + /* Bind input buffers */ + bzero(bind, sizeof(bind)); + + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char*) &res; + + mysql_stmt_bind_result(stmt, bind); + + rc= mysql_stmt_fetch(stmt); + assert(rc != 0 && rc != MYSQL_NO_DATA); + printf("Got error from mysql_stmt_fetch (as expected):\n%s\n", + mysql_stmt_error(stmt)); + /* buggy version of libmysql hanged up here */ + mysql_stmt_close(stmt); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -10162,6 +10205,7 @@ int main(int argc, char **argv) test_ps_i18n(); /* test for i18n support in binary protocol */ test_bug3796(); /* test for select concat(?, ) */ test_bug4026(); /* test microseconds precision of time types */ + test_bug4079(); /* erroneous subquery in prepared statement */ /* XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.