From f974c735cf419b56824ed4e5f27dfe182cf50e03 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Wed, 19 Jun 2002 17:52:44 +0300 Subject: EXISTS type of subselect more correct parameters in result creation script --- mysql-test/create-test-result | 2 +- mysql-test/r/subselect.result | 7 +++ mysql-test/t/subselect.test | 2 + sql/item_subselect.cc | 121 +++++++++++++++++++++++++++++------------- sql/item_subselect.h | 89 ++++++++++++++++++++++++------- sql/sql_class.cc | 43 ++++++++++----- sql/sql_class.h | 23 ++++++-- sql/sql_yacc.yy | 27 +++++++--- 8 files changed, 235 insertions(+), 79 deletions(-) diff --git a/mysql-test/create-test-result b/mysql-test/create-test-result index bfd64f32fc5..a50b4c87641 100755 --- a/mysql-test/create-test-result +++ b/mysql-test/create-test-result @@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result touch $result_file echo "Running the test case against empty file, will fail, but don't worry" -./mysql-test-run --do-test=$test_name +./mysql-test-run --local $test_name reject_file=$result_file.reject diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 2e40d0a92d8..37a66993ef2 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -67,4 +67,11 @@ b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) 8 7.5000 8 6.0000 9 5.5000 +select * from t3 where exists (select * from t2 where t2.b=t3.a); +a +7 +select * from t3 where not exists (select * from t2 where t2.b=t3.a); +a +6 +3 drop table t1,t2,t3,t4; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c94522fde8f..78300dc3e09 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -26,4 +26,6 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1); select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; +select * from t3 where exists (select * from t2 where t2.b=t3.a); +select * from t3 where not exists (select * from t2 where t2.b=t3.a); drop table t1,t2,t3,t4; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c2349ed414c..d8f9cf40d50 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -35,12 +35,13 @@ SUBSELECT TODO: #include "mysql_priv.h" #include "sql_select.h" -Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex): +Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, + select_subselect *result): assigned(0), executed(0), optimized(0), error(0) { DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); - result= new select_subselect(this); + this->result= result; SELECT_LEX_UNIT *unit= select_lex->master_unit(); unit->offset_limit_cnt= unit->global_parameters->offset_limit; unit->select_limit_cnt= unit->global_parameters->select_limit+ @@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex): select_lex->options&= ~OPTION_FOUND_ROWS; join= new JOIN(thd, select_lex->item_list, select_lex->options, result); this->select_lex= select_lex; - maybe_null= 1; + assign_null(); /* item value is NULL if select_subselect not changed this value (i.e. some rows will be found returned) */ - assign_null(); + null_value= 1; DBUG_VOID_RETURN; } -Item::Type Item_subselect::type() const -{ - return SUBSELECT_ITEM; -} - -double Item_subselect::val () -{ - if (exec()) - return 0; - return real_value; -} - -longlong Item_subselect::val_int () -{ - if (exec()) - return 0; - return int_value; -} - -String *Item_subselect::val_str (String *str) -{ - if (exec() || null_value) - return 0; - return &str_value; -} - void Item_subselect::make_field (Send_field *tmp_field) { if (null_value) @@ -108,9 +83,9 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) //TODO: subselects in having do not suported now my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0)); return 1; - } + } // Is it one field subselect? - if (select_lex->item_list.elements != 1) + if (select_lex->item_list.elements > max_columns) { my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); return 1; @@ -131,13 +106,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) int Item_subselect::exec() { + DBUG_ENTER("Item_subselect::exec"); if (!optimized) { optimized=1; if (join->optimize()) { executed= 1; - return (join->error?join->error:1); + DBUG_RETURN(join->error?join->error:1); } } if (join->select_lex->depended && executed) @@ -145,7 +121,7 @@ int Item_subselect::exec() if (join->reinit()) { error= 1; - return 1; + DBUG_RETURN(1); } assign_null(); executed= assigned= 0; @@ -157,7 +133,80 @@ int Item_subselect::exec() join->exec(); join->thd->lex.select= save_select; executed= 1; - return join->error; + DBUG_RETURN(join->error); } - return 0; + DBUG_RETURN(0); } + +inline table_map Item_subselect::used_tables() const +{ + return (table_map) select_lex->depended ? 1L : 0L; +} + +Item_singleval_subselect::Item_singleval_subselect(THD *thd, + st_select_lex *select_lex): + Item_subselect(thd, select_lex, new select_singleval_subselect(this)) +{ + max_columns= 1; + maybe_null= 1; +} + +Item::Type Item_subselect::type() const +{ + return SUBSELECT_ITEM; +} + +double Item_singleval_subselect::val () +{ + if (exec()) + return 0; + return real_value; +} + +longlong Item_singleval_subselect::val_int () +{ + if (exec()) + return 0; + return int_value; +} + +String *Item_singleval_subselect::val_str (String *str) +{ + if (exec() || null_value) + return 0; + return &str_value; +} + +Item_exists_subselect::Item_exists_subselect(THD *thd, + st_select_lex *select_lex): + Item_subselect(thd, select_lex, new select_singleval_subselect(this)) +{ + max_columns= UINT_MAX; + null_value= 0; //can't be NULL + maybe_null= 0; //can't be NULL + value= 0; + select_lex->select_limit= 1; // we need only 1 row to determinate existence +} + +double Item_exists_subselect::val () +{ + if (exec()) + return 0; + return (double) value; +} + +longlong Item_exists_subselect::val_int () +{ + if (exec()) + return 0; + return value; +} + +String *Item_exists_subselect::val_str(String *str) +{ + if (exec()) + return 0; + str->set(value); + return str; +} + diff --git a/sql/item_subselect.h b/sql/item_subselect.h index c6963df2d53..79832116c67 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -24,42 +24,34 @@ struct st_select_lex; class JOIN; class select_subselect; -/* simple (not depended of covered select ) subselect */ +/* base class for subselects */ class Item_subselect :public Item { protected: - longlong int_value; - double real_value; + uint max_columns; my_bool assigned; /* value already assigned to subselect */ my_bool executed; /* simple subselect is executed */ my_bool optimized; /* simple subselect is optimized */ my_bool error; /* error in query */ - enum Item_result res_type; int exec(); - void assign_null() + virtual void assign_null() { null_value= 1; - int_value= 0; - real_value= 0; - max_length= 4; - res_type= STRING_RESULT; } public: st_select_lex *select_lex; JOIN *join; select_subselect *result; - Item_subselect(THD *thd, st_select_lex *select_lex); + Item_subselect(THD *thd, st_select_lex *select_lex, + select_subselect* result); Item_subselect(Item_subselect *item) { null_value= item->null_value; - int_value= item->int_value; - real_value= item->real_value; - max_length= item->max_length; decimals= item->decimals; - res_type= item->res_type; + max_columns= item->max_columns; assigned= item->assigned; executed= item->executed; select_lex= item->select_lex; @@ -69,16 +61,75 @@ public: error= item->error; } enum Type type() const; - double val (); - longlong val_int (); - String *val_str (String *); bool is_null() { return null_value; } void make_field (Send_field *); bool fix_fields(THD *thd, TABLE_LIST *tables); - Item *new_item() { return new Item_subselect(this); } - enum Item_result result_type() const { return res_type; } + table_map used_tables() const; friend class select_subselect; }; +/* single value subselect */ + +class Item_singleval_subselect :public Item_subselect +{ +protected: + longlong int_value; + double real_value; + enum Item_result res_type; + + virtual void assign_null() + { + null_value= 1; + int_value= 0; + real_value= 0; + max_length= 4; + res_type= STRING_RESULT; + } +public: + Item_singleval_subselect(THD *thd, st_select_lex *select_lex); + Item_singleval_subselect(Item_singleval_subselect *item): + Item_subselect(item) + { + int_value= item->int_value; + real_value= item->real_value; + max_length= item->max_length; + decimals= item->decimals; + res_type= item->res_type; + } + double val (); + longlong val_int (); + String *val_str (String *); + Item *new_item() { return new Item_singleval_subselect(this); } + enum Item_result result_type() const { return res_type; } + + friend class select_singleval_subselect; +}; + +/* exists subselect */ + +class Item_exists_subselect :public Item_subselect +{ +protected: + longlong value; + + virtual void assign_null() + { + value= 0; + } +public: + Item_exists_subselect(THD *thd, st_select_lex *select_lex); + Item_exists_subselect(Item_exists_subselect *item): + Item_subselect(item) + { + value= item->value; + } + Item *new_item() { return new Item_exists_subselect(this); } + enum Item_result result_type() const { return INT_RESULT;} + longlong val_int(); + double val(); + String *val_str(String*); + + friend class select_exists_subselect; +}; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 86e4e6896e6..85f5b3cb5f2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -763,7 +763,6 @@ void select_dump::send_error(uint errcode,const char *err) file= -1; } - bool select_dump::send_eof() { int error=test(end_io_cache(&cache)); @@ -782,10 +781,11 @@ select_subselect::select_subselect(Item_subselect *item) this->item=item; } -bool select_subselect::send_data(List &items) +bool select_singleval_subselect::send_data(List &items) { - DBUG_ENTER("select_subselect::send_data"); - if (item->assigned){ + DBUG_ENTER("select_singleval_subselect::send_data"); + Item_singleval_subselect *it= (Item_singleval_subselect *)item; + if (it->assigned){ my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0)); DBUG_RETURN(1); } @@ -800,18 +800,33 @@ bool select_subselect::send_data(List &items) Following val() call have to be first, because function AVG() & STD() calculate value on it & determinate "is it NULL?". */ - item->real_value= val_item->val(); - if ((item->null_value= val_item->is_null())) + it->real_value= val_item->val(); + if ((it->null_value= val_item->is_null())) { - item->assign_null(); + it->assign_null(); } else { - item->max_length= val_item->max_length; - item->decimals= val_item->decimals; - item->binary= val_item->binary; - val_item->val_str(&item->str_value); - item->int_value= val_item->val_int(); - item->res_type= val_item->result_type(); + it->max_length= val_item->max_length; + it->decimals= val_item->decimals; + it->binary= val_item->binary; + val_item->val_str(&it->str_value); + it->int_value= val_item->val_int(); + it->res_type= val_item->result_type(); } - item->assigned= 1; + it->assigned= 1; DBUG_RETURN(0); } + +bool select_exists_subselect::send_data(List &items) +{ + DBUG_ENTER("select_exists_subselect::send_data"); + Item_exists_subselect *it= (Item_exists_subselect *)item; + if (unit->offset_limit_cnt) + { // Using limit offset,count + unit->offset_limit_cnt--; + DBUG_RETURN(0); + } + it->value= 1; + it->assigned= 1; + DBUG_RETURN(0); +} + diff --git a/sql/sql_class.h b/sql/sql_class.h index 8a1a299ceee..eb57b5828f6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -712,19 +712,36 @@ class select_union :public select_result { bool flush(); }; -/* Single value subselect interface class */ +/* Base subselect interface class */ class select_subselect :public select_result { +protected: Item_subselect *item; public: select_subselect(Item_subselect *item); bool send_fields(List &list, uint flag) { return 0; }; - bool send_data(List &items); + bool send_data(List &items)=0; bool send_eof() { return 0; }; - + friend class Ttem_subselect; }; +/* Single value subselect interface class */ +class select_singleval_subselect :public select_subselect +{ +public: + select_singleval_subselect(Item_subselect *item):select_subselect(item){} + bool send_data(List &items); +}; + +/* EXISTS subselect interface class */ +class select_exists_subselect :public select_subselect +{ +public: + select_exists_subselect(Item_subselect *item):select_subselect(item){} + bool send_data(List &items); +}; + /* Structs used when sorting */ typedef struct st_sort_field { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index efc8b8b5389..9047bc472ac 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -548,7 +548,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr - using_list subselect subselect_init + using_list singleval_subselect singleval_subselect_init + exists_subselect exists_subselect_init %type expr_list udf_expr_list when_list ident_list ident_list_arg @@ -1738,7 +1739,8 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } - | subselect { $$= $1; } + | EXISTS exists_subselect { $$= $2; } + | singleval_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' expr ')' { Select->ftfunc_list.push_back((Item_func_match *) @@ -3918,17 +3920,30 @@ union_option: /* empty */ {} | ALL {Lex->union_option=1;}; -subselect: - subselect_start subselect_init +singleval_subselect: + subselect_start singleval_subselect_init subselect_end { $$= $2; }; -subselect_init: +singleval_subselect_init: select_init { - $$= new Item_subselect(current_thd, Lex->select); + $$= new Item_singleval_subselect(current_thd, Lex->select); + }; + +exists_subselect: + subselect_start exists_subselect_init + subselect_end + { + $$= $2; + }; + +exists_subselect_init: + select_init + { + $$= new Item_exists_subselect(current_thd, Lex->select); }; subselect_start: -- cgit v1.2.1 From 6f5f47855acc0e421596dd287217f95685b1ec8b Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Wed, 19 Jun 2002 21:21:30 +0500 Subject: Default table character set has been added: CREATE TABLE a (field,...) TYPE=type CHARSET=cset; --- sql/handler.h | 1 + sql/lex.h | 1 + sql/sql_show.cc | 8 +++++++- sql/sql_table.cc | 5 +++++ sql/sql_yacc.yy | 24 ++++++++++++++++++------ sql/table.cc | 11 ++++++----- sql/unireg.cc | 3 +-- 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index 45865c39154..7260e8f2f8c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, #define HA_CREATE_USED_MAX_ROWS 32 #define HA_CREATE_USED_AVG_ROW_LENGTH 64 #define HA_CREATE_USED_PACK_KEYS 128 +#define HA_CREATE_USED_CHARSET 256 typedef struct st_thd_trans { void *bdb_tid; diff --git a/sql/lex.h b/sql/lex.h index da0a71a135e..4af36df58af 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -82,6 +82,7 @@ static SYMBOL symbols[] = { { "CASE", SYM(CASE_SYM),0,0}, { "CHAR", SYM(CHAR_SYM),0,0}, { "CHARACTER", SYM(CHAR_SYM),0,0}, + { "CHARSET", SYM(CHARSET),0,0}, { "CHANGE", SYM(CHANGE),0,0}, { "CHANGED", SYM(CHANGED),0,0}, { "CHECK", SYM(CHECK_SYM),0,0}, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 48d6bc7471f..494607c7fff 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1156,6 +1156,12 @@ store_create_info(THD *thd, TABLE *table, String *packet) char buff[128]; char* p; + if (table->table_charset) + { + packet->append(" CHARSET="); + packet->append(table->table_charset->name); + } + if (table->min_rows) { packet->append(" MIN_ROWS="); @@ -1386,7 +1392,7 @@ int mysqld_show_charsets(THD *thd, const char *wild) net_store_data(&packet2,(uint32) cs->mbmaxlen); if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length())) - goto err; /* purecov: inspected */ + goto err; } } send_eof(&thd->net); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f4f4dd212bd..3a6ff3d6b16 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -375,6 +375,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) auto_increment++; + if(!sql_field->charset) + sql_field->charset = create_info->table_charset ? + create_info->table_charset : default_charset_info; pos+=sql_field->pack_length; } if (auto_increment > 1) @@ -1645,6 +1648,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, create_info->max_rows=table->max_rows; if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) create_info->avg_row_length=table->avg_row_length; + if (!(used_fields & HA_CREATE_USED_CHARSET)) + create_info->table_charset=table->table_charset; table->file->update_create_info(create_info); if ((create_info->table_options & diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d140cd4dcdd..228e43f3954 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -162,6 +162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CACHE_SYM %token CASCADE %token CAST_SYM +%token CHARSET %token CHECKSUM_SYM %token CHECK_SYM %token CIPHER @@ -767,7 +768,7 @@ create: bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.options=$2 | $4; lex->create_info.db_type= default_table_type; - lex->create_info.table_charset=default_charset_info; + lex->create_info.table_charset=NULL; } create2 @@ -881,6 +882,17 @@ create_table_option: table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } + | CHARSET EQ ident + { + CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); + if (!cs) + { + net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); + YYABORT; + } + Lex->create_info.table_charset=cs; + Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; + } | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; } | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; @@ -965,7 +977,7 @@ field_spec: LEX *lex=Lex; lex->length=lex->dec=0; lex->type=0; lex->interval=0; lex->default_value=lex->comment=0; - lex->charset=default_charset_info; + lex->charset=NULL; } type opt_attribute { @@ -1116,8 +1128,8 @@ attribute: | COMMENT_SYM text_literal { Lex->comment= $2; }; opt_binary: - /* empty */ { Lex->charset=default_charset_info; } - | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=default_charset_info; } + /* empty */ { Lex->charset=NULL; } + | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; } | CHAR_SYM SET ident { CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); @@ -1130,7 +1142,7 @@ opt_binary: }; default_charset: - /* empty */ { Lex->charset-default_charset_info; } + /* empty */ { Lex->charset=NULL; } | DEFAULT CHAR_SYM SET ident { CHARSET_INFO *cs=get_charset_by_name($4.str,MYF(MY_WME)); @@ -1259,7 +1271,7 @@ alter: bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.row_type= ROW_TYPE_NOT_USED; - lex->create_info.table_charset=default_charset_info; + lex->create_info.table_charset=NULL; lex->alter_keys_onoff=LEAVE_AS_IS; lex->simple_alter=1; } diff --git a/sql/table.cc b/sql/table.cc index 201b67032bf..8a7604687e7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -118,7 +118,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, outparam->raid_chunks= head[42]; outparam->raid_chunksize= uint4korr(head+43); if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0)))) - outparam->table_charset=default_charset_info; + outparam->table_charset=NULL; // QQ display error message? null_field_first=1; } outparam->db_record_offset=1; @@ -358,7 +358,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, uint comment_length=uint2korr(strpos+13); field_type=(enum_field_types) (uint) strpos[11]; if (!(charset=get_charset((uint) strpos[12], MYF(0)))) - charset=outparam->table_charset; + charset=outparam->table_charset?outparam->table_charset:default_charset_info; if (!comment_length) { comment.str= (char*) ""; @@ -375,7 +375,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, { /* old frm file */ field_type= (enum_field_types) f_packtype(pack_flag); - charset=outparam->table_charset; + charset=outparam->table_charset?outparam->table_charset:default_charset_info; bzero((char*) &comment, sizeof(comment)); } *field_ptr=reg_field= @@ -1041,7 +1041,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, int2store(fileinfo+30,create_info->table_options); fileinfo[32]=0; // No filename anymore int4store(fileinfo+34,create_info->avg_row_length); - fileinfo[38]= create_info->table_charset->number; + fileinfo[38]= create_info->table_charset?create_info->table_charset->number:0; fileinfo[40]= (uchar) create_info->row_type; fileinfo[41]= (uchar) create_info->raid_type; fileinfo[42]= (uchar) create_info->raid_chunks; @@ -1072,6 +1072,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) create_info->raid_type=table->raid_type; create_info->raid_chunks=table->raid_chunks; create_info->raid_chunksize=table->raid_chunksize; + create_info->table_charset=table->table_charset; DBUG_VOID_RETURN; } @@ -1094,7 +1095,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr) { Field *field=table->field[fieldnr]; char buff[MAX_FIELD_WIDTH]; - String str(buff,sizeof(buff),table->table_charset); + String str(buff,sizeof(buff),default_charset_info); field->val_str(&str,&str); uint length=str.length(); if (!length) diff --git a/sql/unireg.cc b/sql/unireg.cc index 863f71d1cce..f2d8d6532a9 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -459,8 +459,7 @@ static bool pack_fields(File file,List &create_fields) int2store(buff+8,field->unireg_check); buff[10]= (uchar) field->interval_id; buff[11]= (uchar) field->sql_type; - buff[12]= (uchar) (field->charset ? field->charset->number : - default_charset_info->number); + buff[12]= (uchar) field->charset->number; int2store(buff+13, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); -- cgit v1.2.1 From 630f7cac959aba78b4bfacbaddd3eaf20c80dce2 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Wed, 19 Jun 2002 21:48:34 +0500 Subject: Now it is possible to drop default charset from table: ALTER TABLE a CHARSET=DEFAULT --- sql/sql_yacc.yy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 228e43f3954..83343e429e8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -882,6 +882,11 @@ create_table_option: table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } + | CHARSET EQ DEFAULT + { + Lex->create_info.table_charset=NULL; + Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; + } | CHARSET EQ ident { CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); -- cgit v1.2.1 From 5eafe401c0cb60a45d838e4503ba6c053b71a52d Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 20 Jun 2002 18:47:55 +0500 Subject: New syntax for string with charset: _latin1'string' Remove dupicated code --- sql/sql_lex.cc | 14 +++++++++++++- sql/sql_yacc.yy | 58 +++++++++++++++++++-------------------------------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 008ef44d83a..bcf212f6bd2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -525,7 +525,19 @@ int yylex(void *arg) yylval->lex_str=get_token(lex,length); if (lex->convert_set) lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); - return(IDENT); + + /* + Note: "SELECT _bla AS 'alias'" + _bla should be considered as a IDENT if charset haven't been found. + So we don't use MYF(MY_WME) with get_charset_by_name to avoid + producing an error. + */ + + if ((yylval->lex_str.str[0]=='_') && + (lex->charset=get_charset_by_name(yylval->lex_str.str+1,MYF(0)))) + return(UNDERSCORE_CHARSET); + else + return(IDENT); case STATE_IDENT_SEP: // Found ident and now '.' lex->next_state=STATE_IDENT_START;// Next is an ident (not a keyword) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 78d03bbbd1a..f3c5ae6efaf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -334,6 +334,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token UDF_SONAME_SYM %token UDF_SYM %token UNCOMMITTED_SYM +%token UNDERSCORE_CHARSET %token UNION_SYM %token UNIQUE_SYM %token USAGE @@ -525,7 +526,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME - ULONGLONG_NUM field_ident select_alias ident ident_or_text + ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET %type opt_table_alias @@ -888,15 +889,9 @@ create_table_option: Lex->create_info.table_charset=NULL; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; } - | CHARSET EQ ident + | CHARSET EQ charset { - CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); - YYABORT; - } - Lex->create_info.table_charset=cs; + Lex->create_info.table_charset=Lex->charset; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; } | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} @@ -1133,32 +1128,24 @@ attribute: | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } | COMMENT_SYM text_literal { Lex->comment= $2; }; +charset: + ident + { + if (!(Lex->charset=get_charset_by_name($1.str,MYF(0)))) + { + net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$1); + YYABORT; + } + }; + opt_binary: /* empty */ { Lex->charset=NULL; } | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; } - | CHAR_SYM SET ident - { - CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); - YYABORT; - } - Lex->charset=cs; - }; + | CHAR_SYM SET charset {/* charset is already in Lex->charset */} ; default_charset: /* empty */ { Lex->charset=NULL; } - | DEFAULT CHAR_SYM SET ident - { - CHARSET_INFO *cs=get_charset_by_name($4.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$4); - YYABORT; - } - Lex->charset=cs; - }; + | DEFAULT CHAR_SYM SET charset ; references: REFERENCES table_ident @@ -1777,16 +1764,8 @@ simple_expr: | CASE_SYM opt_expr WHEN_SYM when_list opt_else END { $$= new Item_func_case(* $4, $2, $5 ); } | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); } - | CONVERT_SYM '(' expr USING IDENT ')' - { - CHARSET_INFO *cs=get_charset_by_name($5.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$5); - YYABORT; - } - $$= new Item_func_conv_charset($3,cs); - } + | CONVERT_SYM '(' expr USING charset ')' + { $$= new Item_func_conv_charset($3,Lex->charset); } | CONVERT_SYM '(' expr ',' expr ',' expr ')' { $$= new Item_func_conv_charset3($3,$7,$5); @@ -3094,6 +3073,7 @@ opt_ignore_lines: text_literal: TEXT_STRING { $$ = new Item_string($1.str,$1.length,default_charset_info); } + | UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); } | text_literal TEXT_STRING { ((Item_string*) $1)->append($2.str,$2.length); }; -- cgit v1.2.1 From 44347c5a541c97b88b40a2a7698e33281ebcf951 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 20 Jun 2002 22:52:56 +0500 Subject: SELECT left(non_default_charset_field,n) GROUP BY 1 now works more correctly. Still needs fixes. --- sql/item.cc | 3 +++ sql/item_func.cc | 11 +++++++++++ sql/item_strfunc.cc | 1 + sql/sql_select.cc | 3 ++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index d01a06e5eba..415fe4d72af 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par) field_name=field_par->field_name; binary=field_par->binary(); unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); + /* For string fields copy character set from original field */ + if (!field_par->binary()) + str_value.set_charset(((Field_str*)field_par)->charset()); } const char *Item_ident::full_name() const diff --git a/sql/item_func.cc b/sql/item_func.cc index 0675bf81dab..b14c1b38383 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -78,6 +78,17 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables) maybe_null=1; if ((*arg)->binary) binary=1; + /* + Change charset to arg charset if it is not equal to + default_charset_info. This will work for many cases, + but generally this should be done more carefull. Each string + function should have it's own fix_fields() method to correctly + setup it's result's character set taking in account arguments. + For example: left(a,b) should take in account only first argument, + but ignore the second one. + */ + if ((*arg)->str_value.charset() != default_charset_info) + str_value.set_charset((*arg)->str_value.charset()); with_sum_func= with_sum_func || (*arg)->with_sum_func; used_tables_cache|=(*arg)->used_tables(); const_item_cache&= (*arg)->const_item(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5275da95b6e..81d866bfe6d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str) if (!res->alloced_length()) { // Don't change const str str_value= *res; // Not malloced string + str_value.set_charset(res->charset()); res= &str_value; } res->length((uint) length); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4737e068d3e..025a5c600a5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3579,7 +3579,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name,table,item->binary); else new_field= new Field_string(item->max_length,maybe_null, - item->name,table,item->binary,default_charset_info); + item->name,table,item->binary, + item->str_value.charset()); break; } if (copy_func) -- cgit v1.2.1 From c5b8f48cf5acecb4f50155a98bf83f4eefd53484 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 20 Jun 2002 23:26:04 +0500 Subject: New CHARSET() function --- sql/item_strfunc.cc | 13 +++++++++++++ sql/item_strfunc.h | 12 ++++++++++++ sql/sql_yacc.yy | 2 ++ 3 files changed, 27 insertions(+) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 81d866bfe6d..a4f09f9103e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1911,12 +1911,25 @@ outp: return str; } +String *Item_func_charset::val_str(String *str) +{ + String *res = args[0]->val_str(str); + + if ((null_value=(args[0]->null_value || !res->charset()))) + return 0; + str->copy(res->charset()->name,strlen(res->charset()->name)); + return str; +} + + void Item_func_conv_charset3::fix_length_and_dec() { /* BAR TODO: What to do here??? */ } + + String *Item_func_hex::val_str(String *str) { if (args[0]->result_type() != STRING_RESULT) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 03ef65c352a..a273abaf614 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -503,6 +503,18 @@ public: const char *func_name() const { return "conv_charset3"; } }; +class Item_func_charset :public Item_str_func +{ +public: + Item_func_charset(Item *a) :Item_str_func(a) {} + String *val_str(String *); + const char *func_name() const { return "charset"; } + void fix_length_and_dec() + { + max_length=20; // should be enough + }; +}; + /******************************************************* Spatial functions diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f3c5ae6efaf..91c87e9b849 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1784,6 +1784,8 @@ simple_expr: { $$= new Item_func_atan($3,$5); } | CHAR_SYM '(' expr_list ')' { $$= new Item_func_char(*$3); } + | CHARSET '(' expr ')' + { $$= new Item_func_charset($3); } | COALESCE '(' expr_list ')' { $$= new Item_func_coalesce(* $3); } | CONCAT '(' expr_list ')' -- cgit v1.2.1 From d616c90188f2c9903b6790720cd6172cbdada7dd Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Fri, 21 Jun 2002 14:46:50 +0500 Subject: Fixed charset problem on UPDATE in non-default-charset field --- sql/field_conv.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3b6de1383e2..3b8a2ee791c 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -520,7 +520,9 @@ void field_conv(Field *to,Field *from) char buff[MAX_FIELD_WIDTH]; String result(buff,sizeof(buff),default_charset_info); from->val_str(&result,&result); - to->store(result.c_ptr_quick(),result.length(),default_charset_info); + to->store(result.c_ptr_quick(),result.length(), + to->binary()?default_charset_info:((Field_str*)to)->charset()); + // QQ: what to do if "from" and "to" are of dirrent charsets? } else if (from->result_type() == REAL_RESULT) to->store(from->val_real()); -- cgit v1.2.1 From 5b45ebe812a564a6d118124d428f17abd8ec14f7 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Fri, 21 Jun 2002 16:55:55 +0500 Subject: database default character set is now stored in database directory --- sql/mysql_priv.h | 2 +- sql/sql_db.cc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- sql/sql_parse.cc | 2 +- sql/sql_yacc.yy | 1 + 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4f0bc2fe14a..1d0e3c1a72f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -289,7 +289,7 @@ inline THD *_current_thd(void) #define prepare_execute(A) ((A)->command == COM_EXECUTE) -int mysql_create_db(THD *thd, char *db, uint create_info, bool silent); +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 3f619b70244..5275403db40 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -31,13 +31,15 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, /* db-name is already validated when we come here */ -int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) { char path[FN_REFLEN+16]; MY_DIR *dirp; long result=1; int error = 0; DBUG_ENTER("mysql_create_db"); + register File file; + uint create_options = create_info ? create_info->options : 0; VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -73,6 +75,37 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) } } + /* + Create database options file: + Currently databse default charset is only stored there. + */ + + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,"db.opt"); + if ((file=my_create(path,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + { + sprintf(path,"CREATE DATABASE %s DEFAULT CHARACTER SET=%s\n",db, + (create_info && create_info->table_charset) + ? create_info->table_charset->name : "DEFAULT"); + + if (my_write(file,(byte*) path,strlen(path),MYF(MY_NABP+MY_WME))) + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } + my_close(file,MYF(0)); + } + else + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } + if (!silent) { if (!thd->query) @@ -104,7 +137,7 @@ exit2: DBUG_RETURN(error); } -const char *del_exts[]= {".frm", ".BAK", ".TMD", NullS}; +const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts}; @@ -333,6 +366,7 @@ bool mysql_change_db(THD *thd,const char *name) char path[FN_REFLEN]; uint db_access; DBUG_ENTER("mysql_change_db"); + register File file; if (!dbname || !(db_length=strip_sp(dbname))) { @@ -382,5 +416,25 @@ bool mysql_change_db(THD *thd,const char *name) thd->db=dbname; thd->db_length=db_length; thd->db_access=db_access; + + /* + Load database options file: + */ + + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,"db.opt"); + if ((file=my_open(path,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) + { + int nbytes=my_read(file,(byte*) path,sizeof(path),MYF(0)); + if ( nbytes >= 0 ) + { + path[nbytes]='\0'; + // BAR TODO: parse create options + // and extract database default charset + } + my_close(file,MYF(0)); + } + DBUG_RETURN(0); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 70f50483114..1f7e05fbae0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2308,7 +2308,7 @@ mysql_execute_command(void) } if (check_access(thd,CREATE_ACL,lex->name,0,1)) break; - res=mysql_create_db(thd,lex->name,lex->create_info.options,0); + res=mysql_create_db(thd,lex->name,&lex->create_info,0); break; } case SQLCOM_DROP_DB: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 91c87e9b849..faa63afa6c7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -798,6 +798,7 @@ create: lex->sql_command=SQLCOM_CREATE_DB; lex->name=$4.str; lex->create_info.options=$3; + lex->create_info.table_charset=lex->charset; } | CREATE udf_func_type UDF_SYM ident { -- cgit v1.2.1 From 97d9936f5dcd985671b393ec84ab6438d929d17e Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Mon, 24 Jun 2002 21:50:08 +0500 Subject: Database default charset now works: CREATE DATABASE dbname DEFAULT CHARACTERSET=latin1 --- .bzrignore | 1 + sql/sql_class.cc | 1 + sql/sql_class.h | 3 ++- sql/sql_db.cc | 45 ++++++++++++++++++++++++++++++++++++++------- sql/sql_table.cc | 4 +++- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/.bzrignore b/.bzrignore index 4683dcd2fb7..3b9576a47f0 100644 --- a/.bzrignore +++ b/.bzrignore @@ -478,3 +478,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +tests/client_test diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7a1ac4728da..c8914702ae7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -103,6 +103,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), file_id = 0; cond_count=0; convert_set=0; + db_charset=default_charset_info; mysys_var=0; #ifndef DBUG_OFF dbug_sentry=THD_SENTRY_MAGIC; diff --git a/sql/sql_class.h b/sql/sql_class.h index 37eb366e21f..9b708e35a1e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -473,7 +473,8 @@ public: ulong slave_proxy_id; NET* slave_net; // network connection from slave -> m. my_off_t log_pos; - + CHARSET_INFO *db_charset; + THD(); ~THD(); void cleanup(void); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 5275403db40..91f7474bb33 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,6 +25,8 @@ #include #endif +#define MY_DB_OPT_FILE ".db.opt" + static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level); @@ -82,12 +84,12 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent strcat(path,"/"); unpack_dirname(path,path); - strcat(path,"db.opt"); + strcat(path,MY_DB_OPT_FILE); if ((file=my_create(path,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { - sprintf(path,"CREATE DATABASE %s DEFAULT CHARACTER SET=%s\n",db, - (create_info && create_info->table_charset) - ? create_info->table_charset->name : "DEFAULT"); + sprintf(path,"default-character-set=%s\n", + (create_info && create_info->table_charset) ? + create_info->table_charset->name : "DEFAULT"); if (my_write(file,(byte*) path,strlen(path),MYF(MY_NABP+MY_WME))) { @@ -423,15 +425,44 @@ bool mysql_change_db(THD *thd,const char *name) strcat(path,"/"); unpack_dirname(path,path); - strcat(path,"db.opt"); + strcat(path,MY_DB_OPT_FILE); if ((file=my_open(path,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) { int nbytes=my_read(file,(byte*) path,sizeof(path),MYF(0)); if ( nbytes >= 0 ) { + char *ln=path; + char *pe=path+nbytes; + path[nbytes]='\0'; - // BAR TODO: parse create options - // and extract database default charset + for ( ln=path; lndb_charset=get_charset_by_name(val, MYF(0)); + } + goto cnt; + break; + } + } +cnt: + ln=le; + } } my_close(file,MYF(0)); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3a6ff3d6b16..d8012c0c102 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -377,7 +377,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, auto_increment++; if(!sql_field->charset) sql_field->charset = create_info->table_charset ? - create_info->table_charset : default_charset_info; + create_info->table_charset : + thd->db_charset? thd->db_charset : + default_charset_info; pos+=sql_field->pack_length; } if (auto_increment > 1) -- cgit v1.2.1 From 337d46966cf9fd37752a4f870b3f5161001be504 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Wed, 26 Jun 2002 16:00:43 +0500 Subject: Several problems were fixed (mostly BLOB+charset related) Fixed that MyISAM were not working properly with non-8bit charsets in some cases CONVERT() function now works properly --- myisam/mi_unique.c | 35 ++++++++++++++++++++++++++--------- sql/field.cc | 11 ++++++----- sql/field.h | 11 ++++++----- sql/field_conv.cc | 3 ++- sql/item_strfunc.cc | 38 ++++++++++++++++++++++++++++---------- sql/item_strfunc.h | 4 +++- sql/sql_select.cc | 9 ++++++--- 7 files changed, 77 insertions(+), 34 deletions(-) diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index 629523ec69a..7afaabfe75b 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -99,11 +99,20 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) end= pos+length; if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) { - uchar *sort_order=keyseg->charset->sort_order; - while (pos != end) - crc=((crc << 8) + - (((uchar) sort_order[*(uchar*) pos++]))) + - (crc >> (8*sizeof(ha_checksum)-8)); + if (keyseg->charset->hash_sort) + { + ulong nr=1, nr2=4; + keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2); + crc=nr; + } + else + { + uchar *sort_order=keyseg->charset->sort_order; + while (pos != end) + crc=((crc << 8) + + (((uchar) sort_order[*(uchar*) pos++]))) + + (crc >> (8*sizeof(ha_checksum)-8)); + } } else while (pos != end) @@ -173,11 +182,19 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, end= pos_a+length; if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) { - uchar *sort_order=keyseg->charset->sort_order; - while (pos_a != end) - if (sort_order[*(uchar*) pos_a++] != - sort_order[*(uchar*) pos_b++]) + if (use_strcoll(keyseg->charset)) + { + if (my_strnncoll(keyseg->charset,pos_a,length,pos_b,length)) return 1; + } + else + { + uchar *sort_order=keyseg->charset->sort_order; + while (pos_a != end) + if (sort_order[*(uchar*) pos_a++] != + sort_order[*(uchar*) pos_b++]) + return 1; + } } else while (pos_a != end) diff --git a/sql/field.cc b/sql/field.cc index 8b1073d32f3..a475612fbb0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3782,10 +3782,10 @@ uint Field_varstring::max_packed_col_length(uint max_length) Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, - bool binary_arg) + bool binary_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - table_arg, default_charset_info), + table_arg, cs), packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true) { flags|= BLOB_FLAG; @@ -3967,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)), char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) - val_ptr->set("",0,default_charset_info); // A bit safer than ->length(0) + val_ptr->set("",0,field_charset); // A bit safer than ->length(0) else - val_ptr->set((const char*) blob,get_length(ptr),default_charset_info); + val_ptr->set((const char*) blob,get_length(ptr),field_charset); return val_ptr; } @@ -4782,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length, if (f_is_blob(pack_flag)) return new Field_blob(ptr,null_pos,null_bit, unireg_check, field_name, table, - pack_length,f_is_binary(pack_flag) != 0); + pack_length,f_is_binary(pack_flag) != 0, + default_charset_info); if (f_is_geom(pack_flag)) return new Field_geom(ptr,null_pos,null_bit, unireg_check, field_name, table, diff --git a/sql/field.h b/sql/field.h index 5b9723654d9..5bc463af48d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -842,11 +842,11 @@ public: Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, - bool binary_arg); + bool binary_arg, CHARSET_INFO *cs); Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, bool binary_arg) + struct st_table *table_arg, bool binary_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg, default_charset_info), + NONE, field_name_arg, table_arg, cs), packlength(3),binary_flag(binary_arg), geom_flag(true) { flags|= BLOB_FLAG; @@ -930,11 +930,12 @@ public: struct st_table *table_arg,uint blob_pack_length, bool binary_arg) :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, table_arg, blob_pack_length,binary_arg) {} + field_name_arg, table_arg, blob_pack_length,binary_arg, + default_charset_info) {} Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, struct st_table *table_arg, bool binary_arg) :Field_blob(len_arg, maybe_null_arg, field_name_arg, - table_arg, binary_arg) {} + table_arg, binary_arg, default_charset_info) {} enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; } void get_key_image(char *buff,uint length, imagetype type); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3b8a2ee791c..da7a1187a47 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from) if (!blob->value.is_alloced() && from->real_type() != FIELD_TYPE_STRING) blob->value.copy(); - blob->store(blob->value.ptr(),blob->value.length(),default_charset_info); + blob->store(blob->value.ptr(),blob->value.length(), + to->binary()?default_charset_info:((Field_str*)to)->charset()); return; } if ((from->result_type() == STRING_RESULT && diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a4f09f9103e..c2549ddc769 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1799,7 +1799,7 @@ String *Item_func_conv_charset::val_str(String *str) s=(const uchar*)arg->ptr(); se=s+arg->length(); - dmaxlen=arg->length()*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1)+1; + dmaxlen=arg->length()*(to->mbmaxlen?to->mbmaxlen:1)+1; str->alloc(dmaxlen); d0=d=(unsigned char*)str->ptr(); de=d+dmaxlen; @@ -1841,7 +1841,7 @@ outp: void Item_func_conv_charset::fix_length_and_dec() { - /* BAR TODO: What to do here??? */ + max_length = args[0]->max_length*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1); } @@ -1911,23 +1911,41 @@ outp: return str; } -String *Item_func_charset::val_str(String *str) -{ - String *res = args[0]->val_str(str); - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->name,strlen(res->charset()->name)); - return str; +bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables) +{ + char buff[STACK_BUFF_ALLOC]; // Max argument in function + binary=0; + used_tables_cache=0; + const_item_cache=1; + + if (thd && check_stack_overrun(thd,buff)) + return 0; // Fatal error if flag is set! + if (args[0]->fix_fields(thd,tables)) + return 1; + maybe_null=args[0]->maybe_null; + binary=args[0]->binary; + str_value.set_charset(conv_charset); + fix_length_and_dec(); + return 0; } void Item_func_conv_charset3::fix_length_and_dec() { - /* BAR TODO: What to do here??? */ + max_length = args[0]->max_length; } +String *Item_func_charset::val_str(String *str) +{ + String *res = args[0]->val_str(str); + + if ((null_value=(args[0]->null_value || !res->charset()))) + return 0; + str->copy(res->charset()->name,strlen(res->charset()->name)); + return str; +} String *Item_func_hex::val_str(String *str) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a273abaf614..74ec51274fc 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -40,7 +40,8 @@ public: if (!t_arg) return result_field; return (max_length > 255) ? - (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary) : + (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary, + default_charset_info) : (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary, default_charset_info); } @@ -488,6 +489,7 @@ public: { conv_charset=cs; } + bool fix_fields(THD *thd,struct st_table_list *tables); String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "conv_charset"; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 025a5c600a5..f528750341e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3523,7 +3523,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case STRING_RESULT: if (item_sum->max_length > 255) return new Field_blob(item_sum->max_length,maybe_null, - item->name,table,item->binary); + item->name,table,item->binary,default_charset_info); return new Field_string(item_sum->max_length,maybe_null, item->name,table,item->binary,default_charset_info); } @@ -3576,7 +3576,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case STRING_RESULT: if (item->max_length > 255) new_field= new Field_blob(item->max_length,maybe_null, - item->name,table,item->binary); + item->name,table,item->binary, + item->str_value.charset()); else new_field= new Field_string(item->max_length,maybe_null, item->name,table,item->binary, @@ -4104,7 +4105,9 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, { Field *field=keyinfo->key_part[i].field; seg->flag= 0; - seg->language= MY_CHARSET_CURRENT; + seg->language= field->binary() ? MY_CHARSET_CURRENT : + ((Field_str*)field)->charset()->number; + seg->length= keyinfo->key_part[i].length; seg->start= keyinfo->key_part[i].offset; if (field->flags & BLOB_FLAG) -- cgit v1.2.1 From f683fe68908b74632e7426fe7f0a40d4c3669f65 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Wed, 26 Jun 2002 16:41:51 +0500 Subject: This now correctly substitutes charset to new table: CREATE TABLE a SELECT strfunc(non_default_charset_expr) --- sql/item_strfunc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 74ec51274fc..967fb1ee7f2 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -41,9 +41,9 @@ public: return result_field; return (max_length > 255) ? (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary, - default_charset_info) : + str_value.charset()) : (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary, - default_charset_info); + str_value.charset()); } }; -- cgit v1.2.1 From a3d8e08695ed9a4307e89c08ee6e033b464f5e94 Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Wed, 26 Jun 2002 18:08:33 +0500 Subject: SELECT DISTINCT CONVERT(field USING charset) now works properly --- sql/item_strfunc.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c2549ddc769..8fb3b7f6897 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1925,6 +1925,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables) return 1; maybe_null=args[0]->maybe_null; binary=args[0]->binary; + const_item_cache=args[0]->const_item(); str_value.set_charset(conv_charset); fix_length_and_dec(); return 0; -- cgit v1.2.1 From 0dce493b69bb53a38af044f9bd56a2933163a37b Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 27 Jun 2002 14:41:02 +0500 Subject: ALTER DATABASE DEFAULT CHARACTER SET latin1; --- sql/mysql_priv.h | 3 +- sql/sql_db.cc | 227 ++++++++++++++++++++++++++++++++++++++----------------- sql/sql_lex.h | 3 +- sql/sql_parse.cc | 17 +++++ sql/sql_yacc.yy | 24 ++++-- 5 files changed, 195 insertions(+), 79 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1d0e3c1a72f..2992f11ef65 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -289,7 +289,8 @@ inline THD *_current_thd(void) #define prepare_execute(A) ((A)->command == COM_EXECUTE) -int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent); +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); +int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 91f7474bb33..aa8030e5a3e 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -31,6 +31,96 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level); +/* + Create database options file: + Currently databse default charset is only stored there. +*/ + +static int write_db_opt(THD *thd, char *db, HA_CREATE_INFO *create, char *fn) +{ + register File file; + char buf[256]; // Should be enough + int error=0; + + if ((file=my_create(fn,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + { + sprintf(buf,"default-character-set=%s\n", + (create && create->table_charset) ? + create->table_charset->name : "DEFAULT"); + + if (my_write(file,(byte*)buf,strlen(buf),MYF(MY_NABP+MY_WME))) + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } + my_close(file,MYF(0)); + } + else + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } +exit: + return error; +} + + + /* + Load database options file: + */ +static int load_db_opt(THD *thd,char *fn) +{ + register File file; + char buf[256]=""; + + if ((file=my_open(fn,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) + { + int nbytes=my_read(file,(byte*)buf,sizeof(buf)-1,MYF(0)); + if ( nbytes >= 0 ) + { + char *ln=buf; + char *pe=buf+nbytes; + + buf[nbytes]='\0'; + + for ( ln=buf; lndb_charset=get_charset_by_name(val, MYF(0)); + } + goto cnt; + break; + } + } +cnt: + ln=le; + } + } + my_close(file,MYF(0)); + } + return 0; +} + /* db-name is already validated when we come here */ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) @@ -39,10 +129,10 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent MY_DIR *dirp; long result=1; int error = 0; - DBUG_ENTER("mysql_create_db"); - register File file; uint create_options = create_info ? create_info->options : 0; - + + DBUG_ENTER("mysql_create_db"); + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not create database if another thread is holding read lock @@ -77,43 +167,81 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent } } - /* - Create database options file: - Currently databse default charset is only stored there. - */ - strcat(path,"/"); unpack_dirname(path,path); strcat(path,MY_DB_OPT_FILE); - if ((file=my_create(path,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((error=write_db_opt(thd,db,create_info,path))) + goto exit; + + if (!silent) { - sprintf(path,"default-character-set=%s\n", - (create_info && create_info->table_charset) ? - create_info->table_charset->name : "DEFAULT"); - - if (my_write(file,(byte*) path,strlen(path),MYF(MY_NABP+MY_WME))) + if (!thd->query) { - // QQ : should we send more suitable error message? - my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); - error = -1; - goto exit; + thd->query = path; + thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- + path); } - my_close(file,MYF(0)); + { + mysql_update_log.write(thd,thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + } + } + if (thd->query == path) + { + thd->query = 0; // just in case + thd->query_length = 0; + } + send_ok(&thd->net, result); } - else + +exit: + start_waiting_global_read_lock(thd); +exit2: + VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + DBUG_RETURN(error); +} + + +/* db-name is already validated when we come here */ + +int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) +{ + char path[FN_REFLEN+16]; + MY_DIR *dirp; + long result=1; + int error = 0; + DBUG_ENTER("mysql_create_db"); + register File file; + uint create_options = create_info ? create_info->options : 0; + + printf("alter database\n"); + + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + + // do not alter database if another thread is holding read lock + if (wait_if_global_read_lock(thd,0)) { - // QQ : should we send more suitable error message? - my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); - error = -1; - goto exit; + error= -1; + goto exit2; } + /* Check directory */ + (void)sprintf(path,"%s/%s", mysql_data_home, db); + strcat(path,"/"); + unpack_dirname(path,path); // Convert if not unix + strcat(path,MY_DB_OPT_FILE); + if ((error=write_db_opt(thd,db,create_info,path))) + goto exit; + if (!silent) { if (!thd->query) { thd->query = path; - thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- + thd->query_length = (uint) (strxmov(path,"alter database ", db, NullS)- path); } { @@ -139,6 +267,10 @@ exit2: DBUG_RETURN(error); } + + + + const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts}; @@ -368,7 +500,6 @@ bool mysql_change_db(THD *thd,const char *name) char path[FN_REFLEN]; uint db_access; DBUG_ENTER("mysql_change_db"); - register File file; if (!dbname || !(db_length=strip_sp(dbname))) { @@ -419,53 +550,11 @@ bool mysql_change_db(THD *thd,const char *name) thd->db_length=db_length; thd->db_access=db_access; - /* - Load database options file: - */ - strcat(path,"/"); unpack_dirname(path,path); strcat(path,MY_DB_OPT_FILE); - if ((file=my_open(path,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) - { - int nbytes=my_read(file,(byte*) path,sizeof(path),MYF(0)); - if ( nbytes >= 0 ) - { - char *ln=path; - char *pe=path+nbytes; + load_db_opt(thd,path); - path[nbytes]='\0'; - for ( ln=path; lndb_charset=get_charset_by_name(val, MYF(0)); - } - goto cnt; - break; - } - } -cnt: - ln=le; - } - } - my_close(file,MYF(0)); - } DBUG_RETURN(0); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ca824b3eab8..545300b2629 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -44,7 +44,8 @@ enum enum_sql_command { SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, - SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, + SQLCOM_GRANT, + SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1f7e05fbae0..43cb056ffc8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2328,6 +2328,23 @@ mysql_execute_command(void) res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0); break; } + case SQLCOM_ALTER_DB: + { + if (!strip_sp(lex->name) || check_db_name(lex->name)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + break; + } + if (check_access(thd,DROP_ACL,lex->name,0,1)) + break; + if (thd->locked_tables || thd->active_transaction()) + { + send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + goto error; + } + res=mysql_alter_db(thd,lex->name,&lex->create_info,0); + break; + } case SQLCOM_CREATE_FUNCTION: if (check_access(thd,INSERT_ACL,"mysql",0,1)) break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index faa63afa6c7..303a539eb49 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -885,12 +885,7 @@ create_table_option: table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } - | CHARSET EQ DEFAULT - { - Lex->create_info.table_charset=NULL; - Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; - } - | CHARSET EQ charset + | CHARSET EQ charset_or_nocharset { Lex->create_info.table_charset=Lex->charset; Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; @@ -1139,6 +1134,10 @@ charset: } }; +charset_or_nocharset: + charset + | DEFAULT {Lex->charset=NULL; } + opt_binary: /* empty */ { Lex->charset=NULL; } | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; } @@ -1146,7 +1145,7 @@ opt_binary: default_charset: /* empty */ { Lex->charset=NULL; } - | DEFAULT CHAR_SYM SET charset ; + | DEFAULT CHAR_SYM SET charset_or_nocharset ; references: REFERENCES table_ident @@ -1270,7 +1269,16 @@ alter: lex->simple_alter=1; } alter_list; - + + | ALTER DATABASE ident default_charset + { + LEX *lex=Lex; + lex->sql_command=SQLCOM_ALTER_DB; + lex->name=$3.str; + lex->create_info.table_charset=lex->charset; + } + + alter_list: | alter_list_item | alter_list ',' alter_list_item; -- cgit v1.2.1 From 3ad618d403a7857654c5ac0a7081d5ff8c0e77cc Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 27 Jun 2002 15:21:52 +0500 Subject: Now database default character is changed during ALTER DATABASE if the current db is being altered --- sql/sql_db.cc | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index aa8030e5a3e..63edebd4ac7 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -36,7 +36,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, Currently databse default charset is only stored there. */ -static int write_db_opt(THD *thd, char *db, HA_CREATE_INFO *create, char *fn) +static int write_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) { register File file; char buf[256]; // Should be enough @@ -72,7 +72,7 @@ exit: /* Load database options file: */ -static int load_db_opt(THD *thd,char *fn) +static int load_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) { register File file; char buf[256]=""; @@ -217,8 +217,6 @@ int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) register File file; uint create_options = create_info ? create_info->options : 0; - printf("alter database\n"); - VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not alter database if another thread is holding read lock @@ -236,6 +234,15 @@ int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) if ((error=write_db_opt(thd,db,create_info,path))) goto exit; + /* + Change options if current + database is being altered + */ + if (thd->db && !strcmp(thd->db,db)) + { + thd->db_charset= create_info ? create_info->table_charset : NULL; + } + if (!silent) { if (!thd->query) @@ -499,6 +506,8 @@ bool mysql_change_db(THD *thd,const char *name) char *dbname=my_strdup((char*) name,MYF(MY_WME)); char path[FN_REFLEN]; uint db_access; + HA_CREATE_INFO create; + DBUG_ENTER("mysql_change_db"); if (!dbname || !(db_length=strip_sp(dbname))) @@ -553,8 +562,9 @@ bool mysql_change_db(THD *thd,const char *name) strcat(path,"/"); unpack_dirname(path,path); strcat(path,MY_DB_OPT_FILE); - load_db_opt(thd,path); - + bzero(&create,sizeof(create)); + load_db_opt(thd,name,&create,path); + thd->db_charset=create.table_charset; DBUG_RETURN(0); } -- cgit v1.2.1 From 2e1285f296be14749bdd51464a1327171e21850a Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 27 Jun 2002 19:00:49 +0500 Subject: Fix --- sql/item_strfunc.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8fb3b7f6897..5bb2c4015ad 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1792,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str) null_value=1; return 0; } + null_value=0; from=arg->charset(); to=conv_charset; -- cgit v1.2.1 From 8703e6063c5d5b1a366bbc9e1562b3d7988faece Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Thu, 27 Jun 2002 19:36:18 +0500 Subject: Added test for new charset features --- mysql-test/r/ctype_many.result | 1334 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_many.test | 189 ++++++ 2 files changed, 1523 insertions(+) create mode 100644 mysql-test/r/ctype_many.result create mode 100644 mysql-test/t/ctype_many.test diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result new file mode 100644 index 00000000000..b6c0f25853d --- /dev/null +++ b/mysql-test/r/ctype_many.result @@ -0,0 +1,1334 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +comment CHAR(32) CHARACTER SET latin1 NOT NULL, +koi8_ru_f CHAR(32) CHARACTER SET koi8_ru NOT NULL +) CHARSET=latin5; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin1 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '', + `latin5_f` char(32) character set latin5 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 CHARSET=latin2; +ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '', + `latin5_f` char(32) character set latin5 NOT NULL default '', + `latin2_f` char(32) character set latin2 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin2 +ALTER TABLE t1 DROP latin2_f, DROP latin5_f; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin2 +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA'); +ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL; +UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8); +SELECT * FROM t1; +comment koi8_ru_f utf8_f +LAT SMALL A a a +LAT SMALL B b b +LAT SMALL C c c +LAT SMALL D d d +LAT SMALL E e e +LAT SMALL F f f +LAT SMALL G g g +LAT SMALL H h h +LAT SMALL I i i +LAT SMALL J j j +LAT SMALL K k k +LAT SMALL L l l +LAT SMALL M m m +LAT SMALL N n n +LAT SMALL O o o +LAT SMALL P p p +LAT SMALL Q q q +LAT SMALL R r r +LAT SMALL S s s +LAT SMALL T t t +LAT SMALL U u u +LAT SMALL V v v +LAT SMALL W w w +LAT SMALL X x x +LAT SMALL Y y y +LAT SMALL Z z z +LAT CAPIT A A A +LAT CAPIT B B B +LAT CAPIT C C C +LAT CAPIT D D D +LAT CAPIT E E E +LAT CAPIT F F F +LAT CAPIT G G G +LAT CAPIT H H H +LAT CAPIT I I I +LAT CAPIT J J J +LAT CAPIT K K K +LAT CAPIT L L L +LAT CAPIT M M M +LAT CAPIT N N N +LAT CAPIT O O O +LAT CAPIT P P P +LAT CAPIT Q Q Q +LAT CAPIT R R R +LAT CAPIT S S S +LAT CAPIT T T T +LAT CAPIT U U U +LAT CAPIT V V V +LAT CAPIT W W W +LAT CAPIT X X X +LAT CAPIT Y Y Y +LAT CAPIT Z Z Z +CYR SMALL A Á а +CYR SMALL BE  б +CYR SMALL VE × Ð² +CYR SMALL GE Ç Ð³ +CYR SMALL DE Ä Ð´ +CYR SMALL IE Šе +CYR SMALL IO £ Ñ‘ +CYR SMALL ZHE Ö Ð¶ +CYR SMALL ZE Ú Ð· +CYR SMALL I É Ð¸ +CYR SMALL KA Ë Ðº +CYR SMALL EL Ì Ð» +CYR SMALL EM Í Ð¼ +CYR SMALL EN Πн +CYR SMALL O Ï Ð¾ +CYR SMALL PE Рп +CYR SMALL ER Ò Ñ€ +CYR SMALL ES Ó Ñ +CYR SMALL TE Ô Ñ‚ +CYR SMALL U Õ Ñƒ +CYR SMALL EF Æ Ñ„ +CYR SMALL HA È Ñ… +CYR SMALL TSE à ц +CYR SMALL CHE Þ Ñ‡ +CYR SMALL SHA Û Ñˆ +CYR SMALL SCHA Ý Ñ‰ +CYR SMALL HARD SIGN ß ÑŠ +CYR SMALL YERU Ù Ñ‹ +CYR SMALL SOFT SIGN Ø ÑŒ +CYR SMALL E Ü Ñ +CYR SMALL YU À ÑŽ +CYR SMALL YA Ñ Ñ +CYR CAPIT A á Ð +CYR CAPIT BE â Б +CYR CAPIT VE ÷ Ð’ +CYR CAPIT GE ç Г +CYR CAPIT DE ä Д +CYR CAPIT IE å Е +CYR CAPIT IO ³ Ð +CYR CAPIT ZHE ö Ж +CYR CAPIT ZE ú З +CYR CAPIT I é И +CYR CAPIT KA ë К +CYR CAPIT EL ì Л +CYR CAPIT EM í Ðœ +CYR CAPIT EN î Ð +CYR CAPIT O ï О +CYR CAPIT PE ð П +CYR CAPIT ER ò Р +CYR CAPIT ES ó С +CYR CAPIT TE ô Т +CYR CAPIT U õ У +CYR CAPIT EF æ Ф +CYR CAPIT HA è Ð¥ +CYR CAPIT TSE ã Ц +CYR CAPIT CHE þ Ч +CYR CAPIT SHA û Ш +CYR CAPIT SCHA ý Щ +CYR CAPIT HARD SIGN ÿ Ъ +CYR CAPIT YERU ù Ы +CYR CAPIT SOFT SIGN ø Ь +CYR CAPIT E ü Э +CYR CAPIT YU à Ю +CYR CAPIT YA ñ Я +SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1; +koi8_ru_f MIN(comment) +a LAT CAPIT A +b LAT CAPIT B +c LAT CAPIT C +d LAT CAPIT D +e LAT CAPIT E +f LAT CAPIT F +g LAT CAPIT G +h LAT CAPIT H +i LAT CAPIT I +j LAT CAPIT J +k LAT CAPIT K +l LAT CAPIT L +m LAT CAPIT M +n LAT CAPIT N +o LAT CAPIT O +p LAT CAPIT P +q LAT CAPIT Q +r LAT CAPIT R +s LAT CAPIT S +t LAT CAPIT T +u LAT CAPIT U +v LAT CAPIT V +w LAT CAPIT W +x LAT CAPIT X +y LAT CAPIT Y +z LAT CAPIT Z +Á CYR CAPIT A + CYR CAPIT BE +× CYR CAPIT VE +Ç CYR CAPIT GE +Ä CYR CAPIT DE +Å CYR CAPIT IE +£ CYR CAPIT IO +Ö CYR CAPIT ZHE +Ú CYR CAPIT ZE +É CYR CAPIT I +Ë CYR CAPIT KA +Ì CYR CAPIT EL +Í CYR CAPIT EM +Î CYR CAPIT EN +Ï CYR CAPIT O +Ð CYR CAPIT PE +Ò CYR CAPIT ER +Ó CYR CAPIT ES +Ô CYR CAPIT TE +Õ CYR CAPIT U +Æ CYR CAPIT EF +È CYR CAPIT HA +à CYR CAPIT TSE +Þ CYR CAPIT CHE +Û CYR CAPIT SHA +Ý CYR CAPIT SCHA +ß CYR CAPIT HARD SIGN +Ù CYR CAPIT YERU +Ø CYR CAPIT SOFT SIGN +Ü CYR CAPIT E +À CYR CAPIT YU +Ñ CYR CAPIT YA +SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1; +utf8_f MIN(comment) +a LAT CAPIT A +b LAT CAPIT B +c LAT CAPIT C +d LAT CAPIT D +e LAT CAPIT E +f LAT CAPIT F +g LAT CAPIT G +h LAT CAPIT H +i LAT CAPIT I +j LAT CAPIT J +k LAT CAPIT K +l LAT CAPIT L +m LAT CAPIT M +n LAT CAPIT N +o LAT CAPIT O +p LAT CAPIT P +q LAT CAPIT Q +r LAT CAPIT R +s LAT CAPIT S +t LAT CAPIT T +u LAT CAPIT U +v LAT CAPIT V +w LAT CAPIT W +x LAT CAPIT X +y LAT CAPIT Y +z LAT CAPIT Z +а CYR CAPIT A +б CYR CAPIT BE +в CYR CAPIT VE +г CYR CAPIT GE +д CYR CAPIT DE +е CYR CAPIT IE +ж CYR CAPIT ZHE +з CYR CAPIT ZE +и CYR CAPIT I +к CYR CAPIT KA +л CYR CAPIT EL +м CYR CAPIT EM +н CYR CAPIT EN +о CYR CAPIT O +п CYR CAPIT PE +Ñ€ CYR CAPIT ER +Ñ CYR CAPIT ES +Ñ‚ CYR CAPIT TE +у CYR CAPIT U +Ñ„ CYR CAPIT EF +Ñ… CYR CAPIT HA +ц CYR CAPIT TSE +ч CYR CAPIT CHE +ш CYR CAPIT SHA +щ CYR CAPIT SCHA +ÑŠ CYR CAPIT HARD SIGN +Ñ‹ CYR CAPIT YERU +ÑŒ CYR CAPIT SOFT SIGN +Ñ CYR CAPIT E +ÑŽ CYR CAPIT YU +Ñ CYR CAPIT YA +SELECT DISTINCT koi8_ru_f FROM t1; +koi8_ru_f +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +Á + +× +Ç +Ä +Å +£ +Ö +Ú +É +Ë +Ì +Í +Î +Ï +Ð +Ò +Ó +Ô +Õ +Æ +È +à +Þ +Û +Ý +ß +Ù +Ø +Ü +À +Ñ +SELECT DISTINCT utf8_f FROM t1; +utf8_f +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +а +б +в +г +д +е +ж +з +и +к +л +м +н +о +п +Ñ€ +Ñ +Ñ‚ +у +Ñ„ +Ñ… +ц +ч +ш +щ +ÑŠ +Ñ‹ +ÑŒ +Ñ +ÑŽ +Ñ +SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC; +lower(koi8_ru_f) +Ñ +Ñ +À +À +Ü +Ü +Ø +Ø +Ù +Ù +ß +ß +Ý +Ý +Û +Û +Þ +Þ +à +à +È +È +Æ +Æ +Õ +Õ +Ô +Ô +Ó +Ó +Ò +Ò +Ð +Ð +Ï +Ï +Î +Î +Í +Í +Ì +Ì +Ë +Ë +É +É +Ú +Ú +Ö +Ö +£ +£ +Å +Å +Ä +Ä +Ç +Ç +× +× + + +Á +Á +z +z +y +y +x +x +w +w +v +v +u +u +t +t +s +s +r +r +q +q +p +p +o +o +n +n +m +m +l +l +k +k +j +j +i +i +h +h +g +g +f +f +e +e +d +d +c +c +b +b +a +a +SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC; +lower(utf8_f) +Ñ +Ñ +ÑŽ +ÑŽ +Ñ +Ñ +ÑŒ +ÑŒ +Ñ‹ +Ñ‹ +ÑŠ +ÑŠ +щ +щ +ш +ш +ч +ч +ц +ц +Ñ… +Ñ… +Ñ„ +Ñ„ +у +у +Ñ‚ +Ñ‚ +Ñ +Ñ +Ñ€ +Ñ€ +п +п +о +о +н +н +м +м +л +л +к +к +и +и +з +з +ж +ж +е +Ñ‘ +е +Ñ‘ +д +д +г +г +в +в +б +б +а +а +z +z +y +y +x +x +w +w +v +v +u +u +t +t +s +s +r +r +q +q +p +p +o +o +n +n +m +m +l +l +k +k +j +j +i +i +h +h +g +g +f +f +e +e +d +d +c +c +b +b +a +a +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f +ORDER BY t11.koi8_ru_f; +comment comment +LAT SMALL A LAT SMALL A +LAT SMALL A LAT CAPIT A +LAT CAPIT A LAT SMALL A +LAT CAPIT A LAT CAPIT A +LAT SMALL B LAT CAPIT B +LAT CAPIT B LAT SMALL B +LAT CAPIT B LAT CAPIT B +LAT SMALL B LAT SMALL B +LAT CAPIT C LAT SMALL C +LAT CAPIT C LAT CAPIT C +LAT SMALL C LAT SMALL C +LAT SMALL C LAT CAPIT C +LAT CAPIT D LAT CAPIT D +LAT SMALL D LAT SMALL D +LAT SMALL D LAT CAPIT D +LAT CAPIT D LAT SMALL D +LAT SMALL E LAT SMALL E +LAT SMALL E LAT CAPIT E +LAT CAPIT E LAT SMALL E +LAT CAPIT E LAT CAPIT E +LAT SMALL F LAT SMALL F +LAT SMALL F LAT CAPIT F +LAT CAPIT F LAT SMALL F +LAT CAPIT F LAT CAPIT F +LAT SMALL G LAT CAPIT G +LAT CAPIT G LAT SMALL G +LAT CAPIT G LAT CAPIT G +LAT SMALL G LAT SMALL G +LAT CAPIT H LAT CAPIT H +LAT SMALL H LAT SMALL H +LAT SMALL H LAT CAPIT H +LAT CAPIT H LAT SMALL H +LAT CAPIT I LAT CAPIT I +LAT SMALL I LAT SMALL I +LAT SMALL I LAT CAPIT I +LAT CAPIT I LAT SMALL I +LAT SMALL J LAT SMALL J +LAT SMALL J LAT CAPIT J +LAT CAPIT J LAT SMALL J +LAT CAPIT J LAT CAPIT J +LAT SMALL K LAT CAPIT K +LAT CAPIT K LAT SMALL K +LAT CAPIT K LAT CAPIT K +LAT SMALL K LAT SMALL K +LAT SMALL L LAT CAPIT L +LAT CAPIT L LAT SMALL L +LAT CAPIT L LAT CAPIT L +LAT SMALL L LAT SMALL L +LAT CAPIT M LAT CAPIT M +LAT SMALL M LAT SMALL M +LAT SMALL M LAT CAPIT M +LAT CAPIT M LAT SMALL M +LAT SMALL N LAT SMALL N +LAT SMALL N LAT CAPIT N +LAT CAPIT N LAT SMALL N +LAT CAPIT N LAT CAPIT N +LAT SMALL O LAT SMALL O +LAT SMALL O LAT CAPIT O +LAT CAPIT O LAT SMALL O +LAT CAPIT O LAT CAPIT O +LAT SMALL P LAT CAPIT P +LAT CAPIT P LAT SMALL P +LAT CAPIT P LAT CAPIT P +LAT SMALL P LAT SMALL P +LAT CAPIT Q LAT SMALL Q +LAT CAPIT Q LAT CAPIT Q +LAT SMALL Q LAT SMALL Q +LAT SMALL Q LAT CAPIT Q +LAT CAPIT R LAT CAPIT R +LAT SMALL R LAT SMALL R +LAT SMALL R LAT CAPIT R +LAT CAPIT R LAT SMALL R +LAT SMALL S LAT SMALL S +LAT SMALL S LAT CAPIT S +LAT CAPIT S LAT SMALL S +LAT CAPIT S LAT CAPIT S +LAT SMALL T LAT CAPIT T +LAT CAPIT T LAT SMALL T +LAT CAPIT T LAT CAPIT T +LAT SMALL T LAT SMALL T +LAT SMALL U LAT CAPIT U +LAT CAPIT U LAT SMALL U +LAT CAPIT U LAT CAPIT U +LAT SMALL U LAT SMALL U +LAT CAPIT V LAT CAPIT V +LAT SMALL V LAT SMALL V +LAT SMALL V LAT CAPIT V +LAT CAPIT V LAT SMALL V +LAT CAPIT W LAT CAPIT W +LAT SMALL W LAT SMALL W +LAT SMALL W LAT CAPIT W +LAT CAPIT W LAT SMALL W +LAT SMALL X LAT SMALL X +LAT SMALL X LAT CAPIT X +LAT CAPIT X LAT SMALL X +LAT CAPIT X LAT CAPIT X +LAT SMALL Y LAT CAPIT Y +LAT CAPIT Y LAT SMALL Y +LAT CAPIT Y LAT CAPIT Y +LAT SMALL Y LAT SMALL Y +LAT CAPIT Z LAT SMALL Z +LAT CAPIT Z LAT CAPIT Z +LAT SMALL Z LAT SMALL Z +LAT SMALL Z LAT CAPIT Z +CYR CAPIT A CYR SMALL A +CYR SMALL A CYR CAPIT A +CYR CAPIT A CYR CAPIT A +CYR SMALL A CYR SMALL A +CYR SMALL BE CYR CAPIT BE +CYR CAPIT BE CYR CAPIT BE +CYR SMALL BE CYR SMALL BE +CYR CAPIT BE CYR SMALL BE +CYR CAPIT VE CYR CAPIT VE +CYR SMALL VE CYR SMALL VE +CYR CAPIT VE CYR SMALL VE +CYR SMALL VE CYR CAPIT VE +CYR CAPIT GE CYR CAPIT GE +CYR SMALL GE CYR SMALL GE +CYR CAPIT GE CYR SMALL GE +CYR SMALL GE CYR CAPIT GE +CYR CAPIT DE CYR SMALL DE +CYR SMALL DE CYR CAPIT DE +CYR CAPIT DE CYR CAPIT DE +CYR SMALL DE CYR SMALL DE +CYR SMALL IE CYR SMALL IO +CYR SMALL IE CYR CAPIT IE +CYR CAPIT IE CYR SMALL IE +CYR CAPIT IE CYR CAPIT IO +CYR SMALL IE CYR SMALL IE +CYR SMALL IE CYR CAPIT IO +CYR CAPIT IE CYR SMALL IO +CYR CAPIT IE CYR CAPIT IE +CYR SMALL IO CYR SMALL IE +CYR SMALL IO CYR CAPIT IO +CYR CAPIT IO CYR SMALL IO +CYR CAPIT IO CYR CAPIT IE +CYR SMALL IO CYR SMALL IO +CYR SMALL IO CYR CAPIT IE +CYR CAPIT IO CYR SMALL IE +CYR CAPIT IO CYR CAPIT IO +CYR CAPIT ZHE CYR SMALL ZHE +CYR SMALL ZHE CYR CAPIT ZHE +CYR CAPIT ZHE CYR CAPIT ZHE +CYR SMALL ZHE CYR SMALL ZHE +CYR SMALL ZE CYR CAPIT ZE +CYR CAPIT ZE CYR CAPIT ZE +CYR SMALL ZE CYR SMALL ZE +CYR CAPIT ZE CYR SMALL ZE +CYR CAPIT I CYR CAPIT I +CYR SMALL I CYR SMALL I +CYR CAPIT I CYR SMALL I +CYR SMALL I CYR CAPIT I +CYR CAPIT KA CYR CAPIT KA +CYR SMALL KA CYR SMALL KA +CYR CAPIT KA CYR SMALL KA +CYR SMALL KA CYR CAPIT KA +CYR CAPIT EL CYR SMALL EL +CYR SMALL EL CYR CAPIT EL +CYR CAPIT EL CYR CAPIT EL +CYR SMALL EL CYR SMALL EL +CYR CAPIT EM CYR SMALL EM +CYR SMALL EM CYR CAPIT EM +CYR CAPIT EM CYR CAPIT EM +CYR SMALL EM CYR SMALL EM +CYR SMALL EN CYR CAPIT EN +CYR CAPIT EN CYR CAPIT EN +CYR SMALL EN CYR SMALL EN +CYR CAPIT EN CYR SMALL EN +CYR CAPIT O CYR CAPIT O +CYR SMALL O CYR SMALL O +CYR CAPIT O CYR SMALL O +CYR SMALL O CYR CAPIT O +CYR SMALL PE CYR SMALL PE +CYR CAPIT PE CYR SMALL PE +CYR SMALL PE CYR CAPIT PE +CYR CAPIT PE CYR CAPIT PE +CYR CAPIT ER CYR SMALL ER +CYR SMALL ER CYR CAPIT ER +CYR CAPIT ER CYR CAPIT ER +CYR SMALL ER CYR SMALL ER +CYR SMALL ES CYR CAPIT ES +CYR CAPIT ES CYR CAPIT ES +CYR SMALL ES CYR SMALL ES +CYR CAPIT ES CYR SMALL ES +CYR CAPIT TE CYR CAPIT TE +CYR SMALL TE CYR SMALL TE +CYR CAPIT TE CYR SMALL TE +CYR SMALL TE CYR CAPIT TE +CYR CAPIT U CYR CAPIT U +CYR SMALL U CYR SMALL U +CYR CAPIT U CYR SMALL U +CYR SMALL U CYR CAPIT U +CYR CAPIT EF CYR SMALL EF +CYR SMALL EF CYR CAPIT EF +CYR CAPIT EF CYR CAPIT EF +CYR SMALL EF CYR SMALL EF +CYR CAPIT HA CYR SMALL HA +CYR SMALL HA CYR CAPIT HA +CYR CAPIT HA CYR CAPIT HA +CYR SMALL HA CYR SMALL HA +CYR SMALL TSE CYR CAPIT TSE +CYR CAPIT TSE CYR CAPIT TSE +CYR SMALL TSE CYR SMALL TSE +CYR CAPIT TSE CYR SMALL TSE +CYR CAPIT CHE CYR CAPIT CHE +CYR SMALL CHE CYR SMALL CHE +CYR CAPIT CHE CYR SMALL CHE +CYR SMALL CHE CYR CAPIT CHE +CYR CAPIT SHA CYR CAPIT SHA +CYR SMALL SHA CYR SMALL SHA +CYR CAPIT SHA CYR SMALL SHA +CYR SMALL SHA CYR CAPIT SHA +CYR CAPIT SCHA CYR SMALL SCHA +CYR SMALL SCHA CYR CAPIT SCHA +CYR CAPIT SCHA CYR CAPIT SCHA +CYR SMALL SCHA CYR SMALL SCHA +CYR CAPIT HARD SIGN CYR SMALL HARD SIGN +CYR SMALL HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN +CYR SMALL HARD SIGN CYR SMALL HARD SIGN +CYR CAPIT YERU CYR CAPIT YERU +CYR SMALL YERU CYR SMALL YERU +CYR CAPIT YERU CYR SMALL YERU +CYR SMALL YERU CYR CAPIT YERU +CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN +CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN +CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN +CYR CAPIT E CYR SMALL E +CYR SMALL E CYR CAPIT E +CYR CAPIT E CYR CAPIT E +CYR SMALL E CYR SMALL E +CYR CAPIT YU CYR SMALL YU +CYR SMALL YU CYR CAPIT YU +CYR CAPIT YU CYR CAPIT YU +CYR SMALL YU CYR SMALL YU +CYR SMALL YA CYR CAPIT YA +CYR CAPIT YA CYR CAPIT YA +CYR SMALL YA CYR SMALL YA +CYR CAPIT YA CYR SMALL YA +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 +WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8_ru) +ORDER BY t12.utf8_f; +comment comment +LAT SMALL A LAT SMALL A +LAT SMALL A LAT CAPIT A +LAT CAPIT A LAT SMALL A +LAT CAPIT A LAT CAPIT A +LAT SMALL B LAT CAPIT B +LAT CAPIT B LAT SMALL B +LAT CAPIT B LAT CAPIT B +LAT SMALL B LAT SMALL B +LAT CAPIT C LAT SMALL C +LAT CAPIT C LAT CAPIT C +LAT SMALL C LAT SMALL C +LAT SMALL C LAT CAPIT C +LAT CAPIT D LAT CAPIT D +LAT SMALL D LAT SMALL D +LAT SMALL D LAT CAPIT D +LAT CAPIT D LAT SMALL D +LAT SMALL E LAT SMALL E +LAT SMALL E LAT CAPIT E +LAT CAPIT E LAT SMALL E +LAT CAPIT E LAT CAPIT E +LAT SMALL F LAT SMALL F +LAT SMALL F LAT CAPIT F +LAT CAPIT F LAT SMALL F +LAT CAPIT F LAT CAPIT F +LAT SMALL G LAT CAPIT G +LAT CAPIT G LAT SMALL G +LAT CAPIT G LAT CAPIT G +LAT SMALL G LAT SMALL G +LAT CAPIT H LAT CAPIT H +LAT SMALL H LAT SMALL H +LAT SMALL H LAT CAPIT H +LAT CAPIT H LAT SMALL H +LAT CAPIT I LAT CAPIT I +LAT SMALL I LAT SMALL I +LAT SMALL I LAT CAPIT I +LAT CAPIT I LAT SMALL I +LAT SMALL J LAT SMALL J +LAT SMALL J LAT CAPIT J +LAT CAPIT J LAT SMALL J +LAT CAPIT J LAT CAPIT J +LAT SMALL K LAT CAPIT K +LAT CAPIT K LAT SMALL K +LAT CAPIT K LAT CAPIT K +LAT SMALL K LAT SMALL K +LAT SMALL L LAT CAPIT L +LAT CAPIT L LAT SMALL L +LAT CAPIT L LAT CAPIT L +LAT SMALL L LAT SMALL L +LAT CAPIT M LAT CAPIT M +LAT SMALL M LAT SMALL M +LAT SMALL M LAT CAPIT M +LAT CAPIT M LAT SMALL M +LAT SMALL N LAT SMALL N +LAT SMALL N LAT CAPIT N +LAT CAPIT N LAT SMALL N +LAT CAPIT N LAT CAPIT N +LAT SMALL O LAT SMALL O +LAT SMALL O LAT CAPIT O +LAT CAPIT O LAT SMALL O +LAT CAPIT O LAT CAPIT O +LAT SMALL P LAT CAPIT P +LAT CAPIT P LAT SMALL P +LAT CAPIT P LAT CAPIT P +LAT SMALL P LAT SMALL P +LAT CAPIT Q LAT SMALL Q +LAT CAPIT Q LAT CAPIT Q +LAT SMALL Q LAT SMALL Q +LAT SMALL Q LAT CAPIT Q +LAT CAPIT R LAT CAPIT R +LAT SMALL R LAT SMALL R +LAT SMALL R LAT CAPIT R +LAT CAPIT R LAT SMALL R +LAT SMALL S LAT SMALL S +LAT SMALL S LAT CAPIT S +LAT CAPIT S LAT SMALL S +LAT CAPIT S LAT CAPIT S +LAT SMALL T LAT CAPIT T +LAT CAPIT T LAT SMALL T +LAT CAPIT T LAT CAPIT T +LAT SMALL T LAT SMALL T +LAT SMALL U LAT CAPIT U +LAT CAPIT U LAT SMALL U +LAT CAPIT U LAT CAPIT U +LAT SMALL U LAT SMALL U +LAT CAPIT V LAT CAPIT V +LAT SMALL V LAT SMALL V +LAT SMALL V LAT CAPIT V +LAT CAPIT V LAT SMALL V +LAT CAPIT W LAT CAPIT W +LAT SMALL W LAT SMALL W +LAT SMALL W LAT CAPIT W +LAT CAPIT W LAT SMALL W +LAT SMALL X LAT SMALL X +LAT SMALL X LAT CAPIT X +LAT CAPIT X LAT SMALL X +LAT CAPIT X LAT CAPIT X +LAT SMALL Y LAT CAPIT Y +LAT CAPIT Y LAT SMALL Y +LAT CAPIT Y LAT CAPIT Y +LAT SMALL Y LAT SMALL Y +LAT CAPIT Z LAT SMALL Z +LAT CAPIT Z LAT CAPIT Z +LAT SMALL Z LAT SMALL Z +LAT SMALL Z LAT CAPIT Z +CYR CAPIT A CYR SMALL A +CYR CAPIT A CYR CAPIT A +CYR SMALL A CYR SMALL A +CYR SMALL A CYR CAPIT A +CYR SMALL BE CYR SMALL BE +CYR SMALL BE CYR CAPIT BE +CYR CAPIT BE CYR SMALL BE +CYR CAPIT BE CYR CAPIT BE +CYR SMALL VE CYR SMALL VE +CYR SMALL VE CYR CAPIT VE +CYR CAPIT VE CYR SMALL VE +CYR CAPIT VE CYR CAPIT VE +CYR SMALL GE CYR SMALL GE +CYR SMALL GE CYR CAPIT GE +CYR CAPIT GE CYR SMALL GE +CYR CAPIT GE CYR CAPIT GE +CYR CAPIT DE CYR SMALL DE +CYR CAPIT DE CYR CAPIT DE +CYR SMALL DE CYR SMALL DE +CYR SMALL DE CYR CAPIT DE +CYR CAPIT IE CYR SMALL IE +CYR CAPIT IE CYR CAPIT IE +CYR SMALL IO CYR SMALL IO +CYR SMALL IO CYR CAPIT IO +CYR SMALL IE CYR SMALL IE +CYR SMALL IE CYR CAPIT IE +CYR CAPIT IO CYR SMALL IO +CYR CAPIT IO CYR CAPIT IO +CYR SMALL ZHE CYR SMALL ZHE +CYR SMALL ZHE CYR CAPIT ZHE +CYR CAPIT ZHE CYR SMALL ZHE +CYR CAPIT ZHE CYR CAPIT ZHE +CYR CAPIT ZE CYR SMALL ZE +CYR CAPIT ZE CYR CAPIT ZE +CYR SMALL ZE CYR SMALL ZE +CYR SMALL ZE CYR CAPIT ZE +CYR CAPIT I CYR SMALL I +CYR CAPIT I CYR CAPIT I +CYR SMALL I CYR SMALL I +CYR SMALL I CYR CAPIT I +CYR SMALL KA CYR SMALL KA +CYR SMALL KA CYR CAPIT KA +CYR CAPIT KA CYR SMALL KA +CYR CAPIT KA CYR CAPIT KA +CYR SMALL EL CYR SMALL EL +CYR SMALL EL CYR CAPIT EL +CYR CAPIT EL CYR SMALL EL +CYR CAPIT EL CYR CAPIT EL +CYR SMALL EM CYR SMALL EM +CYR SMALL EM CYR CAPIT EM +CYR CAPIT EM CYR SMALL EM +CYR CAPIT EM CYR CAPIT EM +CYR CAPIT EN CYR SMALL EN +CYR CAPIT EN CYR CAPIT EN +CYR SMALL EN CYR SMALL EN +CYR SMALL EN CYR CAPIT EN +CYR CAPIT O CYR SMALL O +CYR CAPIT O CYR CAPIT O +CYR SMALL O CYR SMALL O +CYR SMALL O CYR CAPIT O +CYR SMALL PE CYR SMALL PE +CYR SMALL PE CYR CAPIT PE +CYR CAPIT PE CYR SMALL PE +CYR CAPIT PE CYR CAPIT PE +CYR SMALL ER CYR SMALL ER +CYR SMALL ER CYR CAPIT ER +CYR CAPIT ER CYR SMALL ER +CYR CAPIT ER CYR CAPIT ER +CYR SMALL ES CYR SMALL ES +CYR SMALL ES CYR CAPIT ES +CYR CAPIT ES CYR SMALL ES +CYR CAPIT ES CYR CAPIT ES +CYR CAPIT TE CYR SMALL TE +CYR CAPIT TE CYR CAPIT TE +CYR SMALL TE CYR SMALL TE +CYR SMALL TE CYR CAPIT TE +CYR SMALL U CYR SMALL U +CYR SMALL U CYR CAPIT U +CYR CAPIT U CYR SMALL U +CYR CAPIT U CYR CAPIT U +CYR SMALL EF CYR SMALL EF +CYR SMALL EF CYR CAPIT EF +CYR CAPIT EF CYR SMALL EF +CYR CAPIT EF CYR CAPIT EF +CYR SMALL HA CYR SMALL HA +CYR SMALL HA CYR CAPIT HA +CYR CAPIT HA CYR SMALL HA +CYR CAPIT HA CYR CAPIT HA +CYR CAPIT TSE CYR SMALL TSE +CYR CAPIT TSE CYR CAPIT TSE +CYR SMALL TSE CYR SMALL TSE +CYR SMALL TSE CYR CAPIT TSE +CYR CAPIT CHE CYR SMALL CHE +CYR CAPIT CHE CYR CAPIT CHE +CYR SMALL CHE CYR SMALL CHE +CYR SMALL CHE CYR CAPIT CHE +CYR SMALL SHA CYR SMALL SHA +CYR SMALL SHA CYR CAPIT SHA +CYR CAPIT SHA CYR SMALL SHA +CYR CAPIT SHA CYR CAPIT SHA +CYR SMALL SCHA CYR SMALL SCHA +CYR SMALL SCHA CYR CAPIT SCHA +CYR CAPIT SCHA CYR SMALL SCHA +CYR CAPIT SCHA CYR CAPIT SCHA +CYR SMALL HARD SIGN CYR SMALL HARD SIGN +CYR SMALL HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT HARD SIGN CYR SMALL HARD SIGN +CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT YERU CYR SMALL YERU +CYR CAPIT YERU CYR CAPIT YERU +CYR SMALL YERU CYR SMALL YERU +CYR SMALL YERU CYR CAPIT YERU +CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN +CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN +CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL E CYR SMALL E +CYR SMALL E CYR CAPIT E +CYR CAPIT E CYR SMALL E +CYR CAPIT E CYR CAPIT E +CYR SMALL YU CYR SMALL YU +CYR SMALL YU CYR CAPIT YU +CYR CAPIT YU CYR SMALL YU +CYR CAPIT YU CYR CAPIT YU +CYR CAPIT YA CYR SMALL YA +CYR CAPIT YA CYR CAPIT YA +CYR SMALL YA CYR SMALL YA +CYR SMALL YA CYR CAPIT YA +ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2 NOT NULL; +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA'); +ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL; +ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL; +UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%'; +UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%'; +UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f=''; +UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f=''; +SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f; +min(comment) count(*) +LAT CAPIT A 2 +LAT CAPIT B 2 +LAT CAPIT C 2 +LAT CAPIT D 2 +LAT CAPIT E 2 +LAT CAPIT F 2 +LAT CAPIT G 2 +LAT CAPIT H 2 +LAT CAPIT I 2 +LAT CAPIT J 2 +LAT CAPIT K 2 +LAT CAPIT L 2 +LAT CAPIT M 2 +LAT CAPIT N 2 +LAT CAPIT O 2 +LAT CAPIT P 2 +LAT CAPIT Q 2 +LAT CAPIT R 2 +LAT CAPIT S 2 +LAT CAPIT T 2 +LAT CAPIT U 2 +LAT CAPIT V 2 +LAT CAPIT W 2 +LAT CAPIT X 2 +LAT CAPIT Y 2 +LAT CAPIT Z 2 +GREEK CAPIT ALPHA 2 +GREEK CAPIT BETA 2 +GREEK CAPIT GAMMA 2 +GREEK CAPIT DELTA 2 +GREEK CAPIT EPSILON 2 +CYR CAPIT A 2 +CYR CAPIT BE 2 +CYR CAPIT VE 2 +CYR CAPIT GE 2 +CYR CAPIT DE 2 +CYR CAPIT IE 4 +CYR CAPIT ZHE 2 +CYR CAPIT ZE 2 +CYR CAPIT I 2 +CYR CAPIT KA 2 +CYR CAPIT EL 2 +CYR CAPIT EM 2 +CYR CAPIT EN 2 +CYR CAPIT O 2 +CYR CAPIT PE 2 +CYR CAPIT ER 2 +CYR CAPIT ES 2 +CYR CAPIT TE 2 +CYR CAPIT U 2 +CYR CAPIT EF 2 +CYR CAPIT HA 2 +CYR CAPIT TSE 2 +CYR CAPIT CHE 2 +CYR CAPIT SHA 2 +CYR CAPIT SCHA 2 +CYR CAPIT HARD SIGN 2 +CYR CAPIT YERU 2 +CYR CAPIT SOFT SIGN 2 +CYR CAPIT E 2 +CYR CAPIT YU 2 +CYR CAPIT YA 2 +ARMENIAN CAPIT AYB 2 +ARMENIAN CAPIT BEN 2 +ARMENIAN CAPIT GIM 2 +ARMENIAN CAPIT DA 2 +ARMENIAN CAPIT ECH 2 +ARMENIAN CAPIT ZA 2 +DROP TABLE t1; diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test new file mode 100644 index 00000000000..7db8f49919b --- /dev/null +++ b/mysql-test/t/ctype_many.test @@ -0,0 +1,189 @@ +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 ( + comment CHAR(32) CHARACTER SET latin1 NOT NULL, + koi8_ru_f CHAR(32) CHARACTER SET koi8_ru NOT NULL +) CHARSET=latin5; + +SHOW CREATE TABLE t1; +ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 CHARSET=latin2; +ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 DROP latin2_f, DROP latin5_f; +SHOW CREATE TABLE t1; + +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA'); + +ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL; +UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8); + +SELECT * FROM t1; + +SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1; +SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1; +SELECT DISTINCT koi8_ru_f FROM t1; +SELECT DISTINCT utf8_f FROM t1; +SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC; +SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC; + +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f +ORDER BY t11.koi8_ru_f; + +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 +WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8_ru) +ORDER BY t12.utf8_f; + +ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2 NOT NULL; + +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA'); + +ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL; +ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL; +UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%'; +UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%'; +UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f=''; +UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f=''; +SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f; +DROP TABLE t1; -- cgit v1.2.1 From 2cf620004e8a15c5d72a27377b536db2394a62d8 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Mon, 1 Jul 2002 14:14:51 +0300 Subject: subselect in having clause fixed bug in sum function in subselect --- mysql-test/r/subselect.result | 12 +++++++-- mysql-test/t/subselect.test | 5 ++++ sql/item.cc | 62 ++++++++++++++++++++++++++++++++++++++----- sql/item.h | 11 +++++--- sql/item_cmpfunc.cc | 21 ++++++++------- sql/item_cmpfunc.h | 18 +++++++------ sql/item_func.cc | 19 ++++++------- sql/item_func.h | 19 ++++++------- sql/item_strfunc.h | 16 ++++++----- sql/item_subselect.cc | 9 +------ sql/item_subselect.h | 2 +- sql/item_sum.cc | 13 ++++----- sql/item_sum.h | 8 +++--- sql/item_uniq.h | 2 +- sql/sql_base.cc | 6 ++--- sql/sql_class.cc | 2 +- sql/sql_class.h | 1 - sql/sql_handler.cc | 2 +- sql/sql_lex.cc | 4 +-- sql/sql_lex.h | 5 +++- sql/sql_prepare.cc | 4 +-- sql/sql_select.cc | 28 ++++++++++++------- sql/sql_yacc.yy | 7 ++--- 23 files changed, 177 insertions(+), 99 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 37a66993ef2..bd92c496f29 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -65,8 +65,8 @@ a select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) 8 7.5000 -8 6.0000 -9 5.5000 +8 4.5000 +9 7.5000 select * from t3 where exists (select * from t2 where t2.b=t3.a); a 7 @@ -74,4 +74,12 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a); a 6 3 +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) +from t2 where t2.b=t4.b); +b ma +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) +from t2 where t2.b=t4.b); +b ma +7 12 drop table t1,t2,t3,t4; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 78300dc3e09..7b1ebdcbc27 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -28,4 +28,9 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; select * from t3 where exists (select * from t2 where t2.b=t3.a); select * from t3 where not exists (select * from t2 where t2.b=t3.a); +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) +from t2 where t2.b=t4.b); +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) +from t2 where t2.b=t4.b); drop table t1,t2,t3,t4; diff --git a/sql/item.cc b/sql/item.cc index 415fe4d72af..81c5168b72d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -446,12 +446,13 @@ String *Item_copy_string::val_str(String *str) /* ARGSUSED */ bool Item::fix_fields(THD *thd, - struct st_table_list *list) + struct st_table_list *list, + Item ** ref) { return 0; } -bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!field) // If field is not checked { @@ -467,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) mention of table name, but if we join tables in one list it will cause error ER_NON_UNIQ_ERROR in find_field_in_tables. */ - SELECT_LEX *last; + SELECT_LEX *last= 0; for (SELECT_LEX *sl= thd->lex.select->outer_select(); sl && !tmp; sl= sl->outer_select()) @@ -476,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) if (!tmp) return 1; else + { + depended_from= last; /* Mark all selects from resolved to 1 before select where was found table as depended (of select where was found table) @@ -493,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) tbl= tbl->next) tbl->shared= 1; } + } } set_field(tmp); } @@ -504,6 +508,14 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) table->used_fields++; table->used_keys&=field->part_of_key; } + if (depended_from != 0 && depended_from->having_fix_field) + { + *ref= new Item_ref((char *)db_name, (char *)table_name, + (char *)field_name); + if (!*ref) + return 1; + return (*ref)->fix_fields(thd, tables, ref); + } return 0; } @@ -787,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet) Find field in select list having the same name */ -bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if (!ref) { - if (!(ref=find_item_in_list(this,thd->lex.select->item_list))) - return 1; + if (!(ref= find_item_in_list(this,thd->lex.select->item_list))) + { + /* + We can't find table field in table list of current select, + consequently we have to find it in outer subselect(s). + We can't join lists of outer & current select, because of scope + of view rules. For example if both tables (outer & current) have + field 'field' it is not mistake to refer to this field without + mention of table name, but if we join tables in one list it will + cause error ER_NON_UNIQ_ERROR in find_field_in_tables. + */ + SELECT_LEX *last=0; + for (SELECT_LEX *sl= thd->lex.select->outer_select(); + sl && !ref; + sl= sl->outer_select()) + ref= find_item_in_list(this, (last= sl)->item_list); + if (!ref) + return 1; + else + { + depended_from= last; + /* + Mark all selects from resolved to 1 before select where was + found table as depended (of select where was found table) + */ + for (SELECT_LEX *s= thd->lex.select; + s &&s != last; + s= s->outer_select()) + if( !s->depended ) + { + s->depended= 1; //Select is depended of outer select + //Tables will be reopened many times + for (TABLE_LIST *tbl= + (TABLE_LIST*)s->table_list.first; + tbl; + tbl= tbl->next) + tbl->shared= 1; + } + } + } max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; diff --git a/sql/item.h b/sql/item.h index e6debdf2afc..187e3903b84 100644 --- a/sql/item.h +++ b/sql/item.h @@ -52,7 +52,7 @@ public: virtual ~Item() { name=0; } /*lint -e1509 */ void set_name(char* str,uint length=0); void init_make_field(Send_field *tmp_field,enum enum_field_types type); - virtual bool fix_fields(THD *,struct st_table_list *); + virtual bool fix_fields(THD *, struct st_table_list *, Item **); virtual bool save_in_field(Field *field); virtual void save_org_in_field(Field *field) { (void) save_in_field(field); } @@ -85,15 +85,18 @@ public: }; +class st_select_lex; class Item_ident :public Item { public: const char *db_name; const char *table_name; const char *field_name; + st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par) - :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par) + :db_name(db_name_par),table_name(table_name_par), + field_name(field_name_par), depended_from(0) { name = (char*) field_name_par; } const char *full_name() const; }; @@ -120,7 +123,7 @@ public: String *str_result(String* tmp); bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); } void make_field(Send_field *field); - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **); bool save_in_field(Field *field); void save_org_in_field(Field *field); table_map used_tables() const; @@ -390,7 +393,7 @@ public: } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } void make_field(Send_field *field) { (*ref)->make_field(field); } - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **); bool save_in_field(Field *field) { return (*ref)->save_in_field(field); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8433ae5bfba..0fc9a1f0e4c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -727,12 +727,12 @@ double Item_func_case::val() bool -Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (first_expr && first_expr->fix_fields(thd,tables) || - else_expr && else_expr->fix_fields(thd,tables)) + if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) || + else_expr && else_expr->fix_fields(thd, tables, &else_expr)) return 1; - if (Item_func::fix_fields(thd,tables)) + if (Item_func::fix_fields(thd, tables, ref)) return 1; if (first_expr) { @@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int() bool -Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) +Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { List_iterator li(list); Item *item; @@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) #endif item= *li.ref(); // new current item } - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, li.ref())) return 1; /* purecov: inspected */ used_tables_cache|=item->used_tables(); with_sum_func= with_sum_func || item->with_sum_func; @@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const return OPTIMIZE_NONE; } -bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) +bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) { - if (Item_bool_func2::fix_fields(thd, tlist)) + if (Item_bool_func2::fix_fields(thd, tlist, ref)) return 1; /* @@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) #ifdef USE_REGEX bool -Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables)) + if (args[0]->fix_fields(thd, tables, args) || + args[1]->fix_fields(thd,tables, args + 1)) return 1; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; max_length=1; decimals=0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 302ad88905e..08c5a30c57c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -177,9 +177,10 @@ public: Item_func_interval(Item *a,List &list) :Item_int_func(list),item(a),intervals(0) {} longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); ~Item_func_interval() { delete item; } @@ -259,7 +260,7 @@ public: enum Item_result result_type () const { return cached_result_type; } const char *func_name() const { return "case"; } void print(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); Item *find_item(String *str); }; @@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func Item_func_in(Item *a,List &list) :Item_int_func(list),item(a),array(0),in_item(0) {} longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); ~Item_func_in() { delete item; delete array; delete in_item; } @@ -505,7 +507,7 @@ public: cond_result eq_cmp_result() const { return COND_TRUE; } const char *func_name() const { return "like"; } void fix_length_and_dec(); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); }; #ifdef USE_REGEX @@ -523,7 +525,7 @@ public: regex_compiled(0),regex_is_const(0) {} ~Item_func_regex(); longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); const char *func_name() const { return "regex"; } }; @@ -552,7 +554,7 @@ public: { list.push_back(i1); list.push_back(i2); } ~Item_cond() { list.delete_elements(); } bool add(Item *item) { return list.push_back(item); } - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **ref); enum Type type() const { return COND_ITEM; } List* argument_list() { return &list; } diff --git a/sql/item_func.cc b/sql/item_func.cc index b14c1b38383..ae3fc7cb8f0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -58,7 +58,7 @@ Item_func::Item_func(List &list) } bool -Item_func::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { Item **arg,**arg_end; char buff[STACK_BUFF_ALLOC]; // Max argument in function @@ -72,7 +72,7 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables) { // Print purify happy for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd,tables)) + if ((*arg)->fix_fields(thd, tables, arg)) return 1; /* purecov: inspected */ if ((*arg)->maybe_null) maybe_null=1; @@ -1102,7 +1102,7 @@ udf_handler::~udf_handler() bool -udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, +udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, uint arg_count, Item **arguments) { char buff[STACK_BUFF_ALLOC]; // Max argument in function @@ -1146,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd,tables)) + if ((*arg)->fix_fields(thd, tables, arg)) return 1; if ((*arg)->binary) func->binary=1; @@ -1765,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, } -bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, + Item **ref) { if (!thd) thd=current_thd; - if (Item_func::fix_fields(thd,tables) || + if (Item_func::fix_fields(thd, tables, ref) || !(entry= get_variable(&thd->user_vars, name, 1))) return 1; entry->update_query_id=thd->query_id; @@ -2095,7 +2096,7 @@ void Item_func_match::init_search(bool no_order) } } -bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) +bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { List_iterator li(fields); Item *item; @@ -2108,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) modifications to find_best and auto_close as complement to auto_init code above. */ - if (Item_func::fix_fields(thd,tlist) || !const_item()) + if (Item_func::fix_fields(thd, tlist, ref) || !const_item()) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST"); return 1; @@ -2116,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) while ((item=li++)) { - if (item->fix_fields(thd,tlist)) + if (item->fix_fields(thd, tlist, li.ref())) return 1; if (item->type() == Item::REF_ITEM) li.replace(item= *((Item_ref *)item)->ref); diff --git a/sql/item_func.h b/sql/item_func.h index 0056126d50e..86b2a17931d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -99,7 +99,7 @@ public: } Item_func(List &list); ~Item_func() {} /* Nothing to do; Items are freed automaticly */ - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *,struct st_table_list *, Item **ref); void make_field(Send_field *field); table_map used_tables() const; void update_used_tables(); @@ -567,9 +567,10 @@ public: Item_func_field(Item *a,List &list) :Item_int_func(list),item(a) {} ~Item_func_field() { delete item; } longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void update_used_tables() { @@ -708,11 +709,11 @@ public: :Item_func(list), udf(udf_arg) {} ~Item_udf_func() {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd,struct st_table_list *tables) + bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref) { - bool res=udf.fix_fields(thd,tables,this,arg_count,args); - used_tables_cache=udf.used_tables_cache; - const_item_cache=udf.const_item_cache; + bool res= udf.fix_fields(thd, tables, this, arg_count, args); + used_tables_cache= udf.used_tables_cache; + const_item_cache= udf.const_item_cache; return res; } Item_result result_type () const { return udf.result_type(); } @@ -867,7 +868,7 @@ public: void update_hash(void *ptr, uint length, enum Item_result type); bool update(); enum Item_result result_type () const { return cached_result_type; } - bool fix_fields(THD *thd,struct st_table_list *tables); + bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); void fix_length_and_dec(); void print(String *str); const char *func_name() const { return "set_user_var"; } @@ -941,7 +942,7 @@ public: } enum Functype functype() const { return FT_FUNC; } void update_used_tables() {} - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); bool eq(const Item *, bool binary_cmp) const; longlong val_int() { return val()!=0.0; } double val(); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a273abaf614..6e15b8317d1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -79,10 +79,10 @@ public: String *val_str(String *); void fix_length_and_dec(); void update_used_tables(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (separator->fix_fields(thd,tlist) - || Item_func::fix_fields(thd,tlist)); + return (separator->fix_fields(thd, tlist, &separator) + || Item_func::fix_fields(thd, tlist, ref)); } const char *func_name() const { return "concat_ws"; } }; @@ -325,9 +325,10 @@ public: double val(); longlong val_int(); String *val_str(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); void update_used_tables(); @@ -344,9 +345,10 @@ public: Item_func_make_set(Item *a,List &list) :Item_str_func(list),item(a) {} ~Item_func_make_set() { delete item; } String *val_str(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); void update_used_tables(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index d8f9cf40d50..2bff2af45e4 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -75,15 +75,8 @@ void Item_subselect::make_field (Send_field *tmp_field) } } -bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - - if (thd->having_fix_field) - { - //TODO: subselects in having do not suported now - my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0)); - return 1; - } // Is it one field subselect? if (select_lex->item_list.elements > max_columns) { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 79832116c67..3f363df33df 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -63,7 +63,7 @@ public: enum Type type() const; bool is_null() { return null_value; } void make_field (Send_field *); - bool fix_fields(THD *thd, TABLE_LIST *tables); + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); table_map used_tables() const; friend class select_subselect; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 6ef968c33f7..809dd65d52b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -112,7 +112,7 @@ Item_sum_int::val_str(String *str) bool -Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) +Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!thd->allow_sum_func) { @@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) maybe_null=0; for (uint i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd,tables)) + if (args[i]->fix_fields(thd, tables, args + i)) return 1; if (decimals < args[i]->decimals) decimals=args[i]->decimals; @@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) bool -Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) +Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { Item *item=args[0]; if (!thd->allow_sum_func) @@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) return 1; } thd->allow_sum_func=0; // No included group funcs - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, args)) return 1; hybrid_type=item->result_type(); if (hybrid_type == INT_RESULT) @@ -930,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct() } -bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables, + Item **ref) { - if (Item_sum_num::fix_fields(thd,tables) || + if (Item_sum_num::fix_fields(thd, tables, ref) || !(tmp_table_param= new TMP_TABLE_PARAM)) return 1; return 0; diff --git a/sql/item_sum.h b/sql/item_sum.h index a963799b6a7..3e67f1e3624 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -80,7 +80,7 @@ public: Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List &list) :Item_sum(list) {} - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, TABLE_LIST *, Item **); longlong val_int() { return (longlong) val(); } /* Real as default */ String *val_str(String*str); void reset_field(); @@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int { TABLE *table; table_map used_table_cache; - bool fix_fields(THD *thd,TABLE_LIST *tables); + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); uint32 *field_lengths; TMP_TABLE_PARAM *tmp_table_param; TREE tree; @@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign), used_table_cache(~(table_map) 0) {} - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, TABLE_LIST *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -382,7 +382,7 @@ public: { quick_group=0;} ~Item_udf_sum() {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd,struct st_table_list *tables) + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { return udf.fix_fields(thd,tables,this,this->arg_count,this->args); } diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 4be64ecc74a..e56632e7289 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -42,5 +42,5 @@ public: bool add() { return 0; } void reset_field() {} void update_field(int offset) {} - bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;} + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;} }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 92606716c63..b3ef043f582 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1874,7 +1874,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List &fields, } else { - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, it.ref())) DBUG_RETURN(-1); /* purecov: inspected */ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && sum_func_list) @@ -2025,7 +2025,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) if (*conds) { thd->where="where clause"; - if ((*conds)->fix_fields(thd,tables)) + if ((*conds)->fix_fields(thd, tables, conds)) DBUG_RETURN(1); } @@ -2036,7 +2036,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) { /* Make a join an a expression */ thd->where="on clause"; - if (table->on_expr->fix_fields(thd,tables)) + if (table->on_expr->fix_fields(thd, tables, &table->on_expr)) DBUG_RETURN(1); thd->cond_count++; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c8914702ae7..9922eacdec1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -81,7 +81,7 @@ static void free_var(user_var_entry *entry) THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), insert_id_used(0), in_lock_tables(0), - global_read_lock(0), bootstrap(0), having_fix_field(0) + global_read_lock(0), bootstrap(0) { host=user=priv_user=db=query=ip=0; host_or_ip="unknown ip"; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9b708e35a1e..a6b7e45ab03 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -453,7 +453,6 @@ public: bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; - bool having_fix_field; //TRUE when having fix field called bool prepare_command; ulong param_count,current_param_number; Error err_list; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 4ecd5dbca36..a98012653b3 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && cond->fix_fields(thd,tables)) + if (cond && cond->fix_fields(thd, tables, &cond)) return -1; if (keyname) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index bcf212f6bd2..9ae5cdeeb15 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -942,8 +942,8 @@ void st_select_lex::init_select() interval_list.empty(); use_index.empty(); ftfunc_list.empty(); - linkage=UNSPECIFIED_TYPE; - depended= 0; + linkage= UNSPECIFIED_TYPE; + depended= having_fix_field= 0; } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ca824b3eab8..f4e788b67e2 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -253,7 +253,10 @@ public: uint in_sum_expr; bool create_refs, braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ - depended; /* depended from outer select subselect */ + depended, /* depended from outer select subselect */ + /* TRUE when having fix field called in processing of this SELECT */ + having_fix_field; + void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d5896901935..d41aca21fb8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -448,7 +448,7 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, List &fields, List &values, COND *conds, ORDER *order, ORDER *group, - Item *having,thr_lock_type lock_type) + Item *having, thr_lock_type lock_type) { TABLE *table; bool hidden_group_fields; @@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, { thd->where="having clause"; thd->allow_sum_func=1; - if (having->fix_fields(thd,tables) || thd->fatal_error) + if (having->fix_fields(thd, tables, &having) || thd->fatal_error) DBUG_RETURN(1); if (having->with_sum_func) having->split_sum_func(all_fields); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 025a5c600a5..d70b7dfdbed 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -227,10 +227,9 @@ JOIN::prepare(TABLE_LIST *tables_init, { thd->where="having clause"; thd->allow_sum_func=1; - bool having_fix_field_store= thd->having_fix_field; - thd->having_fix_field= 1; - bool having_fix_rc= having->fix_fields(thd,tables_list); - thd->having_fix_field= having_fix_field_store; + select_lex->having_fix_field= 1; + bool having_fix_rc= having->fix_fields(thd, tables_list, &having); + select_lex->having_fix_field= 0; if (having_fix_rc || thd->fatal_error) DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) @@ -349,7 +348,7 @@ JOIN::optimize() } else if ((conds=new Item_cond_and(conds,having))) { - conds->fix_fields(thd, tables_list); + conds->fix_fields(thd, tables_list, &conds); conds->change_ref_to_fields(thd, tables_list); having= 0; } @@ -612,6 +611,15 @@ JOIN::reinit() if (setup_tables(tables_list)) DBUG_RETURN(1); + + // Reset of sum functions + first_record= 0; + if (sum_funcs) + { + Item_sum *func, **func_ptr= sum_funcs; + while ((func= *(func_ptr++))) + func->null_value= 1; + } DBUG_RETURN(0); } @@ -3381,7 +3389,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) 21)))) { cond=new_cond; - cond->fix_fields(thd,0); + cond->fix_fields(thd, 0, &cond); } thd->insert_id(0); // Clear for next request } @@ -3395,7 +3403,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2)))) { cond=new_cond; - cond->fix_fields(thd,0); + cond->fix_fields(thd, 0, &cond); } } } @@ -6429,7 +6437,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List &fields, return 0; } order->in_field_list=0; - if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error) + if ((*order->item)->fix_fields(thd, tables, order->item) || thd->fatal_error) return 1; // Wrong field all_fields.push_front(*order->item); // Add new field to field list order->item=(Item**) all_fields.head_ref(); @@ -6527,7 +6535,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, else { thd->where="procedure list"; - if ((*new_field->item)->fix_fields(thd,tables)) + if ((*new_field->item)->fix_fields(thd, tables, new_field->item)) DBUG_RETURN(1); /* purecov: inspected */ thd->where=0; all_fields.push_front(*new_field->item); @@ -7092,7 +7100,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) Here we pass 0 as the first argument to fix_fields that don't need to do any stack checking (This is already done in the initial fix_fields). */ - cond->fix_fields((THD *) 0,(TABLE_LIST *) 0); + cond->fix_fields((THD *) 0,(TABLE_LIST *) 0, (Item**)&cond); if (join_tab->select) { error=(int) cond->add(join_tab->select->cond); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index faa63afa6c7..f237aac81d3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2973,7 +2973,7 @@ kill: KILL_SYM expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd,0)) + if ($2->fix_fields(lex->thd, 0, &$2)) { send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; @@ -3469,7 +3469,8 @@ option_value: | '@' ident_or_text equal expr { Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); - if (item->fix_fields(current_thd,0) || item->update()) + if (item->fix_fields(current_thd, 0, (Item**) &item) || + item->update()) { send_error(¤t_thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; @@ -3501,7 +3502,7 @@ option_value: { THD *thd=current_thd; Item *item= $3; - if (item->fix_fields(current_thd,0)) + if (item->fix_fields(current_thd, 0, &item)) { send_error(&thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; -- cgit v1.2.1 From 0c6cb114e2d6c922e6e15fe6ebec38b55a4a982a Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Mon, 1 Jul 2002 19:06:24 +0300 Subject: subselect clean up fix after automerge --- sql/item_strfunc.cc | 2 +- sql/sql_lex.h | 4 +++- sql/sql_select.cc | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5bb2c4015ad..1aee4e7d553 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1922,7 +1922,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables) if (thd && check_stack_overrun(thd,buff)) return 0; // Fatal error if flag is set! - if (args[0]->fix_fields(thd,tables)) + if (args[0]->fix_fields(thd, tables, args)) return 1; maybe_null=args[0]->maybe_null; binary=args[0]->binary; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c3a4526e052..658c1dc2cdb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -240,6 +240,7 @@ typedef struct st_select_lex_unit SELECT_LEX_UNIT; /* SELECT_LEX - store information of parsed SELECT_LEX statment */ +class JOIN; class st_select_lex: public st_select_lex_node { public: char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ @@ -251,12 +252,13 @@ public: List interval_list, use_index, *use_index_ptr, ignore_index, *ignore_index_ptr; List ftfunc_list; + JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ uint in_sum_expr; bool create_refs, braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ depended, /* depended from outer select subselect */ /* TRUE when having fix field called in processing of this SELECT */ - having_fix_field; + having_fix_field;e void init_query(); void init_select(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8dd611add86..76f78009e84 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -211,6 +211,7 @@ JOIN::prepare(TABLE_LIST *tables_init, proc_param= proc_param_init; tables_list= tables_init; select_lex= select; + select->join= this; union_part= (unit->first_select()->next_select() != 0); /* Check that all tables, fields, conds and order are ok */ @@ -974,6 +975,21 @@ JOIN::cleanup(THD *thd) delete select; delete_dynamic(&keyuse); delete procedure; + for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); + unit != 0; + unit= unit->next_unit()) + for (SELECT_LEX *sl= unit->first_select(); + sl != 0; + sl= sl->next_select()) + { + if (sl->join) + { + int err= sl->join->cleanup(thd); + if (err) + error= err; + sl->join= 0; + } + } return error; } -- cgit v1.2.1 From ba30e55d4bc979d24eda724e2ef7642beeaa1849 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Mon, 1 Jul 2002 19:13:14 +0300 Subject: typo fixed --- sql/sql_lex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 658c1dc2cdb..7234a7a92ff 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -258,7 +258,7 @@ public: braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ depended, /* depended from outer select subselect */ /* TRUE when having fix field called in processing of this SELECT */ - having_fix_field;e + having_fix_field; void init_query(); void init_select(); -- cgit v1.2.1 From 189d1dd630676a2e3be004d27770ae820e81b36b Mon Sep 17 00:00:00 2001 From: "bar@gw.udmsearch.izhnet.ru" <> Date: Tue, 2 Jul 2002 14:31:54 +0500 Subject: SHOW CREATE DATABASE name; Small fixes in database default charset code --- sql/mysql_priv.h | 1 + sql/sql_db.cc | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- sql/sql_lex.h | 1 + sql/sql_parse.cc | 19 +++++++++++- sql/sql_yacc.yy | 5 ++++ 5 files changed, 115 insertions(+), 2 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2992f11ef65..c0371d1e90c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -472,6 +472,7 @@ int mysqld_show_logs(THD *thd); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1); int mysqld_show_create(THD *thd, TABLE_LIST *table_list); +int mysqld_show_create_db(THD *thd, const char *dbname); void mysqld_list_processes(THD *thd,const char *user,bool verbose); int mysqld_show_status(THD *thd); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 63edebd4ac7..7e82e1433b9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -106,7 +106,7 @@ static int load_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) for( ; (le[0]=='\r' || le[0]=='\n') ; le++); if (!strcmp(ln,"default-character-set") && val && val[0]) { - thd->db_charset=get_charset_by_name(val, MYF(0)); + create->table_charset=get_charset_by_name(val, MYF(0)); } goto cnt; break; @@ -568,3 +568,92 @@ bool mysql_change_db(THD *thd,const char *name) DBUG_RETURN(0); } + + +int mysqld_show_create_db(THD *thd,const char *name) +{ + int length, db_length; + char *dbname=my_strdup((char*) name,MYF(MY_WME)); + char path[FN_REFLEN]; + uint db_access; + HA_CREATE_INFO create; + CONVERT *convert=thd->convert_set; + + DBUG_ENTER("mysql_show_create_db"); + + if (!dbname || !(db_length=strip_sp(dbname))) + { + x_free(dbname); /* purecov: inspected */ + send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ + } + + if ((db_length > NAME_LEN) || check_db_name(dbname)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, dbname); + x_free(dbname); + DBUG_RETURN(1); + } + + if (test_all_bits(thd->master_access,DB_ACLS)) + db_access=DB_ACLS; + else + db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, + thd->priv_user,dbname) | + thd->master_access); + if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + { + net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + thd->priv_user, + thd->host_or_ip, + dbname); + mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + thd->priv_user, + thd->host_or_ip, + dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + + (void) sprintf(path,"%s/%s",mysql_data_home,dbname); + length=unpack_dirname(path,path); // Convert if not unix + if (length && path[length-1] == FN_LIBCHAR) + path[length-1]=0; // remove ending '\' + if (access(path,F_OK)) + { + net_printf(&thd->net,ER_BAD_DB_ERROR,dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,MY_DB_OPT_FILE); + bzero(&create,sizeof(create)); + load_db_opt(thd,name,&create,path); + + List field_list; + field_list.push_back(new Item_empty_string("Database",NAME_LEN)); + field_list.push_back(new Item_empty_string("Create Database",1024)); + + if (send_fields(thd,field_list,1)) + DBUG_RETURN(1); + + String *packet = &thd->packet; + packet->length(0); + net_store_data(packet, convert, name); + sprintf(path, "CREATE DATABASE %s", name); + if (create.table_charset) + { + strcat(path," DEFAULT CHARACTER SET "); + strcat(path,create.table_charset->name); + } + net_store_data(packet, convert, path); + + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + DBUG_RETURN(1); + + send_eof(&thd->net); + + DBUG_RETURN(0); +} diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7234a7a92ff..470230c0999 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -42,6 +42,7 @@ enum enum_sql_command { SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, + SQLCOM_SHOW_CREATE_DB, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 43cb056ffc8..e006855105c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2335,7 +2335,7 @@ mysql_execute_command(void) net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); break; } - if (check_access(thd,DROP_ACL,lex->name,0,1)) + if (check_access(thd,ALTER_ACL,lex->name,0,1)) break; if (thd->locked_tables || thd->active_transaction()) { @@ -2345,6 +2345,23 @@ mysql_execute_command(void) res=mysql_alter_db(thd,lex->name,&lex->create_info,0); break; } + case SQLCOM_SHOW_CREATE_DB: + { + if (!strip_sp(lex->name) || check_db_name(lex->name)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + break; + } + if (check_access(thd,DROP_ACL,lex->name,0,1)) + break; + if (thd->locked_tables || thd->active_transaction()) + { + send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + goto error; + } + res=mysqld_show_create_db(thd,lex->name); + break; + } case SQLCOM_CREATE_FUNCTION: if (check_access(thd,INSERT_ACL,"mysql",0,1)) break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e96c72ab04b..160bc253dc9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2851,6 +2851,11 @@ show_param: lex->grant_user=$3; lex->grant_user->password.str=NullS; } + | CREATE DATABASE ident + { + Lex->sql_command=SQLCOM_SHOW_CREATE_DB; + Lex->name=$3.str; + } | CREATE TABLE_SYM table_ident { Lex->sql_command = SQLCOM_SHOW_CREATE; -- cgit v1.2.1 From 86a01b39ef94566c91678c090c12a8d45d48cb54 Mon Sep 17 00:00:00 2001 From: "walrus@mysql.com" <> Date: Wed, 3 Jul 2002 07:17:35 +0200 Subject: server-cfg.sh remove %smds, remove conversation from date to int for mysql, server-cfg.sh set bdb as transactional --- BitKeeper/etc/logging_ok | 1 + sql-bench/server-cfg.sh | 176 ++--------------------------------------------- 2 files changed, 6 insertions(+), 171 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 0ed14928cdb..ffac1d8c3cd 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -68,3 +68,4 @@ worm@altair.is.lan zak@balfor.local zak@linux.local venu@myvenu.com +walrus@mysql.com diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index a4e74fcb4f9..e82fd5d5907 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -115,7 +115,6 @@ sub new $self->{'data_source'} = "DBI:mysql:database=$database;host=$host"; $self->{'data_source'} .= ";mysql_socket=$socket" if($socket); $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -168,25 +167,6 @@ sub new $limits{'working_all_fields'} = 1; $limits{'working_blobs'} = 1; # If big varchar/blobs works - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; - # Some fixes that depends on the environment if (defined($main::opt_create_options) && $main::opt_create_options =~ /type=heap/i) @@ -199,6 +179,11 @@ sub new $limits{'max_text_size'} = 8000; # Limit in Innobase $self->{'transactions'} = 1; # Transactions enabled } + if (defined($main::opt_create_options) && + $main::opt_create_options =~ /type=bdb/i) + { + $self->{'transactions'} = 1; # Transactions enabled + } if (defined($main::opt_create_options) && $main::opt_create_options =~ /type=gemini/i) { @@ -266,7 +251,6 @@ sub create { $field =~ s/ decimal/ double(10,2)/i; $field =~ s/ big_decimal/ double(10,2)/i; - $field =~ s/ date/ int/i; # Because of tcp ? $query.= $field . ','; } foreach $index (@$index) @@ -575,7 +559,6 @@ sub new $self->{'cmp_name'} = "pg"; $self->{'data_source'} = "DBI:Pg:dbname=$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; @@ -626,27 +609,6 @@ sub new $limits{'working_all_fields'} = 1; $limits{'working_blobs'} = 1; # If big varchar/blobs works - # the different cases per query ... - $smds{'q1'} = 'b'; # with time - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time - $smds{'q4'} = 'c'; # with time - $smds{'q5'} = 'b'; # with time - $smds{'q6'} = 'c'; # strange error .... - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; # needs 128M to execute - can't do insert ...group by - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; # can't do float8 * int4 - create operator - $smds{'q12'} = 'd'; # strange error??? - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; # strange error??? - $smds{'q15'} = 'd'; # strange error??? - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -871,7 +833,6 @@ sub new $self->{'cmp_name'} = "solid"; $self->{'data_source'} = "DBI:Solid:"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long varchar"; $self->{'text'} = "long varchar"; $self->{'double_quotes'} = 1; @@ -922,28 +883,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - # for the smds small benchmark test .... - # the different cases per query ... - $smds{'q1'} = 'a'; - $smds{'q2'} = ''; - $smds{'q3'} = 'b'; #doesn't work -> strange error about column -fixed - $smds{'q4'} = 'a'; - $smds{'q5'} = 'b'; - $smds{'q6'} = 'c'; - $smds{'q7'} = 'b'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'b'; - $smds{'q10'} = 'b'; - $smds{'q11'} = ''; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'b'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = ''; - $smds{'q17'} = ''; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -1119,7 +1058,6 @@ sub new $self->{'cmp_name'} = "empress"; $self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -1172,28 +1110,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - # for the smds small benchmark test .... - # the different cases per query ... EMPRESS - $smds{'q1'} = 'a'; - $smds{'q2'} = ''; - $smds{'q3'} = 'a'; - $smds{'q4'} = 'a'; - $smds{'q5'} = 'a'; - $smds{'q6'} = 'a'; - $smds{'q7'} = 'b'; - $smds{'q8'} = 'd'; - $smds{'q9'} = 'b'; - $smds{'q10'} = 'a'; - $smds{'q11'} = ''; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'b'; - $smds{'q14'} = 'b'; - $smds{'q15'} = 'a'; - $smds{'q16'} = ''; - $smds{'q17'} = ''; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -1410,7 +1326,6 @@ sub new $self->{'cmp_name'} = "Oracle"; $self->{'data_source'} = "DBI:Oracle:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long"; $self->{'text'} = "long"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -1464,24 +1379,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -1675,7 +1572,6 @@ sub new $self->{'cmp_name'} = "Informix"; $self->{'data_source'} = "DBI:Informix:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "byte in table"; $self->{'text'} = "byte in table"; $self->{'double_quotes'} = 0; # Can handle: 'Walker''s' @@ -1888,7 +1784,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = "blob"; # text ? $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2071,7 +1966,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2264,7 +2158,6 @@ sub new $self->{'data_source'} .= ";hostname=$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2497,7 +2390,6 @@ sub new $self->{'cmp_name'} = "Adabas"; $self->{'data_source'} = "DBI:Adabas:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long"; $self->{'text'} = "long"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2549,24 +2441,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -2718,7 +2592,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "varchar(255)"; $self->{'text'} = "varchar(255)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2894,7 +2767,6 @@ sub new $self->{'cmp_name'} = "mimer"; $self->{'data_source'} = "DBI:mimer:$database:$host"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "binary varying(15000)"; $self->{'text'} = "character varying(15000)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2950,24 +2822,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -3112,7 +2966,6 @@ sub new $self->{'cmp_name'} = "interbase"; $self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = ""; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -3166,24 +3019,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -3331,7 +3166,6 @@ sub new $self->{'cmp_name'} = "FrontBase"; $self->{'data_source'} = "DBI:FB:dbname=$database;host=$host"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "varchar(8000000)"; $self->{'text'} = "varchar(8000000)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' -- cgit v1.2.1 From 984c84c2347395e5364100a2039b588bab0136f3 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Fri, 5 Jul 2002 08:15:57 +0300 Subject: cleanup --- sql/item_subselect.h | 2 +- sql/sql_lex.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 3f363df33df..88ea01f9c68 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -20,7 +20,7 @@ #pragma interface /* gcc class implementation */ #endif -struct st_select_lex; +class st_select_lex; class JOIN; class select_subselect; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 470230c0999..af80b175cd3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -236,7 +236,7 @@ private: bool create_total_list_n_last_return(THD *thd, st_lex *lex, TABLE_LIST ***result); }; -typedef struct st_select_lex_unit SELECT_LEX_UNIT; +typedef class st_select_lex_unit SELECT_LEX_UNIT; /* SELECT_LEX - store information of parsed SELECT_LEX statment @@ -284,7 +284,7 @@ public: friend void mysql_init_query(THD *thd); }; -typedef struct st_select_lex SELECT_LEX; +typedef class st_select_lex SELECT_LEX; class Set_option :public Sql_alloc { public: -- cgit v1.2.1