Commit 17791f95 authored by unknown's avatar unknown

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
parents 621abfac 3e4ae65a
...@@ -875,8 +875,8 @@ static int dbConnect(char *host, char *user,char *passwd) ...@@ -875,8 +875,8 @@ static int dbConnect(char *host, char *user,char *passwd)
cannot reconnect. cannot reconnect.
*/ */
sock->reconnect= 0; sock->reconnect= 0;
sprintf(buff, "/*!40100 SET @@SQL_MODE='%s' */", my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
compatible_mode_normal_str); compatible_mode_normal_str);
if (mysql_query_with_error_report(sock, 0, buff)) if (mysql_query_with_error_report(sock, 0, buff))
{ {
mysql_close(sock); mysql_close(sock);
...@@ -1111,8 +1111,9 @@ static uint getTableStructure(char *table, char* db) ...@@ -1111,8 +1111,9 @@ static uint getTableStructure(char *table, char* db)
if (verbose) if (verbose)
fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); fprintf(stderr, "-- Retrieving table structure for table %s...\n", table);
sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", my_snprintf(insert_pat, sizeof(insert_pat),
(opt_quoted || opt_keywords)); "SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
(opt_quoted || opt_keywords));
if (!create_options) if (!create_options)
strmov(strend(insert_pat), "/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_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) ...@@ -1131,7 +1132,7 @@ static uint getTableStructure(char *table, char* db)
char buff[20+FN_REFLEN]; char buff[20+FN_REFLEN];
MYSQL_FIELD *field; 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)) if (mysql_query_with_error_report(sock, 0, buff))
{ {
safe_exit(EX_MYSQLERR); safe_exit(EX_MYSQLERR);
...@@ -1177,7 +1178,8 @@ static uint getTableStructure(char *table, char* db) ...@@ -1177,7 +1178,8 @@ static uint getTableStructure(char *table, char* db)
check_io(sql_file); check_io(sql_file);
mysql_free_result(tableRes); 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 (mysql_query_with_error_report(sock, &tableRes, insert_pat))
{ {
if (path) if (path)
...@@ -1187,11 +1189,12 @@ static uint getTableStructure(char *table, char* db) ...@@ -1187,11 +1189,12 @@ static uint getTableStructure(char *table, char* db)
} }
if (cFlag) 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 else
{ {
sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, my_snprintf(insert_pat, sizeof(insert_pat), "INSERT %sINTO %s VALUES ",
opt_quoted_table); delayed, opt_quoted_table);
if (!extended_insert) if (!extended_insert)
strcat(insert_pat,"("); strcat(insert_pat,"(");
} }
...@@ -1218,7 +1221,8 @@ static uint getTableStructure(char *table, char* db) ...@@ -1218,7 +1221,8 @@ static uint getTableStructure(char *table, char* db)
"%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", "%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
my_progname, mysql_error(sock)); 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)) if (mysql_query_with_error_report(sock, &tableRes, insert_pat))
{ {
safe_exit(EX_MYSQLERR); safe_exit(EX_MYSQLERR);
...@@ -1253,10 +1257,12 @@ static uint getTableStructure(char *table, char* db) ...@@ -1253,10 +1257,12 @@ static uint getTableStructure(char *table, char* db)
check_io(sql_file); check_io(sql_file);
} }
if (cFlag) 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 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) if (!extended_insert)
strcat(insert_pat,"("); strcat(insert_pat,"(");
} }
...@@ -1313,7 +1319,7 @@ static uint getTableStructure(char *table, char* db) ...@@ -1313,7 +1319,7 @@ static uint getTableStructure(char *table, char* db)
/* Make an sql-file, if path was given iow. option -T was given */ /* Make an sql-file, if path was given iow. option -T was given */
char buff[20+FN_REFLEN]; char buff[20+FN_REFLEN];
uint keynr,primary_key; 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_query_with_error_report(sock, &tableRes, buff))
{ {
if (mysql_errno(sock) == ER_WRONG_OBJECT) if (mysql_errno(sock) == ER_WRONG_OBJECT)
...@@ -1391,8 +1397,12 @@ static uint getTableStructure(char *table, char* db) ...@@ -1391,8 +1397,12 @@ static uint getTableStructure(char *table, char* db)
if (create_options) if (create_options)
{ {
char show_name_buff[FN_REFLEN]; 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_query_with_error_report(sock, &tableRes, buff))
{ {
if (mysql_errno(sock) != ER_PARSE_ERROR) if (mysql_errno(sock) != ER_PARSE_ERROR)
...@@ -1553,8 +1563,9 @@ static void dumpTable(uint numFields, char *table) ...@@ -1553,8 +1563,9 @@ static void dumpTable(uint numFields, char *table)
my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
filename wasn't deleted */ filename wasn't deleted */
to_unix_path(filename); to_unix_path(filename);
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'", my_snprintf(query, QUERY_LENGTH,
filename); "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
filename);
end= strend(query); end= strend(query);
if (fields_terminated || enclosed || opt_enclosed || escaped) if (fields_terminated || enclosed || opt_enclosed || escaped)
...@@ -1566,7 +1577,7 @@ static void dumpTable(uint numFields, char *table) ...@@ -1566,7 +1577,7 @@ static void dumpTable(uint numFields, char *table)
end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
*end= '\0'; *end= '\0';
sprintf(buff," FROM %s", result_table); my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
end= strmov(end,buff); end= strmov(end,buff);
if (where || order_by) if (where || order_by)
{ {
...@@ -1594,8 +1605,9 @@ static void dumpTable(uint numFields, char *table) ...@@ -1594,8 +1605,9 @@ static void dumpTable(uint numFields, char *table)
result_table); result_table);
check_io(md_result_file); check_io(md_result_file);
} }
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", my_snprintf(query, QUERY_LENGTH,
result_table); "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
result_table);
if (where || order_by) if (where || order_by)
{ {
query = alloc_query_str((ulong) (strlen(query) + 1 + query = alloc_query_str((ulong) (strlen(query) + 1 +
...@@ -1693,8 +1705,9 @@ static void dumpTable(uint numFields, char *table) ...@@ -1693,8 +1705,9 @@ static void dumpTable(uint numFields, char *table)
int is_blob; int is_blob;
if (!(field = mysql_fetch_field(res))) if (!(field = mysql_fetch_field(res)))
{ {
sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", my_snprintf(query, QUERY_LENGTH,
my_progname, result_table); "%s: Not enough fields from table %s! Aborting.\n",
my_progname, result_table);
fputs(query,stderr); fputs(query,stderr);
error= EX_CONSCHECK; error= EX_CONSCHECK;
goto err; goto err;
...@@ -1896,12 +1909,13 @@ static void dumpTable(uint numFields, char *table) ...@@ -1896,12 +1909,13 @@ static void dumpTable(uint numFields, char *table)
check_io(md_result_file); check_io(md_result_file);
if (mysql_errno(sock)) if (mysql_errno(sock))
{ {
sprintf(query,"%s: Error %d: %s when dumping table %s at row: %ld\n", my_snprintf(query, QUERY_LENGTH,
my_progname, "%s: Error %d: %s when dumping table %s at row: %ld\n",
mysql_errno(sock), my_progname,
mysql_error(sock), mysql_errno(sock),
result_table, mysql_error(sock),
rownr); result_table,
rownr);
fputs(query,stderr); fputs(query,stderr);
error= EX_CONSCHECK; error= EX_CONSCHECK;
goto err; goto err;
...@@ -2045,8 +2059,9 @@ static int init_dumping(char *database) ...@@ -2045,8 +2059,9 @@ static int init_dumping(char *database)
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *dbinfo; MYSQL_RES *dbinfo;
sprintf(qbuf,"SHOW CREATE DATABASE IF NOT EXISTS %s", my_snprintf(qbuf, sizeof(qbuf),
qdatabase); "SHOW CREATE DATABASE IF NOT EXISTS %s",
qdatabase);
if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
{ {
...@@ -2141,6 +2156,7 @@ static int dump_all_tables_in_db(char *database) ...@@ -2141,6 +2156,7 @@ static int dump_all_tables_in_db(char *database)
return 0; return 0;
} /* dump_all_tables_in_db */ } /* dump_all_tables_in_db */
/* /*
dump structure of views of database dump structure of views of database
...@@ -2195,6 +2211,7 @@ static my_bool dump_all_views_in_db(char *database) ...@@ -2195,6 +2211,7 @@ static my_bool dump_all_views_in_db(char *database)
return 0; return 0;
} /* dump_all_tables_in_db */ } /* dump_all_tables_in_db */
/* /*
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual 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. 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, ...@@ -2211,10 +2228,15 @@ static void get_actual_table_name(const char *old_table_name,
{ {
MYSQL_RES *tableRes; MYSQL_RES *tableRes;
MYSQL_ROW row; 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"); 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)) if (mysql_query_with_error_report(sock, 0, query))
{ {
safe_exit(EX_MYSQLERR); safe_exit(EX_MYSQLERR);
...@@ -2464,8 +2486,10 @@ static const char *check_if_ignore_table(const char *table_name) ...@@ -2464,8 +2486,10 @@ static const char *check_if_ignore_table(const char *table_name)
MYSQL_ROW row; MYSQL_ROW row;
const char *result= 0; const char *result= 0;
sprintf(buff,"show table status like %s", /* Check memory for quote_for_like() */
quote_for_like(table_name, show_name_buff)); 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_query_with_error_report(sock, &res, buff))
{ {
if (mysql_errno(sock) != ER_PARSE_ERROR) if (mysql_errno(sock) != ER_PARSE_ERROR)
...@@ -2523,7 +2547,8 @@ static char *primary_key_fields(const char *table_name) ...@@ -2523,7 +2547,8 @@ static char *primary_key_fields(const char *table_name)
uint result_length = 0; uint result_length = 0;
char *result = 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) || if (mysql_query(sock, show_keys_buff) ||
!(res = mysql_store_result(sock))) !(res = mysql_store_result(sock)))
{ {
......
...@@ -168,8 +168,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, ...@@ -168,8 +168,6 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
keyinfo->write_key= hp_write_key; keyinfo->write_key= hp_write_key;
keyinfo->hash_buckets= 0; 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->min_records= min_records;
share->max_records= max_records; share->max_records= max_records;
...@@ -180,6 +178,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, ...@@ -180,6 +178,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
share->keys= keys; share->keys= keys;
share->max_key_length= max_length; share->max_key_length= max_length;
share->changed= 0; share->changed= 0;
share->auto_key= create_info->auto_key;
share->auto_key_type= create_info->auto_key_type; share->auto_key_type= create_info->auto_key_type;
share->auto_increment= create_info->auto_increment; share->auto_increment= create_info->auto_increment;
/* Must be allocated separately for rename to work */ /* Must be allocated separately for rename to work */
......
...@@ -181,8 +181,10 @@ typedef struct st_heap_info ...@@ -181,8 +181,10 @@ typedef struct st_heap_info
LIST open_list; LIST open_list;
} HP_INFO; } HP_INFO;
typedef struct st_heap_create_info typedef struct st_heap_create_info
{ {
uint auto_key; /* keynr [1 - maxkey] for auto key */
uint auto_key_type; uint auto_key_type;
ulong max_table_size; ulong max_table_size;
ulonglong auto_increment; ulonglong auto_increment;
......
...@@ -432,10 +432,10 @@ while test $# -gt 0; do ...@@ -432,10 +432,10 @@ while test $# -gt 0; do
TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
VALGRIND="$VALGRIND $TMP" VALGRIND="$VALGRIND $TMP"
;; ;;
--skip-ndbcluster) --skip-ndbcluster | --skip-ndb)
USE_NDBCLUSTER="" USE_NDBCLUSTER=""
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-ndbcluster"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-ndbcluster"
;; ;;
--skip-*) --skip-*)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1"
......
...@@ -861,6 +861,13 @@ user c ...@@ -861,6 +861,13 @@ user c
one <one> one <one>
two <two> two <two>
DROP TABLE t1; 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); select convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8);
convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8) convert(_koi8r'' using utf8) < convert(_koi8r'' using utf8)
1 1
...@@ -469,3 +469,11 @@ group_concat(a) ...@@ -469,3 +469,11 @@ group_concat(a)
ABW ABW
ABW ABW
drop table t1; 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;
...@@ -515,7 +515,7 @@ collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set( ...@@ -515,7 +515,7 @@ collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')) coercibility(make_set(
latin2_general_ci 4 latin2_general_ci 4
select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' ')); 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' ')) 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 ')); select collation(trim(_latin2' a ')), coercibility(trim(_latin2' a '));
collation(trim(_latin2' a ')) coercibility(trim(_latin2' a ')) collation(trim(_latin2' a ')) coercibility(trim(_latin2' a '))
latin2_general_ci 4 latin2_general_ci 4
...@@ -630,6 +630,15 @@ t1 CREATE TABLE `t1` ( ...@@ -630,6 +630,15 @@ t1 CREATE TABLE `t1` (
`encode('abcd','ab')` varbinary(4) NOT NULL default '' `encode('abcd','ab')` varbinary(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; 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); select SUBSTR('abcdefg',3,2);
SUBSTR('abcdefg',3,2) SUBSTR('abcdefg',3,2)
cd cd
...@@ -683,16 +692,16 @@ drop table t1, t2; ...@@ -683,16 +692,16 @@ drop table t1, t2;
create table t1 (c1 INT, c2 INT UNSIGNED); create table t1 (c1 INT, c2 INT UNSIGNED);
insert into t1 values ('21474836461','21474836461'); insert into t1 values ('21474836461','21474836461');
Warnings: Warnings:
Warning 1264 Out of range value adjusted for column 'c1' at row 1 Warning 1265 Data truncated 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 'c2' at row 1
insert into t1 values ('-21474836461','-21474836461'); insert into t1 values ('-21474836461','-21474836461');
Warnings: Warnings:
Warning 1264 Out of range value adjusted for column 'c1' at row 1 Warning 1265 Data truncated 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 'c2' at row 1
show warnings; show warnings;
Level Code Message Level Code Message
Warning 1264 Out of range value adjusted for column 'c1' at row 1 Warning 1265 Data truncated 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 'c2' at row 1
select * from t1; select * from t1;
c1 c2 c1 c2
2147483647 4294967295 2147483647 4294967295
......
...@@ -307,3 +307,75 @@ day sample not_cancelled ...@@ -307,3 +307,75 @@ day sample not_cancelled
2004-06-07 1 0 2004-06-07 1 0
NULL 3 1 NULL 3 1
DROP TABLE user_day; 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;
...@@ -4,6 +4,9 @@ reset master; ...@@ -4,6 +4,9 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; 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)); CREATE TABLE t1 (name varchar(64), age smallint(3));
INSERT INTO t1 SET name='Andy', age=31; INSERT INTO t1 SET name='Andy', age=31;
INSERT t1 SET name='Jacob', age=2; INSERT t1 SET name='Jacob', age=2;
......
...@@ -219,3 +219,10 @@ select * from t1; ...@@ -219,3 +219,10 @@ select * from t1;
id id_str id id_str
1 test1 1 test1
drop table t1; 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;
...@@ -694,6 +694,15 @@ SELECT CHARSET('a'); ...@@ -694,6 +694,15 @@ SELECT CHARSET('a');
SELECT user, CONCAT('<', user, '>') AS c FROM t1; SELECT user, CONCAT('<', user, '>') AS c FROM t1;
DROP TABLE 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 # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same
# #
......
...@@ -288,8 +288,16 @@ DROP TABLE t1; ...@@ -288,8 +288,16 @@ DROP TABLE t1;
# #
# Bug #6475 # Bug #6475
# #
create table t1 (a char(3), b char(20), primary key (a, b)); create table t1 (a char(3), b char(20), primary key (a, b));
insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English'); insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
select group_concat(a) from t1 group by b; select group_concat(a) from t1 group by b;
drop table t1; 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;
...@@ -369,6 +369,15 @@ select ...@@ -369,6 +369,15 @@ select
show create table t1; show create table t1;
drop 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 # test for SUBSTR
# #
......
...@@ -125,3 +125,33 @@ SELECT ...@@ -125,3 +125,33 @@ SELECT
DROP TABLE user_day; 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;
source include/master-slave.inc; 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)); CREATE TABLE t1 (name varchar(64), age smallint(3));
INSERT INTO t1 SET name='Andy', age=31; INSERT INTO t1 SET name='Andy', age=31;
INSERT t1 SET name='Jacob', age=2; INSERT t1 SET name='Jacob', age=2;
......
...@@ -179,3 +179,13 @@ insert into t1 (id_str) values ("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(); update t1 set id_str = concat(id_str, id) where id = last_insert_id();
select * from t1; select * from t1;
drop table 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;
...@@ -521,9 +521,17 @@ int ha_heap::create(const char *name, TABLE *table_arg, ...@@ -521,9 +521,17 @@ int ha_heap::create(const char *name, TABLE *table_arg,
seg->null_bit= 0; seg->null_bit= 0;
seg->null_pos= 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(); auto_key_type= field->key_type();
}
} }
} }
mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
...@@ -535,8 +543,8 @@ int ha_heap::create(const char *name, TABLE *table_arg, ...@@ -535,8 +543,8 @@ int ha_heap::create(const char *name, TABLE *table_arg,
found_real_auto_increment= share->next_number_key_offset == 0; found_real_auto_increment= share->next_number_key_offset == 0;
} }
HP_CREATE_INFO hp_create_info; 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.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 ? hp_create_info.auto_increment= (create_info->auto_increment_value ?
create_info->auto_increment_value - 1 : 0); create_info->auto_increment_value - 1 : 0);
hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
......
...@@ -586,6 +586,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) ...@@ -586,6 +586,18 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
return NULL; return NULL;
} }
conv->str_value.copy(); 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; return conv;
} }
......
...@@ -790,6 +790,17 @@ public: ...@@ -790,6 +790,17 @@ public:
Item *safe_charset_converter(CHARSET_INFO *tocs); 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 */ /* Item represents one placeholder ('?') of prepared statement */
...@@ -1274,6 +1285,7 @@ public: ...@@ -1274,6 +1285,7 @@ public:
void save_org_in_field(Field *field) { (*ref)->save_org_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(); } enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); } enum_field_types field_type() const { return (*ref)->field_type(); }
Field *get_tmp_table_field() { return result_field; }
table_map used_tables() const table_map used_tables() const
{ {
return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
......
...@@ -2096,11 +2096,6 @@ longlong Item_func_char_length::val_int() ...@@ -2096,11 +2096,6 @@ longlong Item_func_char_length::val_int()
longlong Item_func_coercibility::val_int() longlong Item_func_coercibility::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (args[0]->null_value)
{
null_value= 1;
return 0;
}
null_value= 0; null_value= 0;
return (longlong) args[0]->collation.derivation; return (longlong) args[0]->collation.derivation;
} }
......
...@@ -267,8 +267,7 @@ String *Item_func_concat::val_str(String *str) ...@@ -267,8 +267,7 @@ String *Item_func_concat::val_str(String *str)
current_thd->variables.max_allowed_packet); current_thd->variables.max_allowed_packet);
goto null; goto null;
} }
if (!args[0]->const_item() && if (res->alloced_length() >= res->length()+res2->length())
res->alloced_length() >= res->length()+res2->length())
{ // Use old buffer { // Use old buffer
res->append(*res2); res->append(*res2);
} }
...@@ -2308,12 +2307,11 @@ void Item_func_set_collation::print(String *str) ...@@ -2308,12 +2307,11 @@ void Item_func_set_collation::print(String *str)
String *Item_func_charset::val_str(String *str) String *Item_func_charset::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
uint dummy_errors; uint dummy_errors;
if ((null_value=(args[0]->null_value || !res->charset()))) CHARSET_INFO *cs= args[0]->collation.collation;
return 0; null_value= 0;
str->copy(res->charset()->csname,strlen(res->charset()->csname), str->copy(cs->csname, strlen(cs->csname),
&my_charset_latin1, collation.collation, &dummy_errors); &my_charset_latin1, collation.collation, &dummy_errors);
return str; return str;
} }
...@@ -2321,12 +2319,11 @@ String *Item_func_charset::val_str(String *str) ...@@ -2321,12 +2319,11 @@ String *Item_func_charset::val_str(String *str)
String *Item_func_collation::val_str(String *str) String *Item_func_collation::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
uint dummy_errors; uint dummy_errors;
CHARSET_INFO *cs= args[0]->collation.collation;
if ((null_value=(args[0]->null_value || !res->charset()))) null_value= 0;
return 0; str->copy(cs->name, strlen(cs->name),
str->copy(res->charset()->name,strlen(res->charset()->name),
&my_charset_latin1, collation.collation, &dummy_errors); &my_charset_latin1, collation.collation, &dummy_errors);
return str; return str;
} }
...@@ -2490,6 +2487,7 @@ String* Item_func_export_set::val_str(String* str) ...@@ -2490,6 +2487,7 @@ String* Item_func_export_set::val_str(String* str)
uint num_set_values = 64; uint num_set_values = 64;
ulonglong mask = 0x1; ulonglong mask = 0x1;
str->length(0); str->length(0);
str->set_charset(collation.collation);
/* Check if some argument is a NULL value */ /* Check if some argument is a NULL value */
if (args[0]->null_value || args[1]->null_value || args[2]->null_value) if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
......
...@@ -368,7 +368,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields) ...@@ -368,7 +368,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
f.rewind(); f.rewind();
while ((field=(Item_field*) f++)) while ((field=(Item_field*) f++))
{ {
if (key_part->field == field->field) if (key_part->field->eq(field->field))
return 1; return 1;
} }
} }
......
...@@ -926,6 +926,7 @@ struct show_var_st init_vars[]= { ...@@ -926,6 +926,7 @@ struct show_var_st init_vars[]= {
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},
{"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG},
#endif #endif
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
{"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
......
...@@ -191,7 +191,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, ...@@ -191,7 +191,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
uint elements, List<Item> &items); uint elements, List<Item> &items);
static void init_tmptable_sum_functions(Item_sum **func); static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); 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 add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr); static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool init_sum_functions(Item_sum **func, Item_sum **end);
...@@ -1386,7 +1386,6 @@ JOIN::exec() ...@@ -1386,7 +1386,6 @@ JOIN::exec()
{ {
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
curr_join->group_list= 0;
} }
thd->proc_info="Copying to group table"; thd->proc_info="Copying to group table";
...@@ -1447,7 +1446,7 @@ JOIN::exec() ...@@ -1447,7 +1446,7 @@ JOIN::exec()
if (curr_join->tmp_having) if (curr_join->tmp_having)
curr_join->tmp_having->update_used_tables(); curr_join->tmp_having->update_used_tables();
if (remove_duplicates(curr_join, curr_tmp_table, 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; DBUG_VOID_RETURN;
curr_join->tmp_having=0; curr_join->tmp_having=0;
curr_join->select_distinct=0; curr_join->select_distinct=0;
...@@ -10132,26 +10131,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -10132,26 +10131,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{ {
if (join->procedure) if (join->procedure)
join->procedure->end_group(); 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) if (!join->first_record)
{ {
/* No matching rows for group function */ /* No matching rows for group function */
join->clear(); join->clear();
} }
copy_sum_funcs(join->sum_funcs); copy_sum_funcs(join->sum_funcs,
if (!join->having || join->having->val_int()) 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,
if (create_myisam_from_heap(join->thd, table, error, 0))
&join->tmp_table_param, DBUG_RETURN(-1);
error, 0)) }
DBUG_RETURN(-1); // Not a table_is_full error if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
} {
else if (join->rollup_write_data((uint) (idx+1), table))
join->send_records++; error= 1;
} }
if (error > 0)
DBUG_RETURN(-1);
if (end_of_records) if (end_of_records)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -12413,11 +12418,10 @@ update_tmptable_sum_func(Item_sum **func_ptr, ...@@ -12413,11 +12418,10 @@ update_tmptable_sum_func(Item_sum **func_ptr,
/* Copy result of sum functions to record in tmp_table */ /* Copy result of sum functions to record in tmp_table */
static void 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_ptr != end_ptr ; func_ptr++)
for (; (func = *func_ptr) ; func_ptr++) (void) (*func_ptr)->save_in_result_field(1);
(void) func->save_in_result_field(1);
return; return;
} }
...@@ -12539,14 +12543,16 @@ bool JOIN::rollup_init() ...@@ -12539,14 +12543,16 @@ bool JOIN::rollup_init()
*/ */
tmp_table_param.group_parts= send_group_parts; tmp_table_param.group_parts= send_group_parts;
if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) + if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
sizeof(List<Item>) + sizeof(Item**) +
ref_pointer_array_size) sizeof(List<Item>) +
* send_group_parts))) ref_pointer_array_size)
* send_group_parts )))
return 1; return 1;
rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
ref_array= (Item**) (rollup.ref_pointer_arrays+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 Prepare space for field list for the different levels
...@@ -12554,12 +12560,16 @@ bool JOIN::rollup_init() ...@@ -12554,12 +12560,16 @@ bool JOIN::rollup_init()
*/ */
for (i= 0 ; i < send_group_parts ; i++) 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]; List<Item> *rollup_fields= &rollup.fields[i];
rollup_fields->empty(); rollup_fields->empty();
rollup.ref_pointer_arrays[i]= ref_array; rollup.ref_pointer_arrays[i]= ref_array;
ref_array+= all_fields.elements; ref_array+= all_fields.elements;
}
for (i= 0 ; i < send_group_parts; i++)
{
for (j=0 ; j < fields_list.elements ; j++) 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; return 0;
} }
...@@ -12663,7 +12673,8 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, ...@@ -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 */ /* Check if this is something that is part of this group by */
ORDER *group_tmp; 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) if (*group_tmp->item == item)
{ {
...@@ -12672,7 +12683,9 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, ...@@ -12672,7 +12683,9 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
set to NULL in this level set to NULL in this level
*/ */
item->maybe_null= 1; // Value will be null sometimes 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; break;
} }
} }
...@@ -12732,6 +12745,58 @@ int JOIN::rollup_send_data(uint idx) ...@@ -12732,6 +12745,58 @@ int JOIN::rollup_send_data(uint idx)
return 0; return 0;
} }
/*
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 clear results if there are not rows found for group
(end_send_group/end_write_group) (end_send_group/end_write_group)
......
...@@ -135,7 +135,7 @@ typedef struct st_rollup ...@@ -135,7 +135,7 @@ typedef struct st_rollup
{ {
enum State { STATE_NONE, STATE_INITED, STATE_READY }; enum State { STATE_NONE, STATE_INITED, STATE_READY };
State state; State state;
Item *item_null; Item_null_result **null_items;
Item ***ref_pointer_arrays; Item ***ref_pointer_arrays;
List<Item> *fields; List<Item> *fields;
} ROLLUP; } ROLLUP;
...@@ -323,6 +323,7 @@ class JOIN :public Sql_alloc ...@@ -323,6 +323,7 @@ class JOIN :public Sql_alloc
bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
Item_sum ***func); Item_sum ***func);
int rollup_send_data(uint idx); int rollup_send_data(uint idx);
int rollup_write_data(uint idx, TABLE *table);
bool test_in_subselect(Item **where); bool test_in_subselect(Item **where);
void join_free(bool full); void join_free(bool full);
void clear(); void clear();
......
...@@ -205,6 +205,10 @@ public: ...@@ -205,6 +205,10 @@ public:
} }
} }
} }
inline void shrink_to_length()
{
Alloced_length= str_length;
}
bool is_alloced() { return alloced; } bool is_alloced() { return alloced; }
inline String& operator = (const String &s) inline String& operator = (const String &s)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment