diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 8d647ef0d82..52c1951f48f 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -72,6 +72,12 @@ if (@config_env > 0) $opt_config_env= join(" ", @config_env); } +if (@config_env > 0) +{ + chomp(@config_env); + $opt_config_env= join(" ", @config_env); +} + chomp($host=`hostname`); $full_host_name=$host; $connect_option= ($opt_tcpip ? "--host=$host" : ""); diff --git a/configure.in b/configure.in index 2ac8e050ae5..d25041dea7a 100644 --- a/configure.in +++ b/configure.in @@ -15,6 +15,7 @@ SHARED_LIB_VERSION=12:0:0 # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|-.*$||"` +MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"` MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"` F_PART=`echo $MYSQL_BASE_VERSION | sed -e "s|\.||g"| sed -e "s|[a-zA-Z]\+||"|sed -e "s|^\(..\)$|\\10|"` L_PART=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|^[[0-9]]\.[[0-9]]*\.||" | sed -e "s|^\(.\)$|0\\1|" | sed -e "s|[[a-z]]||"` diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index 2a7643551ad..03f15031fdf 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -90,6 +90,12 @@ ut_malloc_low( "InnoDB: on Linux we get a stack trace.\n", n, ut_total_allocated_memory, errno); + /* Flush stderr to make more probable that the error + message gets in the error file before we generate a seg + fault */ + + fflush(stderr); + os_fast_mutex_unlock(&ut_list_mutex); /* Make an intentional seg fault so that we get a stack diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index f666c5311b8..6afa74d20e2 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -52,24 +52,3 @@ select min(big),max(big),max(big)-1 from t1 group by a; min(big) max(big) max(big)-1 -1 9223372036854775807 9223372036854775806 drop table t1; -select CAST(1-2 AS UNSIGNED); -CAST(1-2 AS UNSIGNED) -18446744073709551615 -select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); -CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER) --1 -select CONVERT('-1',UNSIGNED); -CONVERT('-1',UNSIGNED) -18446744073709551615 -select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; -cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1 -18446744073709551611 18446744073709551611 -select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; -cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1 -18446744073709551610 18446744073709551612 -select ~5, cast(~5 as signed); -~5 cast(~5 as signed) -18446744073709551610 -6 -select cast(5 as unsigned) -6.0; -cast(5 as unsigned) -6.0 --1.0 diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result new file mode 100644 index 00000000000..572b32c171c --- /dev/null +++ b/mysql-test/r/cast.result @@ -0,0 +1,39 @@ +select CAST(1-2 AS UNSIGNED); +CAST(1-2 AS UNSIGNED) +18446744073709551615 +select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); +CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER) +-1 +select CONVERT('-1',UNSIGNED); +CONVERT('-1',UNSIGNED) +18446744073709551615 +select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; +cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1 +18446744073709551611 18446744073709551611 +select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; +cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1 +18446744073709551610 18446744073709551612 +select ~5, cast(~5 as signed); +~5 cast(~5 as signed) +18446744073709551610 -6 +select cast(5 as unsigned) -6.0; +cast(5 as unsigned) -6.0 +-1.0 +select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; +cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A" +0 1 +select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); +cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME) +2001-1-1 2001-1-1 +select cast("1:2:3" as TIME); +cast("1:2:3" as TIME) +1:2:3 +select cast("2001-1-1" as date) = "2001-01-01"; +cast("2001-1-1" as date) = "2001-01-01" +0 +select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"; +cast("2001-1-1" as datetime) = "2001-01-01 00:00:00" +0 +select cast("1:2:3" as TIME) = "1:02:03"; +cast("1:2:3" as TIME) = "1:02:03" +0 diff --git a/mysql-test/r/constraints.result b/mysql-test/r/constraints.result new file mode 100644 index 00000000000..3b41e291e0f --- /dev/null +++ b/mysql-test/r/constraints.result @@ -0,0 +1,16 @@ +drop table if exists t1; +create table t1 (a int check (a>0)); +insert into t1 values (1); +insert into t1 values (0); +drop table t1; +create table t1 (a int ,b int, check a>b); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int ,b int, constraint abc check (a>b)); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int null); +insert into t1 values (1),(NULL); +drop table t1; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4a1012f73bf..2941352c776 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -24,6 +24,12 @@ now()-curdate()*1000000-curtime() select strcmp(current_timestamp(),concat(current_date()," ",current_time())); strcmp(current_timestamp(),concat(current_date()," ",current_time())) 0 +select strcmp(localtime(),concat(current_date()," ",current_time())); +strcmp(localtime(),concat(current_date()," ",current_time())) +0 +select strcmp(localtimestamp(),concat(current_date()," ",current_time())); +strcmp(localtimestamp(),concat(current_date()," ",current_time())) +0 select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w"); date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w") January Thursday 2nd 1997 97 01 02 03 04 05 4 diff --git a/mysql-test/r/innodb-deadlock.result b/mysql-test/r/innodb-deadlock.result new file mode 100644 index 00000000000..121bfa8c6cb --- /dev/null +++ b/mysql-test/r/innodb-deadlock.result @@ -0,0 +1,20 @@ +drop table if exists t1; +create table t1 (id integer, x integer) type=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; +id x +0 0 +set autocommit=0; +update t1 set x=2 where id = 0; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +commit; +commit; +select * from t1; +id x +0 2 +commit; +drop table t1; diff --git a/mysql-test/r/innodb_cache.result b/mysql-test/r/innodb_cache.result index eaa030046da..47abcb45fe5 100644 --- a/mysql-test/r/innodb_cache.result +++ b/mysql-test/r/innodb_cache.result @@ -98,3 +98,13 @@ commit; show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 1 +drop table if exists t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=InnoDB; +select count(*) from t1; +count(*) +0 +insert into t1 (id) values (0); +select count(*) from t1; +count(*) +1 +drop table t1; diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 85687df411b..484437959a0 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -228,3 +228,36 @@ alter table t1 add key id (id); select * from t1, t2 where t1.id = t2.id; id id drop table t1,t2; +create table t1 ( +id integer, +id2 integer not null, +index (id), +index (id2) +); +insert into t1 values(null,null),(1,1); +select * from t1; +id id2 +NULL 0 +1 1 +select * from t1 where id <=> null; +id id2 +NULL 0 +select * from t1 where id <=> null or id > 0; +id id2 +NULL 0 +1 1 +select * from t1 where id is null or id > 0; +id id2 +NULL 0 +1 1 +select * from t1 where id2 <=> null or id2 > 0; +id id2 +1 1 +select * from t1 where id2 is null or id2 > 0; +id id2 +1 1 +delete from t1 where id <=> NULL; +select * from t1; +id id2 +1 1 +drop table t1; diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 15b35ac7c87..15c61c2c0dc 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -35,11 +35,3 @@ alter table t1 modify big bigint not null; select min(big),max(big),max(big)-1 from t1; select min(big),max(big),max(big)-1 from t1 group by a; drop table t1; - -select CAST(1-2 AS UNSIGNED); -select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); -select CONVERT('-1',UNSIGNED); -select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; -select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; -select ~5, cast(~5 as signed); -select cast(5 as unsigned) -6.0; diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test new file mode 100644 index 00000000000..7a120ef5005 --- /dev/null +++ b/mysql-test/t/cast.test @@ -0,0 +1,22 @@ +# +# Test of cast function +# + +select CAST(1-2 AS UNSIGNED); +select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER); +select CONVERT('-1',UNSIGNED); +select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1; +select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1; +select ~5, cast(~5 as signed); +select cast(5 as unsigned) -6.0; +select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A"; +select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); +select cast("1:2:3" as TIME); + +# +# The following should be fixed in 4.1 +# + +select cast("2001-1-1" as date) = "2001-01-01"; +select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"; +select cast("1:2:3" as TIME) = "1:02:03"; diff --git a/mysql-test/t/constraints.test b/mysql-test/t/constraints.test new file mode 100644 index 00000000000..8682cdc42a2 --- /dev/null +++ b/mysql-test/t/constraints.test @@ -0,0 +1,21 @@ +# +# Testing of constraints +# Currently MySQL only ignores the syntax. +# +drop table if exists t1; + +create table t1 (a int check (a>0)); +insert into t1 values (1); +insert into t1 values (0); +drop table t1; +create table t1 (a int ,b int, check a>b); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int ,b int, constraint abc check (a>b)); +insert into t1 values (1,0); +insert into t1 values (0,1); +drop table t1; +create table t1 (a int null); +insert into t1 values (1),(NULL); +drop table t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 2ff57959965..dd589ff2e66 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -12,6 +12,8 @@ select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"), select sec_to_time(time_to_sec('-838:59:59')); select now()-curdate()*1000000-curtime(); select strcmp(current_timestamp(),concat(current_date()," ",current_time())); +select strcmp(localtime(),concat(current_date()," ",current_time())); +select strcmp(localtimestamp(),concat(current_date()," ",current_time())); select date_format("1997-01-02 03:04:05", "%M %W %D %Y %y %m %d %h %i %s %w"); select date_format("1997-01-02", concat("%M %W %D ","%Y %y %m %d %h %i %s %w")); select dayofmonth("1997-01-02"),dayofmonth(19970323); @@ -164,6 +166,7 @@ select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1; drop table t1; + # # Test problem with TIMESTAMP and BETWEEN # diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test new file mode 100644 index 00000000000..bc2839bfb3a --- /dev/null +++ b/mysql-test/t/innodb-deadlock.test @@ -0,0 +1,38 @@ +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1; + +# +# Testing of FOR UPDATE +# + +connection con1; +create table t1 (id integer, x integer) type=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; + +connection con2; +set autocommit=0; + +# The following query should hang because con1 is locking the page +--send +update t1 set x=2 where id = 0; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +commit; + +connection con1; +select * from t1; +commit; + +drop table t1; diff --git a/mysql-test/t/innodb_cache.test b/mysql-test/t/innodb_cache.test index 21d30420eaf..9066a5f19ba 100644 --- a/mysql-test/t/innodb_cache.test +++ b/mysql-test/t/innodb_cache.test @@ -47,4 +47,11 @@ select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; commit; -show status like "Qcache_queries_in_cache"; \ No newline at end of file +show status like "Qcache_queries_in_cache"; + +drop table if exists t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=InnoDB; +select count(*) from t1; +insert into t1 (id) values (0); +select count(*) from t1; +drop table t1; diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test index 3ab8b993f43..b1cbd5cdfb0 100644 --- a/mysql-test/t/null_key.test +++ b/mysql-test/t/null_key.test @@ -135,3 +135,24 @@ select * from t1, t2 where t1.id = t2.id; alter table t1 add key id (id); select * from t1, t2 where t1.id = t2.id; drop table t1,t2; + +# +# Check bug when doing <=> NULL on an indexed null field +# + +create table t1 ( + id integer, + id2 integer not null, + index (id), + index (id2) +); +insert into t1 values(null,null),(1,1); +select * from t1; +select * from t1 where id <=> null; +select * from t1 where id <=> null or id > 0; +select * from t1 where id is null or id > 0; +select * from t1 where id2 <=> null or id2 > 0; +select * from t1 where id2 is null or id2 > 0; +delete from t1 where id <=> NULL; +select * from t1; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index b2cf86a6abc..cdd007f2cc2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -314,7 +314,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) } #endif #ifdef HAVE_QUERY_CACHE - if (transaction_commited) + if (transaction_commited && thd->transaction.changed_tables) query_cache.invalidate(thd->transaction.changed_tables); #endif /*HAVE_QUERY_CACHE*/ if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) diff --git a/sql/item.h b/sql/item.h index 39e90cef561..bed59b99def 100644 --- a/sql/item.h +++ b/sql/item.h @@ -86,12 +86,14 @@ public: virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_time(TIME *ltime); virtual bool is_null() { return 0; }; - virtual CHARSET_INFO *thd_charset() const; - virtual CHARSET_INFO *charset() const { return str_value.charset(); }; - virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } - virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } virtual bool check_loop(uint id); virtual void top_level_item() {} + + virtual bool binary() const + { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } + CHARSET_INFO *thd_charset() const; + CHARSET_INFO *charset() const { return str_value.charset(); }; + void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } }; diff --git a/sql/item_create.cc b/sql/item_create.cc index ad9058c1691..aa3e7779d73 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -432,6 +432,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type) LINT_INIT(res); switch (cast_type) { case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; + case ITEM_CAST_CHAR: res= new Item_char_typecast(a); break; case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break; case ITEM_CAST_DATE: res= new Item_date_typecast(a); break; diff --git a/sql/item_func.h b/sql/item_func.h index b3daa0d4890..38f461acc13 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1124,5 +1124,5 @@ public: enum Item_cast { ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT, - ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME + ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6a0aaa3b032..fc3b4da8561 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1363,17 +1363,19 @@ String *Item_func_decode::val_str(String *str) String *Item_func_database::val_str(String *str) { - if (!current_thd->db) + THD *thd= current_thd; + if (!thd->db) str->length(0); else - str->copy((const char*) current_thd->db,(uint) strlen(current_thd->db), system_charset_info, thd_charset()); + str->copy((const char*) thd->db,(uint) strlen(thd->db), + system_charset_info, thd->thd_charset); return str; } String *Item_func_user::val_str(String *str) { THD *thd=current_thd; - CHARSET_INFO *cs=thd_charset(); + CHARSET_INFO *cs=thd->thd_charset; const char *host=thd->host ? thd->host : thd->ip ? thd->ip : ""; uint32 res_length=(strlen(thd->user)+strlen(host)+10) * cs->mbmaxlen; @@ -2130,7 +2132,8 @@ String *Item_func_charset::val_str(String *str) if ((null_value=(args[0]->null_value || !res->charset()))) return 0; - str->copy(res->charset()->name,strlen(res->charset()->name),my_charset_latin1,thd_charset()); + str->copy(res->charset()->name,strlen(res->charset()->name), + my_charset_latin1, thd_charset()); return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2b308630b48..9fd9143586e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -494,8 +494,9 @@ public: { String *tmp=args[0]->val_str(a); null_value=args[0]->null_value; + tmp->set_charset(my_charset_bin); return tmp; - } + } void fix_length_and_dec() { set_charset(my_charset_bin); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 07cdfde115b..f9b987324f0 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -513,6 +513,7 @@ public: bool get_date(TIME *res,bool fuzzy_date); }; + class Item_extract :public Item_int_func { const interval_type int_type; @@ -526,17 +527,40 @@ class Item_extract :public Item_int_func void fix_length_and_dec(); }; + class Item_typecast :public Item_str_func { public: Item_typecast(Item *a) :Item_str_func(a) {} + const char *func_name() const { return "char"; } String *val_str(String *a) - { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; } - void fix_length_and_dec() { max_length=args[0]->max_length; } + { + String *tmp=args[0]->val_str(a); + null_value=args[0]->null_value; + tmp->set_charset(charset()); + return tmp; + } + void fix_length_and_dec() + { + set_charset(thd_charset()); + max_length=args[0]->max_length; + } void print(String *str); }; +class Item_char_typecast :public Item_typecast +{ +public: + Item_char_typecast(Item *a) :Item_typecast(a) {} + void fix_length_and_dec() + { + set_charset(thd_charset()); + max_length=args[0]->max_length; + } +}; + + class Item_date_typecast :public Item_typecast { public: @@ -553,6 +577,7 @@ public: } }; + class Item_time_typecast :public Item_typecast { public: @@ -569,6 +594,7 @@ public: } }; + class Item_datetime_typecast :public Item_typecast { public: diff --git a/sql/lex.h b/sql/lex.h index 0d0d60fe204..1f83423a0ba 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -221,6 +221,8 @@ static SYMBOL symbols[] = { { "LIMIT", SYM(LIMIT),0,0}, { "LOAD", SYM(LOAD),0,0}, { "LOCAL", SYM(LOCAL_SYM),0,0}, + { "LOCALTIME", SYM(NOW_SYM),0,0}, + { "LOCALTIMESTAMP", SYM(NOW_SYM),0,0}, { "LOCK", SYM(LOCK_SYM),0,0}, { "LOCKS", SYM(LOCKS_SYM),0,0}, { "LOGS", SYM(LOGS_SYM),0,0}, @@ -417,7 +419,9 @@ static SYMBOL sql_functions[] = { { "BIT_OR", SYM(BIT_OR),0,0}, { "BIT_AND", SYM(BIT_AND),0,0}, { "CAST", SYM(CAST_SYM),0,0}, + { "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, { "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, + { "CURRENT_USER", SYM(USER),0,0}, { "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)}, { "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)}, { "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ebda24b404a..86da0e846a0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4498,7 +4498,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), else { struct hostent *ent; - if (!argument || !argument[0]) + if (argument || argument[0]) ent=gethostbyname(argument); else { @@ -4687,7 +4687,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } return 0; } - /* Initiates DEBUG - but no debugging here ! */ static void get_options(int argc,char **argv) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index cee5502fb32..0fad5769998 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -937,8 +937,11 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (!(res= value->val_str(&tmp))) DBUG_RETURN(&null_element); - // Check if this was a function. This should have be optimized away - // in the sql_select.cc + /* + TODO: + Check if this was a function. This should have be optimized away + in the sql_select.cc + */ if (res != &tmp) { tmp.copy(*res); // Get own copy @@ -1007,8 +1010,10 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, type != Item_func::EQUAL_FUNC) DBUG_RETURN(0); // Can't optimize this - /* We can't always use indexes when comparing a string index to a number */ - /* cmp_type() is checked to allow compare of dates to numbers */ + /* + We can't always use indexes when comparing a string index to a number + cmp_type() is checked to allow compare of dates to numbers + */ if (field->result_type() == STRING_RESULT && value->result_type() != STRING_RESULT && field->cmp_type() != value->result_type()) @@ -1016,6 +1021,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (value->save_in_field(field) > 0) { + /* This happens when we try to insert a NULL field in a not null column */ // TODO; Check if we can we remove the following block. if (type == Item_func::EQUAL_FUNC) { @@ -1027,7 +1033,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, *str = 1; DBUG_RETURN(new SEL_ARG(field,str,str)); } - DBUG_RETURN(&null_element); // NULL is never true + DBUG_RETURN(&null_element); // cmp with NULL is never true } // Get local copy of key char *str= (char*) alloc_root(param->mem_root, @@ -1035,7 +1041,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, if (!str) DBUG_RETURN(0); if (maybe_null) - *str=0; // Not NULL + *str= (char) field->is_real_null(); // Set to 1 if null field->get_key_image(str+maybe_null,key_part->part_length, key_part->image_type); if (!(tree=new SEL_ARG(field,str,str))) DBUG_RETURN(0); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index c9e10b5b0b5..16d6b6d4631 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -180,14 +180,12 @@ cleanup: if (ha_autocommit_or_rollback(thd,error >= 0)) error=1; } + /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if (deleted && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (deleted) { query_cache_invalidate3(thd, table_list, 1); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 6cb146afb33..c8a29dcd8da 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -319,13 +319,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List &fields, error=ha_autocommit_or_rollback(thd,error); /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if ((info.copied || info.deleted) && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (info.copied || info.deleted) { query_cache_invalidate3(thd, table_list, 1); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index e3ffe2a8120..e5860346863 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -76,7 +76,7 @@ inline int lex_casecmp(const char *s, const char *t, uint len) #include "lex_hash.h" -static uchar state_map[256]; +static uchar state_map[256], ident_map[256]; void lex_init(void) @@ -91,7 +91,7 @@ void lex_init(void) VOID(pthread_key_create(&THR_LEX,NULL)); /* Fill state_map with states to get a faster parser */ - for (i=0; i < 256 ; i++) + for (i=0; i < sizeof(state_map) ; i++) { if (my_isalpha(system_charset_info,i)) state_map[i]=(uchar) STATE_IDENT; @@ -126,6 +126,20 @@ void lex_init(void) { state_map[(uchar) '"'] = STATE_USER_VARIABLE_DELIMITER; } + + /* + Create a second map to make it faster to find identifiers + */ + for (i=0; i < sizeof(ident_map) ; i++) + { + ident_map[i]= (uchar) (state_map[i] == STATE_IDENT || + state_map[i] == STATE_NUMBER_IDENT); + } + + /* Special handling of hex and binary strings */ + state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) STATE_IDENT_OR_HEX; + state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) STATE_IDENT_OR_BIN; + DBUG_VOID_RETURN; } @@ -460,7 +474,7 @@ int yylex(void *arg) } case STATE_CHAR: // Unknown or single char token case STATE_SKIP: // This should not happen - yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first char + yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr yylval->lex_str.length=1; c=yyGet(); if (c != ')') @@ -469,12 +483,15 @@ int yylex(void *arg) lex->tok_start=lex->ptr; // Let tok_start point at next item return((int) c); - case STATE_IDENT: // Incomplete keyword or ident - if ((c == 'x' || c == 'X') && yyPeek() == '\'') + case STATE_IDENT_OR_HEX: + if (yyPeek() == '\'') { // Found x'hex-number' - state=STATE_HEX_NUMBER; + state= STATE_HEX_NUMBER; break; } + /* Fall through */ + case STATE_IDENT_OR_BIN: // TODO: Add binary string handling + case STATE_IDENT: #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(system_charset_info)) { @@ -489,8 +506,7 @@ int yylex(void *arg) } lex->ptr += l - 1; } - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) + while (ident_map[c=yyGet()]) { if (my_ismbhead(system_charset_info, c)) { @@ -505,15 +521,13 @@ int yylex(void *arg) } else #endif - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c=yyGet()]) ; length= (uint) (lex->ptr - lex->tok_start)-1; if (lex->ignore_space) { for (; state_map[c] == STATE_SKIP ; c= yyGet()); } - if (c == '.' && (state_map[yyPeek()] == STATE_IDENT || - state_map[yyPeek()] == STATE_NUMBER_IDENT)) + if (c == '.' && ident_map[yyPeek()]) lex->next_state=STATE_IDENT_SEP; else { // '(' must follow directly if function @@ -551,7 +565,7 @@ int yylex(void *arg) case STATE_NUMBER_IDENT: // number or ident which num-start while (my_isdigit(system_charset_info,(c = yyGet()))) ; - if (state_map[c] != STATE_IDENT) + if (!ident_map[c]) { // Can't be identifier state=STATE_INT_OR_REAL; break; @@ -576,7 +590,7 @@ int yylex(void *arg) lex->tok_start[0] == '0' ) { // Varbinary while (my_isxdigit(system_charset_info,(c = yyGet()))) ; - if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT) + if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c]) { yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str.str+=2; // Skip 0x @@ -603,8 +617,7 @@ int yylex(void *arg) } lex->ptr += l - 1; } - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) + while (ident_map[c=yyGet()]) { if (my_ismbhead(system_charset_info, c)) { @@ -619,11 +632,9 @@ int yylex(void *arg) } else #endif - while (state_map[c = yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c = yyGet()]) ; - if (c == '.' && (state_map[yyPeek()] == STATE_IDENT || - state_map[yyPeek()] == STATE_NUMBER_IDENT)) + if (c == '.' && ident_map[yyPeek()]) lex->next_state=STATE_IDENT_SEP;// Next is '.' // fall through @@ -901,8 +912,7 @@ int yylex(void *arg) [(global | local | session) .]variable_name */ - while (state_map[c=yyGet()] == STATE_IDENT || - state_map[c] == STATE_NUMBER_IDENT) ; + while (ident_map[c=yyGet()]) ; if (c == '.') lex->next_state=STATE_IDENT_SEP; length= (uint) (lex->ptr - lex->tok_start)-1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ce3acb4f450..93f01dd66dc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,7 @@ enum lex_states STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT, STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END, STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR, - STATE_IDENT_OR_KEYWORD + STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN }; diff --git a/sql/sql_string.h b/sql/sql_string.h index 42f9e446981..dde67b11d50 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -72,7 +72,7 @@ public: { sql_element_free(ptr_arg); } ~String() { free(); } - inline void set_charset(CHARSET_INFO *charset) { str_charset=charset; } + inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; } inline CHARSET_INFO *charset() const { return str_charset; } inline uint32 length() const { return str_length;} inline uint32 alloced_length() const { return Alloced_length;} @@ -177,7 +177,8 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string - bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); + bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, + CHARSET_INFO *csto); bool append(const String &s); bool append(const char *s,uint32 arg_length=0); bool append(IO_CACHE* file, uint32 arg_length); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index e3e0bca9856..f2a24eda530 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -319,14 +319,12 @@ int mysql_update(THD *thd, if (ha_autocommit_or_rollback(thd, error >= 0)) error=1; } + /* - Only invalidate the query cache if something changed or if we - didn't commit the transacion (query cache is automaticly - invalidated on commit) + Store table for future invalidation or invalidate it in + the query cache if something changed */ - if (updated && - (!transactional_table || - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (updated) { query_cache_invalidate3(thd, table_list, 1); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5dcb4f09951..fad0fb39020 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -991,7 +991,7 @@ field_list: field_list_item: - field_spec + field_spec check_constraint | field_spec references { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -1013,10 +1013,16 @@ field_list_item: lex->fk_match_option)); lex->col_list.empty(); /* Alloced by sql_alloc */ } - | opt_constraint CHECK_SYM '(' expr ')' + | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ - }; + } + ; + +check_constraint: + /* empty */ + | CHECK_SYM expr + ; opt_constraint: /* empty */ @@ -1110,6 +1116,12 @@ type: $$=FIELD_TYPE_SET; } | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } + | SERIAL_SYM + { + $$=FIELD_TYPE_LONGLONG; + Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG | + UNIQUE_FLAG); + } ; char: @@ -1184,12 +1196,13 @@ attribute: | DEFAULT literal { Lex->default_value=$2; } | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } | SERIAL_SYM DEFAULT VALUE_SYM - { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } - | PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } + { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; } + | opt_primary KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } | UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; } | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } | COMMENT_SYM text_literal { Lex->comment= $2; }; + charset_name: BINARY { @@ -1227,6 +1240,11 @@ opt_binary: | BINARY { Lex->charset=my_charset_bin; } | CHAR_SYM SET charset_name { Lex->charset=$3; } ; + +opt_primary: + /* empty */ + | PRIMARY_SYM + references: REFERENCES table_ident { @@ -2258,13 +2276,15 @@ in_sum_expr: cast_type: BINARY { $$=ITEM_CAST_BINARY; } + | CHAR_SYM { $$=ITEM_CAST_CHAR; } | SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; } | SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; } | UNSIGNED { $$=ITEM_CAST_UNSIGNED_INT; } | UNSIGNED INT_SYM { $$=ITEM_CAST_UNSIGNED_INT; } | DATE_SYM { $$=ITEM_CAST_DATE; } | TIME_SYM { $$=ITEM_CAST_TIME; } - | DATETIME { $$=ITEM_CAST_DATETIME; }; + | DATETIME { $$=ITEM_CAST_DATETIME; } + ; expr_list: { Select->expr_list.push_front(new List); } @@ -2801,7 +2821,7 @@ table_name: { if (!Select->add_table_to_list($1, NULL, 1)) YYABORT; }; if_exists: - /* empty */ { $$=0; } + /* empty */ { $$= 0; } | IF EXISTS { $$= 1; } ; @@ -2882,6 +2902,7 @@ fields: insert_values: VALUES values_list {} + | VALUE_SYM values_list {} | SELECT_SYM { LEX *lex=Lex; @@ -3574,7 +3595,6 @@ keyword: | CHANGED {} | CHARSET {} | CHECKSUM_SYM {} - | CHECK_SYM {} | CIPHER_SYM {} | CLIENT_SYM {} | CLOSE_SYM {}