Commit a6b0d0df authored by ingo@mysql.com's avatar ingo@mysql.com

Merge mysql.com:/home/mydev/mysql-5.1

into  mysql.com:/home/mydev/mysql-5.1-bug11527
parents ab8f100f 54bbc4ab
...@@ -2904,7 +2904,7 @@ sub run_mysqltest ($) { ...@@ -2904,7 +2904,7 @@ sub run_mysqltest ($) {
if ( $opt_debug ) if ( $opt_debug )
{ {
$cmdline_mysqlslap .= $cmdline_mysqlslap .=
" --debug=d:t:A,$opt_vardir_trace/log/mysqldump.trace"; " --debug=d:t:A,$opt_vardir_trace/log/mysqlslap.trace";
} }
} }
......
...@@ -11315,20 +11315,6 @@ DROP TABLE t1; ...@@ -11315,20 +11315,6 @@ DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t3; DROP TABLE t3;
DROP TABLE t4; DROP TABLE t4;
RESET MASTER;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 102;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 102 Query 1 189 use `test`; CREATE TABLE t1(f1 blob)
master-bin.000001 189 Table_map 1 228 test.t1
master-bin.000001 228 Write_rows 1 262
SELECT HEX(f1) FROM t1;
HEX(f1)
8300
DROP table t1;
SET collation_connection='cp932_japanese_ci'; SET collation_connection='cp932_japanese_ci';
create table t1 select repeat('a',4000) a; create table t1 select repeat('a',4000) a;
delete from t1; delete from t1;
......
drop table if exists t1,t2;
create table t1(a int, unique(a)); create table t1(a int, unique(a));
insert into t1 values(2); insert into t1 values(2);
create table t2(a int); create table t2(a int);
......
...@@ -334,3 +334,24 @@ lock table mysql.user write; ...@@ -334,3 +334,24 @@ lock table mysql.user write;
revoke all on *.* from 'mysqltest_1'@'localhost'; revoke all on *.* from 'mysqltest_1'@'localhost';
unlock tables; unlock tables;
drop user 'mysqltest_1'@'localhost'; drop user 'mysqltest_1'@'localhost';
create database TESTDB;
create table t2(a int);
create temporary table t1 as select * from mysql.user;
delete from mysql.user where host='localhost';
INSERT INTO mysql.user (host, user, password) VALUES
('%','mysqltest_1',password('password'));
Warnings:
Warning 1364 Field 'ssl_cipher' doesn't have a default value
Warning 1364 Field 'x509_issuer' doesn't have a default value
Warning 1364 Field 'x509_subject' doesn't have a default value
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
('%','TESTDB','mysqltest_1','Y');
FLUSH PRIVILEGES;
create database TEStdb;
ERROR 42000: Access denied for user 'mysqltest_1'@'%' to database 'TEStdb'
delete from mysql.user;
delete from mysql.db where host='%' and user='mysqltest_1' and db='TESTDB';
insert into mysql.user select * from t1;
drop table t1, t2;
drop database TESTDB;
flush privileges;
drop table if exists t1, t2; drop table if exists t1, t2;
== Connected to server1 ==
set GLOBAL query_cache_type=on; set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776; set GLOBAL query_cache_size=1355776;
set GLOBAL ndb_cache_check_time=1; set GLOBAL ndb_cache_check_time=1;
reset query cache; reset query cache;
flush status; flush status;
== Connected to server2 ==
set GLOBAL query_cache_type=on; set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776; set GLOBAL query_cache_size=1355776;
set GLOBAL ndb_cache_check_time=1; set GLOBAL ndb_cache_check_time=1;
reset query cache; reset query cache;
flush status; flush status;
== Connected to server1 ==
create table t1 (a int) engine=ndbcluster; create table t1 (a int) engine=ndbcluster;
create table t2 (a int) engine=ndbcluster; create table t2 (a int) engine=ndbcluster;
insert into t1 value (2); insert into t1 value (2);
...@@ -16,18 +19,22 @@ insert into t2 value (3); ...@@ -16,18 +19,22 @@ insert into t2 value (3);
select * from t1; select * from t1;
a a
2 2
select a != 3 from t1;
a != 3
1
select * from t2; select * from t2;
a a
3 3
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 2 Qcache_queries_in_cache 3
show status like "Qcache_inserts"; show status like "Qcache_inserts";
Variable_name Value Variable_name Value
Qcache_inserts 2 Qcache_inserts 3
show status like "Qcache_hits"; show status like "Qcache_hits";
Variable_name Value Variable_name Value
Qcache_hits 0 Qcache_hits 0
== Connected to server2 ==
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 0 Qcache_queries_in_cache 0
...@@ -50,24 +57,13 @@ show status like "Qcache_hits"; ...@@ -50,24 +57,13 @@ show status like "Qcache_hits";
Variable_name Value Variable_name Value
Qcache_hits 0 Qcache_hits 0
update t1 set a=3 where a=2; update t1 set a=3 where a=2;
show status like "Qcache_queries_in_cache"; == Connected to server1 ==
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from t1; select * from t1;
a a
3 3
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 3 Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
drop table t1, t2; drop table t1, t2;
set GLOBAL query_cache_size=0; set GLOBAL query_cache_size=0;
set GLOBAL ndb_cache_check_time=0; set GLOBAL ndb_cache_check_time=0;
......
...@@ -429,3 +429,35 @@ disconnect con2root; ...@@ -429,3 +429,35 @@ disconnect con2root;
disconnect con3root; disconnect con3root;
# End of 4.1 tests # End of 4.1 tests
#
# Bug#17279 user with no global privs and with create
# priv in db can create databases
#
create database TESTDB;
create table t2(a int);
create temporary table t1 as select * from mysql.user;
delete from mysql.user where host='localhost';
INSERT INTO mysql.user (host, user, password) VALUES
('%','mysqltest_1',password('password'));
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
('%','TESTDB','mysqltest_1','Y');
FLUSH PRIVILEGES;
connect (con1,localhost,mysqltest_1,password,TESTDB);
# The user mysqltest_1 should only be allowed access to
# database TESTDB, not TEStdb
--error 1044
create database TEStdb;
# Clean-up
connection default;
delete from mysql.user;
delete from mysql.db where host='%' and user='mysqltest_1' and db='TESTDB';
insert into mysql.user select * from t1;
drop table t1, t2;
drop database TESTDB;
flush privileges;
# Embedded server doesn't support external clients # Embedded server doesn't support external clients
--source include/not_embedded.inc --source include/not_embedded.inc
# Windows does not have SOCKET, but will try to create a PIPE as well as MEMORY
--source include/not_windows.inc
# test for Bug #4998 "--protocol doesn't reject bad values" # test for Bug #4998 "--protocol doesn't reject bad values"
......
...@@ -10,6 +10,7 @@ drop table if exists t1, t2; ...@@ -10,6 +10,7 @@ drop table if exists t1, t2;
# Turn on and reset query cache on server1 # Turn on and reset query cache on server1
connection server1; connection server1;
echo == Connected to server1 ==;
set GLOBAL query_cache_type=on; set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776; set GLOBAL query_cache_size=1355776;
set GLOBAL ndb_cache_check_time=1; set GLOBAL ndb_cache_check_time=1;
...@@ -18,6 +19,7 @@ flush status; ...@@ -18,6 +19,7 @@ flush status;
# Turn on and reset query cache on server2 # Turn on and reset query cache on server2
connection server2; connection server2;
echo == Connected to server2 ==;
set GLOBAL query_cache_type=on; set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776; set GLOBAL query_cache_size=1355776;
set GLOBAL ndb_cache_check_time=1; set GLOBAL ndb_cache_check_time=1;
...@@ -27,11 +29,14 @@ flush status; ...@@ -27,11 +29,14 @@ flush status;
# Create test tables in NDB and load them into cache # Create test tables in NDB and load them into cache
# on server1 # on server1
connection server1; connection server1;
echo == Connected to server1 ==;
create table t1 (a int) engine=ndbcluster; create table t1 (a int) engine=ndbcluster;
create table t2 (a int) engine=ndbcluster; create table t2 (a int) engine=ndbcluster;
insert into t1 value (2); insert into t1 value (2);
insert into t2 value (3); insert into t2 value (3);
select * from t1; select * from t1;
# Run the check query once to load it into qc on server1
select a != 3 from t1;
select * from t2; select * from t2;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts"; show status like "Qcache_inserts";
...@@ -40,6 +45,7 @@ show status like "Qcache_hits"; ...@@ -40,6 +45,7 @@ show status like "Qcache_hits";
# Connect server2, load table in to cache, then update the table # Connect server2, load table in to cache, then update the table
connection server2; connection server2;
echo == Connected to server2 ==;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts"; show status like "Qcache_inserts";
show status like "Qcache_hits"; show status like "Qcache_hits";
...@@ -49,12 +55,10 @@ show status like "Qcache_inserts"; ...@@ -49,12 +55,10 @@ show status like "Qcache_inserts";
show status like "Qcache_hits"; show status like "Qcache_hits";
update t1 set a=3 where a=2; update t1 set a=3 where a=2;
# Connect to server1 and check that cache is invalidated # Connect to server1 and check that cache is invalidated
# and correct data is returned # and correct data is returned
connection server1; connection server1;
show status like "Qcache_queries_in_cache"; echo == Connected to server1 ==;
show status like "Qcache_inserts";
show status like "Qcache_hits";
# Loop and wait for max 10 seconds until query cache thread # Loop and wait for max 10 seconds until query cache thread
# has invalidated the cache and the column a in t1 is equal to 3 # has invalidated the cache and the column a in t1 is equal to 3
...@@ -75,8 +79,6 @@ select * from t1; ...@@ -75,8 +79,6 @@ select * from t1;
# There should now be three queries in the cache # There should now be three queries in the cache
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
# And inserts should be four
show status like "Qcache_inserts";
drop table t1, t2; drop table t1, t2;
......
# Requires row logging because warnings produced when creating
# the tables in "gis_generic" with no PK and BLOB's differ
--source include/have_binlog_format_row.inc
--source include/have_ndb.inc --source include/have_ndb.inc
SET storage_engine=ndbcluster; SET storage_engine=ndbcluster;
--source include/gis_generic.inc --source include/gis_generic.inc
......
...@@ -7449,7 +7449,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) ...@@ -7449,7 +7449,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
ndb_util_thread= pthread_self(); ndb_util_thread= pthread_self();
thd->thread_stack= (char*)&thd; /* remember where our stack is */ thd->thread_stack= (char*)&thd; /* remember where our stack is */
if (thd->store_globals() && (ndb->init() != -1)) if (thd->store_globals() || (ndb->init() != 0))
{ {
thd->cleanup(); thd->cleanup();
delete thd; delete thd;
......
...@@ -700,11 +700,15 @@ typedef struct st_handler_buffer ...@@ -700,11 +700,15 @@ typedef struct st_handler_buffer
typedef struct system_status_var SSV; typedef struct system_status_var SSV;
/*
The handler class is the interface for dynamically loadable
storage engines. Do not add ifdefs and take care when adding or
changing virtual functions to avoid vtable confusion
*/
class handler :public Sql_alloc class handler :public Sql_alloc
{ {
#ifdef WITH_PARTITION_STORAGE_ENGINE friend class ha_partition;
friend class ha_partition;
#endif
protected: protected:
struct st_table_share *table_share; /* The table definition */ struct st_table_share *table_share; /* The table definition */
struct st_table *table; /* The current open table */ struct st_table *table; /* The current open table */
...@@ -1282,7 +1286,7 @@ class handler :public Sql_alloc ...@@ -1282,7 +1286,7 @@ class handler :public Sql_alloc
virtual const char *table_type() const =0; virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0; virtual const char **bas_ext() const =0;
virtual ulong table_flags(void) const =0; virtual ulong table_flags(void) const =0;
#ifdef WITH_PARTITION_STORAGE_ENGINE
virtual int get_default_no_partitions(ulonglong max_rows) { return 1;} virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
virtual void set_auto_partitions(partition_info *part_info) { return; } virtual void set_auto_partitions(partition_info *part_info) { return; }
virtual bool get_no_parts(const char *name, virtual bool get_no_parts(const char *name,
...@@ -1292,7 +1296,7 @@ class handler :public Sql_alloc ...@@ -1292,7 +1296,7 @@ class handler :public Sql_alloc
return 0; return 0;
} }
virtual void set_part_info(partition_info *part_info) {return;} virtual void set_part_info(partition_info *part_info) {return;}
#endif
virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0; virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
......
...@@ -1116,6 +1116,13 @@ class Item_func_group_concat : public Item_sum ...@@ -1116,6 +1116,13 @@ class Item_func_group_concat : public Item_sum
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; } const char *func_name() const { return "group_concat"; }
virtual Item_result result_type () const { return STRING_RESULT; } virtual Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const
{
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
return FIELD_TYPE_BLOB;
else
return MYSQL_TYPE_VARCHAR;
}
void clear(); void clear();
bool add(); bool add();
void reset_field() { DBUG_ASSERT(0); } // not used void reset_field() { DBUG_ASSERT(0); } // not used
......
...@@ -208,23 +208,44 @@ my_bool net_realloc(NET *net, ulong length) ...@@ -208,23 +208,44 @@ my_bool net_realloc(NET *net, ulong length)
RETURN VALUES RETURN VALUES
0 No data to read 0 No data to read
1 Data or EOF to read 1 Data or EOF to read
-1 Don't know if data is ready or not
*/ */
static my_bool net_data_is_ready(my_socket sd) static int net_data_is_ready(my_socket sd)
{ {
#ifdef HAVE_POLL
struct pollfd ufds;
int res;
ufds.fd= sd;
ufds.events= POLLIN | POLLPRI;
if (!(res= poll(&ufds, 1, 0)))
return 0;
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
return 0;
return 1;
#else
fd_set sfds; fd_set sfds;
struct timeval tv; struct timeval tv;
int res; int res;
#ifndef __WIN__
/* Windows uses an _array_ of 64 fd's as default, so it's safe */
if (sd >= FD_SETSIZE)
return -1;
#define NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE
#endif
FD_ZERO(&sfds); FD_ZERO(&sfds);
FD_SET(sd, &sfds); FD_SET(sd, &sfds);
tv.tv_sec= tv.tv_usec= 0; tv.tv_sec= tv.tv_usec= 0;
if ((res= select(sd+1, &sfds, NULL, NULL, &tv)) < 0) if ((res= select(sd+1, &sfds, NULL, NULL, &tv)) < 0)
return FALSE; return 0;
else else
return test(res ? FD_ISSET(sd, &sfds) : 0); return test(res ? FD_ISSET(sd, &sfds) : 0);
#endif
} }
...@@ -251,10 +272,10 @@ static my_bool net_data_is_ready(my_socket sd) ...@@ -251,10 +272,10 @@ static my_bool net_data_is_ready(my_socket sd)
void net_clear(NET *net) void net_clear(NET *net)
{ {
int count; int count, ready;
DBUG_ENTER("net_clear"); DBUG_ENTER("net_clear");
#if !defined(EMBEDDED_LIBRARY) #if !defined(EMBEDDED_LIBRARY)
while(net_data_is_ready(net->vio->sd)) while((ready= net_data_is_ready(net->vio->sd)) > 0)
{ {
/* The socket is ready */ /* The socket is ready */
if ((count= vio_read(net->vio, (char*) (net->buff), if ((count= vio_read(net->vio, (char*) (net->buff),
...@@ -274,6 +295,22 @@ void net_clear(NET *net) ...@@ -274,6 +295,22 @@ void net_clear(NET *net)
break; break;
} }
} }
#ifdef NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE
/* 'net_data_is_ready' returned "don't know" */
if (ready == -1)
{
/* Read unblocking to clear net */
my_bool old_mode;
if (!vio_blocking(net->vio, FALSE, &old_mode))
{
while ((count= vio_read(net->vio, (char*) (net->buff),
(uint32) net->max_packet)) > 0)
DBUG_PRINT("info",("skipped %d bytes from file: %s",
count, vio_description(net->vio)));
vio_blocking(net->vio, TRUE, &old_mode);
}
}
#endif
#endif #endif
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */ net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff; net->write_pos=net->buff;
......
...@@ -263,7 +263,9 @@ my_bool acl_init(bool dont_read_acl_tables) ...@@ -263,7 +263,9 @@ my_bool acl_init(bool dont_read_acl_tables)
acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0, acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0,
(hash_get_key) acl_entry_get_key, (hash_get_key) acl_entry_get_key,
(hash_free_key) free, system_charset_info); (hash_free_key) free,
/* Use the case sensitive "binary" charset */
&my_charset_bin);
if (dont_read_acl_tables) if (dont_read_acl_tables)
{ {
DBUG_RETURN(0); /* purecov: tested */ DBUG_RETURN(0); /* purecov: tested */
......
...@@ -1226,7 +1226,8 @@ static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, ...@@ -1226,7 +1226,8 @@ static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp,
bool mysql_change_db(THD *thd, const char *name, bool no_access_check) bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
{ {
int length, db_length; int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME)); char *dbname= thd->slave_thread ? (char *) name :
my_strdup((char *) name, MYF(MY_WME));
char path[FN_REFLEN]; char path[FN_REFLEN];
HA_CREATE_INFO create; HA_CREATE_INFO create;
bool system_db= 0; bool system_db= 0;
...@@ -1249,7 +1250,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) ...@@ -1249,7 +1250,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
system_db= 1; system_db= 1;
goto end; goto end;
} }
x_free(dbname); /* purecov: inspected */ if (!(thd->slave_thread))
x_free(dbname); /* purecov: inspected */
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
MYF(0)); /* purecov: inspected */ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
...@@ -1257,7 +1259,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) ...@@ -1257,7 +1259,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
if (check_db_name(dbname)) if (check_db_name(dbname))
{ {
my_error(ER_WRONG_DB_NAME, MYF(0), dbname); my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
my_free(dbname, MYF(0)); if (!(thd->slave_thread))
my_free(dbname, MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_PRINT("info",("Use database: %s", dbname)); DBUG_PRINT("info",("Use database: %s", dbname));
...@@ -1287,7 +1290,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) ...@@ -1287,7 +1290,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
dbname); dbname);
general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR),
sctx->priv_user, sctx->priv_host, dbname); sctx->priv_user, sctx->priv_host, dbname);
my_free(dbname,MYF(0)); if (!(thd->slave_thread))
my_free(dbname,MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
...@@ -1298,7 +1302,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) ...@@ -1298,7 +1302,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
if (my_access(path,F_OK)) if (my_access(path,F_OK))
{ {
my_error(ER_BAD_DB_ERROR, MYF(0), dbname); my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
my_free(dbname,MYF(0)); if (!(thd->slave_thread))
my_free(dbname,MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
end: end:
...@@ -1306,7 +1311,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) ...@@ -1306,7 +1311,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
x_free(thd->db); x_free(thd->db);
if (dbname && dbname[0] == 0) if (dbname && dbname[0] == 0)
{ {
my_free(dbname, MYF(0)); if (!(thd->slave_thread))
my_free(dbname, MYF(0));
thd->db= NULL; thd->db= NULL;
thd->db_length= 0; thd->db_length= 0;
} }
......
...@@ -1353,6 +1353,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) ...@@ -1353,6 +1353,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale)
} }
from+=i; from+=i;
*buf=x ^ mask; *buf=x ^ mask;
if (((uint32)*buf) >= powers10[intg0x+1])
goto err;
if (buf > to->buf || *buf != 0) if (buf > to->buf || *buf != 0)
buf++; buf++;
else else
...@@ -1362,6 +1364,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) ...@@ -1362,6 +1364,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale)
{ {
DBUG_ASSERT(sizeof(dec1) == 4); DBUG_ASSERT(sizeof(dec1) == 4);
*buf=mi_sint4korr(from) ^ mask; *buf=mi_sint4korr(from) ^ mask;
if (((uint32)*buf) > DIG_MAX)
goto err;
if (buf > to->buf || *buf != 0) if (buf > to->buf || *buf != 0)
buf++; buf++;
else else
...@@ -1372,6 +1376,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) ...@@ -1372,6 +1376,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale)
{ {
DBUG_ASSERT(sizeof(dec1) == 4); DBUG_ASSERT(sizeof(dec1) == 4);
*buf=mi_sint4korr(from) ^ mask; *buf=mi_sint4korr(from) ^ mask;
if (((uint32)*buf) > DIG_MAX)
goto err;
buf++; buf++;
} }
if (frac0x) if (frac0x)
...@@ -1387,10 +1393,17 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) ...@@ -1387,10 +1393,17 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale)
default: DBUG_ASSERT(0); default: DBUG_ASSERT(0);
} }
*buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x];
if (((uint32)*buf) > DIG_MAX)
goto err;
buf++; buf++;
} }
my_afree(d_copy); my_afree(d_copy);
return error; return error;
err:
my_afree(d_copy);
decimal_make_zero(((decimal_t*) to));
return(E_DEC_BAD_NUM);
} }
/* /*
......
...@@ -14840,6 +14840,40 @@ static void test_bug15613() ...@@ -14840,6 +14840,40 @@ static void test_bug15613()
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
} }
/* /*
Bug#14169: type of group_concat() result changed to blob if tmp_table was used
*/
static void test_bug14169()
{
MYSQL_STMT *stmt;
const char *stmt_text;
MYSQL_RES *res;
MYSQL_FIELD *field;
int rc;
myheader("test_bug14169");
rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
rc= mysql_query(mysql, "set session group_concat_max_len=1024");
myquery(rc);
rc= mysql_query(mysql, "create table t1 (f1 int unsigned, f2 varchar(255))");
myquery(rc);
rc= mysql_query(mysql, "insert into t1 values (1,repeat('a',255)),"
"(2,repeat('b',255))");
myquery(rc);
stmt= mysql_stmt_init(mysql);
stmt_text= "select f2,group_concat(f1) from t1 group by f2";
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
myquery(rc);
res= mysql_stmt_result_metadata(stmt);
field= mysql_fetch_fields(res);
if (!opt_silent)
printf("GROUP_CONCAT() result type %i", field[1].type);
DIE_UNLESS(field[1].type == MYSQL_TYPE_BLOB);
rc= mysql_query(mysql, "drop table t1");
myquery(rc);
}/*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -15104,6 +15138,7 @@ static struct my_tests_st my_tests[]= { ...@@ -15104,6 +15138,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug16143", test_bug16143 }, { "test_bug16143", test_bug16143 },
{ "test_bug16144", test_bug16144 }, { "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 }, { "test_bug15613", test_bug15613 },
{ "test_bug14169", test_bug14169 },
{ 0, 0 } { 0, 0 }
}; };
......
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