diff options
author | unknown <gluh@gluh.mysql.r18.ru> | 2005-03-17 16:51:07 +0300 |
---|---|---|
committer | unknown <gluh@gluh.mysql.r18.ru> | 2005-03-17 16:51:07 +0300 |
commit | 17791f95002b2f9c8cb31eed64c36f019b2edda9 (patch) | |
tree | 7107fca24e8d8dd39be0300a9e1e64d7ad8921a2 | |
parent | 621abfacfe316df9ce06c9d046ec11f23e543ea7 (diff) | |
parent | 3e4ae65a144d8f7a63ee5f8c4d1ec65f94f35b58 (diff) | |
download | mariadb-git-17791f95002b2f9c8cb31eed64c36f019b2edda9.tar.gz |
Merge 4.1 -> 5.0
heap/hp_create.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/ctype_utf8.result:
Auto merged
mysql-test/r/olap.result:
Auto merged
mysql-test/t/func_str.test:
Auto merged
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_strfunc.cc:
Auto merged
sql/key.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sql_select.h:
Auto merged
sql/sql_string.h:
Auto merged
client/mysqldump.c:
Manual merge
mysql-test/r/func_gconcat.result:
Manual merge
mysql-test/r/func_str.result:
Manual merge
mysql-test/t/func_gconcat.test:
Manual merge
sql/ha_heap.cc:
Manual merge
sql/sql_select.cc:
Manual merge
-rw-r--r-- | client/mysqldump.c | 95 | ||||
-rw-r--r-- | heap/hp_create.c | 3 | ||||
-rw-r--r-- | include/heap.h | 2 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 6 | ||||
-rw-r--r-- | mysql-test/r/ctype_utf8.result | 7 | ||||
-rw-r--r-- | mysql-test/r/func_gconcat.result | 8 | ||||
-rw-r--r-- | mysql-test/r/func_str.result | 23 | ||||
-rw-r--r-- | mysql-test/r/olap.result | 72 | ||||
-rw-r--r-- | mysql-test/r/rpl000005.result | 3 | ||||
-rw-r--r-- | mysql-test/r/update.result | 7 | ||||
-rw-r--r-- | mysql-test/t/ctype_utf8.test | 9 | ||||
-rw-r--r-- | mysql-test/t/func_gconcat.test | 10 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 9 | ||||
-rw-r--r-- | mysql-test/t/olap.test | 30 | ||||
-rw-r--r-- | mysql-test/t/rpl000005.test | 5 | ||||
-rw-r--r-- | mysql-test/t/update.test | 10 | ||||
-rw-r--r-- | sql/ha_heap.cc | 14 | ||||
-rw-r--r-- | sql/item.cc | 12 | ||||
-rw-r--r-- | sql/item.h | 12 | ||||
-rw-r--r-- | sql/item_func.cc | 5 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 18 | ||||
-rw-r--r-- | sql/key.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 119 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_string.h | 4 |
26 files changed, 394 insertions, 95 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index 7d357b25541..46337c99732 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -875,8 +875,8 @@ static int dbConnect(char *host, char *user,char *passwd) cannot reconnect. */ sock->reconnect= 0; - sprintf(buff, "/*!40100 SET @@SQL_MODE='%s' */", - compatible_mode_normal_str); + my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */", + compatible_mode_normal_str); if (mysql_query_with_error_report(sock, 0, buff)) { mysql_close(sock); @@ -1111,8 +1111,9 @@ static uint getTableStructure(char *table, char* db) if (verbose) fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); - sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", - (opt_quoted || opt_keywords)); + my_snprintf(insert_pat, sizeof(insert_pat), + "SET OPTION SQL_QUOTE_SHOW_CREATE=%d", + (opt_quoted || opt_keywords)); if (!create_options) strmov(strend(insert_pat), "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */"); @@ -1131,7 +1132,7 @@ static uint getTableStructure(char *table, char* db) char buff[20+FN_REFLEN]; MYSQL_FIELD *field; - sprintf(buff,"show create table %s", result_table); + my_snprintf(buff, sizeof(buff), "show create table %s", result_table); if (mysql_query_with_error_report(sock, 0, buff)) { safe_exit(EX_MYSQLERR); @@ -1177,7 +1178,8 @@ static uint getTableStructure(char *table, char* db) check_io(sql_file); mysql_free_result(tableRes); } - sprintf(insert_pat,"show fields from %s", result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "show fields from %s", + result_table); if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { if (path) @@ -1187,11 +1189,12 @@ static uint getTableStructure(char *table, char* db) } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, opt_quoted_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (", + delayed, opt_quoted_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, - opt_quoted_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ", + delayed, opt_quoted_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -1218,7 +1221,8 @@ static uint getTableStructure(char *table, char* db) "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", my_progname, mysql_error(sock)); - sprintf(insert_pat,"show fields from %s", result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "show fields from %s", + result_table); if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { safe_exit(EX_MYSQLERR); @@ -1253,10 +1257,12 @@ static uint getTableStructure(char *table, char* db) check_io(sql_file); } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s (", + delayed, result_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, result_table); + my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ", + delayed, result_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -1313,7 +1319,7 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; uint keynr,primary_key; - sprintf(buff,"show keys from %s", result_table); + my_snprintf(buff, sizeof(buff), "show keys from %s", result_table); if (mysql_query_with_error_report(sock, &tableRes, buff)) { if (mysql_errno(sock) == ER_WRONG_OBJECT) @@ -1391,8 +1397,12 @@ static uint getTableStructure(char *table, char* db) if (create_options) { char show_name_buff[FN_REFLEN]; - sprintf(buff,"show table status like %s", - quote_for_like(table, show_name_buff)); + + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(table) < sizeof(show_name_buff)); + my_snprintf(buff, sizeof(buff), "show table status like %s", + quote_for_like(table, show_name_buff)); + if (mysql_query_with_error_report(sock, &tableRes, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -1553,8 +1563,9 @@ static void dumpTable(uint numFields, char *table) my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if filename wasn't deleted */ to_unix_path(filename); - sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", - filename); + my_snprintf(query, QUERY_LENGTH, + "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", + filename); end= strend(query); if (fields_terminated || enclosed || opt_enclosed || escaped) @@ -1566,7 +1577,7 @@ static void dumpTable(uint numFields, char *table) end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); *end= '\0'; - sprintf(buff," FROM %s", result_table); + my_snprintf(buff, sizeof(buff), " FROM %s", result_table); end= strmov(end,buff); if (where || order_by) { @@ -1594,8 +1605,9 @@ static void dumpTable(uint numFields, char *table) result_table); check_io(md_result_file); } - sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", - result_table); + my_snprintf(query, QUERY_LENGTH, + "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", + result_table); if (where || order_by) { query = alloc_query_str((ulong) (strlen(query) + 1 + @@ -1693,8 +1705,9 @@ static void dumpTable(uint numFields, char *table) int is_blob; if (!(field = mysql_fetch_field(res))) { - sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", - my_progname, result_table); + my_snprintf(query, QUERY_LENGTH, + "%s: Not enough fields from table %s! Aborting.\n", + my_progname, result_table); fputs(query,stderr); error= EX_CONSCHECK; goto err; @@ -1896,12 +1909,13 @@ static void dumpTable(uint numFields, char *table) check_io(md_result_file); if (mysql_errno(sock)) { - sprintf(query,"%s: Error %d: %s when dumping table %s at row: %ld\n", - my_progname, - mysql_errno(sock), - mysql_error(sock), - result_table, - rownr); + my_snprintf(query, QUERY_LENGTH, + "%s: Error %d: %s when dumping table %s at row: %ld\n", + my_progname, + mysql_errno(sock), + mysql_error(sock), + result_table, + rownr); fputs(query,stderr); error= EX_CONSCHECK; goto err; @@ -2045,8 +2059,9 @@ static int init_dumping(char *database) MYSQL_ROW row; MYSQL_RES *dbinfo; - sprintf(qbuf,"SHOW CREATE DATABASE IF NOT EXISTS %s", - qdatabase); + my_snprintf(qbuf, sizeof(qbuf), + "SHOW CREATE DATABASE IF NOT EXISTS %s", + qdatabase); if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) { @@ -2141,6 +2156,7 @@ static int dump_all_tables_in_db(char *database) return 0; } /* dump_all_tables_in_db */ + /* dump structure of views of database @@ -2195,6 +2211,7 @@ static my_bool dump_all_views_in_db(char *database) return 0; } /* dump_all_tables_in_db */ + /* get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual table name from the server for the table name given on the command line. @@ -2211,10 +2228,15 @@ static void get_actual_table_name(const char *old_table_name, { MYSQL_RES *tableRes; MYSQL_ROW row; - char query[ NAME_LEN + 50 ]; + char query[50 + 2*NAME_LEN]; + char show_name_buff[FN_REFLEN]; DBUG_ENTER("get_actual_table_name"); - sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name); + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); + my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", + quote_for_like(old_table_name, show_name_buff)); + if (mysql_query_with_error_report(sock, 0, query)) { safe_exit(EX_MYSQLERR); @@ -2464,8 +2486,10 @@ static const char *check_if_ignore_table(const char *table_name) MYSQL_ROW row; const char *result= 0; - sprintf(buff,"show table status like %s", - quote_for_like(table_name, show_name_buff)); + /* Check memory for quote_for_like() */ + DBUG_ASSERT(2*sizeof(table_name) < sizeof(show_name_buff)); + my_snprintf(buff, sizeof(buff), "show table status like %s", + quote_for_like(table_name, show_name_buff)); if (mysql_query_with_error_report(sock, &res, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -2523,7 +2547,8 @@ static char *primary_key_fields(const char *table_name) uint result_length = 0; char *result = 0; - sprintf(show_keys_buff, "SHOW KEYS FROM %s", table_name); + my_snprintf(show_keys_buff, sizeof(show_keys_buff), + "SHOW KEYS FROM %s", table_name); if (mysql_query(sock, show_keys_buff) || !(res = mysql_store_result(sock))) { diff --git a/heap/hp_create.c b/heap/hp_create.c index 55b8e1e2a33..17aa92c9201 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -168,8 +168,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, keyinfo->write_key= hp_write_key; keyinfo->hash_buckets= 0; } - if ((keyinfo->flag & HA_AUTO_KEY) && create_info->with_auto_increment) - share->auto_key= i + 1; } share->min_records= min_records; share->max_records= max_records; @@ -180,6 +178,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, share->keys= keys; share->max_key_length= max_length; share->changed= 0; + share->auto_key= create_info->auto_key; share->auto_key_type= create_info->auto_key_type; share->auto_increment= create_info->auto_increment; /* Must be allocated separately for rename to work */ diff --git a/include/heap.h b/include/heap.h index 51f7b0cfa6a..badec9ce2ef 100644 --- a/include/heap.h +++ b/include/heap.h @@ -181,8 +181,10 @@ typedef struct st_heap_info LIST open_list; } HP_INFO; + typedef struct st_heap_create_info { + uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; ulong max_table_size; ulonglong auto_increment; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 4e970ca034d..92561496544 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -432,10 +432,10 @@ while test $# -gt 0; do TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` VALGRIND="$VALGRIND $TMP" ;; - --skip-ndbcluster) + --skip-ndbcluster | --skip-ndb) USE_NDBCLUSTER="" - EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" - EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1" + EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-ndbcluster" + EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-ndbcluster" ;; --skip-*) EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 893c7cc7039..7fe8e76cb5b 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -861,6 +861,13 @@ user c one <one> two <two> DROP TABLE t1; +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +concat(concat(_latin1'->',f1),_latin1'<-') +-><- +-><- +drop table t1; select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8) 1 diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 06c1759bf1d..d56a5050ced 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -469,3 +469,11 @@ group_concat(a) ABW ABW drop table t1; +create table r2 (a int, b int); +insert into r2 values (1,1), (2,2); +select b x, (select group_concat(x) from r2) from r2; +x (select group_concat(x) from r2) +1 1,1 +2 2,2 +drop table r2; + diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 92c7d46550f..ba4de675157 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -515,7 +515,7 @@ collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set( latin2_general_ci 4 select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')); collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')) coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')) -binary 4 +latin2_general_ci 4 select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a ')); collation(trim(_latin2' a ')) coercibility(trim(_latin2' a ')) latin2_general_ci 4 @@ -630,6 +630,15 @@ t1 CREATE TABLE `t1` ( `encode('abcd','ab')` varbinary(4) NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 (a char character set latin2); +insert into t1 values (null); +select charset(a), collation(a), coercibility(a) from t1; +charset(a) collation(a) coercibility(a) +latin2 latin2_general_ci 2 +drop table t1; +select charset(null), collation(null), coercibility(null); +charset(null) collation(null) coercibility(null) +binary binary 5 select SUBSTR('abcdefg',3,2); SUBSTR('abcdefg',3,2) cd @@ -683,16 +692,16 @@ drop table t1, t2; create table t1 (c1 INT, c2 INT UNSIGNED); insert into t1 values ('21474836461','21474836461'); Warnings: -Warning 1264 Out of range value adjusted for column 'c1' at row 1 -Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1265 Data truncated for column 'c1' at row 1 +Warning 1265 Data truncated for column 'c2' at row 1 insert into t1 values ('-21474836461','-21474836461'); Warnings: -Warning 1264 Out of range value adjusted for column 'c1' at row 1 -Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1265 Data truncated for column 'c1' at row 1 +Warning 1265 Data truncated for column 'c2' at row 1 show warnings; Level Code Message -Warning 1264 Out of range value adjusted for column 'c1' at row 1 -Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1265 Data truncated for column 'c1' at row 1 +Warning 1265 Data truncated for column 'c2' at row 1 select * from t1; c1 c2 2147483647 4294967295 diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index a04fa75082f..b04cd6fd068 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -307,3 +307,75 @@ day sample not_cancelled 2004-06-07 1 0 NULL 3 1 DROP TABLE user_day; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES +(1,4), +(2,2), (2,2), +(4,1), (4,1), (4,1), (4,1), +(2,1), (2,1); +SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) +4 +6 +4 +14 +SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) +4 +6 +14 +SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) +4 1 +6 2 +4 1 +14 3 +SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) +4 1 +6 2 +14 3 +SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(*) +4 1 +6 4 +4 4 +14 9 +SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(*) +4 1 +6 4 +4 4 +14 9 +SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) COUNT(*) +4 1 1 +6 2 4 +4 1 4 +14 3 9 +SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 +GROUP BY a WITH ROLLUP; +SUM(b) COUNT(DISTINCT b) COUNT(*) +4 1 1 +6 2 4 +4 1 4 +14 3 9 +SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +a sum(b) +1 4 +1 4 +2 2 +2 4 +2 6 +4 4 +4 4 +NULL 14 +SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +a sum(b) +1 4 +2 2 +2 4 +2 6 +4 4 +NULL 14 +DROP TABLE t1; diff --git a/mysql-test/r/rpl000005.result b/mysql-test/r/rpl000005.result index 0202e43dcb2..8acfa2cbfac 100644 --- a/mysql-test/r/rpl000005.result +++ b/mysql-test/r/rpl000005.result @@ -4,6 +4,9 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +SHOW VARIABLES LIKE 'relay_log_space_limit'; +Variable_name Value +relay_log_space_limit 0 CREATE TABLE t1 (name varchar(64), age smallint(3)); INSERT INTO t1 SET name='Andy', age=31; INSERT t1 SET name='Jacob', age=2; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index ac370db9ecc..4a9e95fb89e 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -219,3 +219,10 @@ select * from t1; id id_str 1 test1 drop table t1; +create table t1 (a int, b char(255), key(a, b(20))); +insert into t1 values (0, '1'); +update t1 set b = b + 1 where a = 0; +select * from t1; +a b +0 2 +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 35f2b2642be..2c498cd1922 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -695,6 +695,15 @@ SELECT user, CONCAT('<', user, '>') AS c FROM t1; DROP TABLE t1; # +# Bug#8785 +# the same problem with the above, but with nested CONCATs +# +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +drop table t1; + +# # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same # select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index a1fac51371c..694e0223753 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -288,8 +288,16 @@ DROP TABLE t1; # # Bug #6475 # - create table t1 (a char(3), b char(20), primary key (a, b)); insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English'); select group_concat(a) from t1 group by b; drop table t1; + +# +# Bug #8656: Crash with group_concat on alias in outer table +# +create table r2 (a int, b int); +insert into r2 values (1,1), (2,2); +select b x, (select group_concat(x) from r2) from r2; +drop table r2; + diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 2fa6b603155..2041c776423 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -370,6 +370,15 @@ show create table t1; drop table t1; # +# Bug#9129 +# +create table t1 (a char character set latin2); +insert into t1 values (null); +select charset(a), collation(a), coercibility(a) from t1; +drop table t1; +select charset(null), collation(null), coercibility(null); + +# # test for SUBSTR # select SUBSTR('abcdefg',3,2); diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index 674b4ade097..6778af3d533 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -125,3 +125,33 @@ SELECT DROP TABLE user_day; +# +# Tests for bugs #8616, #8615: distinct sum with rollup +# + +CREATE TABLE t1 (a int, b int); + +INSERT INTO t1 VALUES + (1,4), + (2,2), (2,2), + (4,1), (4,1), (4,1), (4,1), + (2,1), (2,1); + +SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; +SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 + GROUP BY a WITH ROLLUP; + +SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; +SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP; + +DROP TABLE t1; + diff --git a/mysql-test/t/rpl000005.test b/mysql-test/t/rpl000005.test index ae713633df3..b94695c72e1 100644 --- a/mysql-test/t/rpl000005.test +++ b/mysql-test/t/rpl000005.test @@ -1,5 +1,10 @@ source include/master-slave.inc; +# +# Bug#7100 relay_log_space_max missing from SHOW VARIABLES +# +SHOW VARIABLES LIKE 'relay_log_space_limit'; + CREATE TABLE t1 (name varchar(64), age smallint(3)); INSERT INTO t1 SET name='Andy', age=31; INSERT t1 SET name='Jacob', age=2; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 04192f25ac8..8eb3a924ee3 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -179,3 +179,13 @@ insert into t1 (id_str) values ("test"); update t1 set id_str = concat(id_str, id) where id = last_insert_id(); select * from t1; drop table t1; + +# +# Bug #8942: a problem with update and partial key part +# + +create table t1 (a int, b char(255), key(a, b(20))); +insert into t1 values (0, '1'); +update t1 set b = b + 1 where a = 0; +select * from t1; +drop table t1; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index c8d0e5c1c18..24f21718b8c 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -521,9 +521,17 @@ int ha_heap::create(const char *name, TABLE *table_arg, seg->null_bit= 0; seg->null_pos= 0; } - // We have to store field->key_type() as seg->type can differ from it - if (field->flags & AUTO_INCREMENT_FLAG) + if (field->flags & AUTO_INCREMENT_FLAG && + table_arg->found_next_number_field && + key == table_arg->next_number_index) + { + /* + Store key number and type for found auto_increment key + We have to store type as seg->type can differ from it + */ + auto_key= key+ 1; auto_key_type= field->key_type(); + } } } mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); @@ -535,8 +543,8 @@ int ha_heap::create(const char *name, TABLE *table_arg, found_real_auto_increment= share->next_number_key_offset == 0; } HP_CREATE_INFO hp_create_info; + hp_create_info.auto_key= auto_key; hp_create_info.auto_key_type= auto_key_type; - hp_create_info.with_auto_increment= found_real_auto_increment; hp_create_info.auto_increment= (create_info->auto_increment_value ? create_info->auto_increment_value - 1 : 0); hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; diff --git a/sql/item.cc b/sql/item.cc index e6be934e334..64fc2696f1f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -586,6 +586,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) return NULL; } conv->str_value.copy(); + /* + The above line executes str_value.realloc() internally, + which alligns Alloced_length using ALLIGN_SIZE. + In the case of Item_string::str_value we don't want + Alloced_length to be longer than str_length. + Otherwise, some functions like Item_func_concat::val_str() + try to reuse str_value as a buffer for concatenation result + for optimization purposes, so our string constant become + corrupted. See bug#8785 for more details. + Let's shrink Alloced_length to str_length to avoid this problem. + */ + conv->str_value.shrink_to_length(); return conv; } diff --git a/sql/item.h b/sql/item.h index a2bf33398cc..31b490d6ed8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -790,6 +790,17 @@ public: Item *safe_charset_converter(CHARSET_INFO *tocs); }; +class Item_null_result :public Item_null +{ +public: + Field *result_field; + Item_null_result() : Item_null(), result_field(0) {} + bool is_result_field() { return result_field != 0; } + void save_in_result_field(bool no_conversions) + { + save_in_field(result_field, no_conversions); + } +}; /* Item represents one placeholder ('?') of prepared statement */ @@ -1274,6 +1285,7 @@ public: void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } enum_field_types field_type() const { return (*ref)->field_type(); } + Field *get_tmp_table_field() { return result_field; } table_map used_tables() const { return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); diff --git a/sql/item_func.cc b/sql/item_func.cc index 684ba814cd4..5eb87c2e92b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2096,11 +2096,6 @@ longlong Item_func_char_length::val_int() longlong Item_func_coercibility::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->null_value) - { - null_value= 1; - return 0; - } null_value= 0; return (longlong) args[0]->collation.derivation; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a9ec7139ea7..81120bbe3f7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -267,8 +267,7 @@ String *Item_func_concat::val_str(String *str) current_thd->variables.max_allowed_packet); goto null; } - if (!args[0]->const_item() && - res->alloced_length() >= res->length()+res2->length()) + if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } @@ -2308,12 +2307,11 @@ void Item_func_set_collation::print(String *str) String *Item_func_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->csname,strlen(res->charset()->csname), + CHARSET_INFO *cs= args[0]->collation.collation; + null_value= 0; + str->copy(cs->csname, strlen(cs->csname), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2321,12 +2319,11 @@ String *Item_func_charset::val_str(String *str) String *Item_func_collation::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); uint dummy_errors; + CHARSET_INFO *cs= args[0]->collation.collation; - if ((null_value=(args[0]->null_value || !res->charset()))) - return 0; - str->copy(res->charset()->name,strlen(res->charset()->name), + null_value= 0; + str->copy(cs->name, strlen(cs->name), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2490,6 +2487,7 @@ String* Item_func_export_set::val_str(String* str) uint num_set_values = 64; ulonglong mask = 0x1; str->length(0); + str->set_charset(collation.collation); /* Check if some argument is a NULL value */ if (args[0]->null_value || args[1]->null_value || args[2]->null_value) diff --git a/sql/key.cc b/sql/key.cc index c5ed60b129c..3299c3db8f8 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -368,7 +368,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields) f.rewind(); while ((field=(Item_field*) f++)) { - if (key_part->field == field->field) + if (key_part->field->eq(field->field)) return 1; } } diff --git a/sql/set_var.cc b/sql/set_var.cc index 1f4713471ba..23dbb22399b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -926,6 +926,7 @@ struct show_var_st init_vars[]= { {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, #ifdef HAVE_REPLICATION {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, + {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, #endif {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b970c184489..1ada220b446 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -191,7 +191,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, uint elements, List<Item> &items); static void init_tmptable_sum_functions(Item_sum **func); static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); -static void copy_sum_funcs(Item_sum **func_ptr); +static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr); static bool init_sum_functions(Item_sum **func, Item_sum **end); @@ -1386,7 +1386,6 @@ JOIN::exec() { DBUG_VOID_RETURN; } - curr_join->group_list= 0; } thd->proc_info="Copying to group table"; @@ -1447,7 +1446,7 @@ JOIN::exec() if (curr_join->tmp_having) curr_join->tmp_having->update_used_tables(); if (remove_duplicates(curr_join, curr_tmp_table, - curr_join->fields_list, curr_join->tmp_having)) + *curr_fields_list, curr_join->tmp_having)) DBUG_VOID_RETURN; curr_join->tmp_having=0; curr_join->select_distinct=0; @@ -10132,26 +10131,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (join->procedure) join->procedure->end_group(); - if (idx < (int) join->send_group_parts) + int send_group_parts= join->send_group_parts; + if (idx < send_group_parts) { if (!join->first_record) { /* No matching rows for group function */ join->clear(); } - copy_sum_funcs(join->sum_funcs); - if (!join->having || join->having->val_int()) + copy_sum_funcs(join->sum_funcs, + join->sum_funcs_end[send_group_parts]); + if (join->having && join->having->val_int() == 0) + error= -1; + else if ((error=table->file->write_row(table->record[0]))) { - if ((error=table->file->write_row(table->record[0]))) - { - if (create_myisam_from_heap(join->thd, table, - &join->tmp_table_param, - error, 0)) - DBUG_RETURN(-1); // Not a table_is_full error - } - else - join->send_records++; + if (create_myisam_from_heap(join->thd, table, + &join->tmp_table_param, + error, 0)) + DBUG_RETURN(-1); + } + if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0) + { + if (join->rollup_write_data((uint) (idx+1), table)) + error= 1; } + if (error > 0) + DBUG_RETURN(-1); if (end_of_records) DBUG_RETURN(0); } @@ -12413,11 +12418,10 @@ update_tmptable_sum_func(Item_sum **func_ptr, /* Copy result of sum functions to record in tmp_table */ static void -copy_sum_funcs(Item_sum **func_ptr) +copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr) { - Item_sum *func; - for (; (func = *func_ptr) ; func_ptr++) - (void) func->save_in_result_field(1); + for (; func_ptr != end_ptr ; func_ptr++) + (void) (*func_ptr)->save_in_result_field(1); return; } @@ -12539,14 +12543,16 @@ bool JOIN::rollup_init() */ tmp_table_param.group_parts= send_group_parts; - if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) + - sizeof(List<Item>) + - ref_pointer_array_size) - * send_group_parts))) + if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) + + sizeof(Item**) + + sizeof(List<Item>) + + ref_pointer_array_size) + * send_group_parts ))) return 1; + + rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); - rollup.item_null= new (thd->mem_root) Item_null(); /* Prepare space for field list for the different levels @@ -12554,12 +12560,16 @@ bool JOIN::rollup_init() */ for (i= 0 ; i < send_group_parts ; i++) { + rollup.null_items[i]= new (thd->mem_root) Item_null_result(); List<Item> *rollup_fields= &rollup.fields[i]; rollup_fields->empty(); rollup.ref_pointer_arrays[i]= ref_array; ref_array+= all_fields.elements; + } + for (i= 0 ; i < send_group_parts; i++) + { for (j=0 ; j < fields_list.elements ; j++) - rollup_fields->push_back(rollup.item_null); + rollup.fields[i].push_back(rollup.null_items[i]); } return 0; } @@ -12663,7 +12673,8 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, { /* Check if this is something that is part of this group by */ ORDER *group_tmp; - for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next) + for (group_tmp= start_group, i-- ; + group_tmp ; group_tmp= group_tmp->next, i++) { if (*group_tmp->item == item) { @@ -12672,7 +12683,9 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, set to NULL in this level */ item->maybe_null= 1; // Value will be null sometimes - item= rollup.item_null; + Item_null_result *null_item= rollup.null_items[i]; + null_item->result_field= ((Item_field *) item)->result_field; + item= null_item; break; } } @@ -12733,6 +12746,58 @@ int JOIN::rollup_send_data(uint idx) } /* + Write all rollup levels higher than the current one to a temp table + + SYNOPSIS: + rollup_write_data() + idx Level we are on: + 0 = Total sum level + 1 = First group changed (a) + 2 = Second group changed (a,b) + table reference to temp table + + SAMPLE + SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP + + RETURN + 0 ok + 1 if write_data_failed() +*/ + +int JOIN::rollup_write_data(uint idx, TABLE *table) +{ + uint i; + for (i= send_group_parts ; i-- > idx ; ) + { + /* Get reference pointers to sum functions in place */ + memcpy((char*) ref_pointer_array, + (char*) rollup.ref_pointer_arrays[i], + ref_pointer_array_size); + if ((!having || having->val_int())) + { + int error; + Item *item; + List_iterator_fast<Item> it(rollup.fields[i]); + while ((item= it++)) + { + if (item->type() == Item::NULL_ITEM && item->is_result_field()) + item->save_in_result_field(1); + } + copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]); + if ((error= table->file->write_row(table->record[0]))) + { + if (create_myisam_from_heap(thd, table, &tmp_table_param, + error, 0)) + return 1; + } + } + } + /* Restore ref_pointer_array */ + set_items_ref_array(current_ref_pointer_array); + return 0; +} + +/* clear results if there are not rows found for group (end_send_group/end_write_group) diff --git a/sql/sql_select.h b/sql/sql_select.h index f00fd476edd..02e1dde8a7f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -135,7 +135,7 @@ typedef struct st_rollup { enum State { STATE_NONE, STATE_INITED, STATE_READY }; State state; - Item *item_null; + Item_null_result **null_items; Item ***ref_pointer_arrays; List<Item> *fields; } ROLLUP; @@ -323,6 +323,7 @@ class JOIN :public Sql_alloc bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, Item_sum ***func); int rollup_send_data(uint idx); + int rollup_write_data(uint idx, TABLE *table); bool test_in_subselect(Item **where); void join_free(bool full); void clear(); diff --git a/sql/sql_string.h b/sql/sql_string.h index 2debeb61787..fc1e9f171b6 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -205,6 +205,10 @@ public: } } } + inline void shrink_to_length() + { + Alloced_length= str_length; + } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { |