mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 21:12:26 +01:00
Merge mysql.com:/home/jonas/src/mysql-5.0
into mysql.com:/home/jonas/src/mysql-5.0-ndb BitKeeper/etc/logging_ok: auto-union ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/ha_ndbcluster.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged
This commit is contained in:
commit
27ba35b30e
67 changed files with 1583 additions and 569 deletions
|
@ -19,8 +19,6 @@ if test -r /proc/cpuinfo ; then
|
|||
if test -z "$model_name" ; then
|
||||
model_name=`uname -m`
|
||||
fi
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$cpu_family--$model_name" in
|
||||
|
|
|
@ -50,6 +50,8 @@ dlenev@build.mysql.com
|
|||
dlenev@jabberwock.localdomain
|
||||
dlenev@mysql.com
|
||||
ejonore@mc03.ndb.mysql.com
|
||||
evgen@moonbone.(none)
|
||||
evgen@moonbone.local
|
||||
gbichot@production.mysql.com
|
||||
gbichot@quadita2.mysql.com
|
||||
gbichot@quadxeon.mysql.com
|
||||
|
|
|
@ -102,5 +102,10 @@ tags:
|
|||
test:
|
||||
cd mysql-test; ./mysql-test-run && ./mysql-test-run --ps-protocol
|
||||
|
||||
test-force:
|
||||
cd mysql-test; \
|
||||
mysql-test-run --force ;\
|
||||
mysql-test-run --ps-protocol --force
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
||||
|
|
|
@ -727,7 +727,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
|
|||
void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
|
||||
|
||||
new_line = 1;
|
||||
if (mysql_query(mysql, "show status") ||
|
||||
if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
|
||||
!(res = mysql_store_result(mysql)))
|
||||
{
|
||||
my_printf_error(0, "unable to show status; error: '%s'", MYF(ME_BELL),
|
||||
|
|
|
@ -646,8 +646,8 @@ m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
|
|||
'void exit (int);' \
|
||||
'#include <stdlib.h>'
|
||||
do
|
||||
_AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
|
||||
$ac_declaration],
|
||||
_AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration
|
||||
@%:@include <stdlib.h>],
|
||||
[exit (42);])],
|
||||
[],
|
||||
[continue])
|
||||
|
|
|
@ -116,8 +116,6 @@ AC_SUBST(SAVE_LDFLAGS)
|
|||
AC_SUBST(SAVE_CXXLDFLAGS)
|
||||
AC_SUBST(CXXLDFLAGS)
|
||||
|
||||
AC_PREREQ(2.58)dnl Minimum Autoconf version required.
|
||||
|
||||
#AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE
|
||||
|
||||
AM_SANITY_CHECK
|
||||
|
@ -1800,6 +1798,9 @@ If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
|
|||
again]);
|
||||
fi
|
||||
fi
|
||||
AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include <sys/types.h>])
|
||||
AC_CHECK_TYPES([size_t], [], [], [#include <stdio.h>])
|
||||
|
||||
MYSQL_PTHREAD_YIELD
|
||||
|
||||
######################################################################
|
||||
|
|
|
@ -106,20 +106,33 @@ functions */
|
|||
|
||||
/* Type information */
|
||||
|
||||
#if defined(__EMX__) || !defined(HAVE_UINT)
|
||||
#undef HAVE_UINT
|
||||
#define HAVE_UINT
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
#endif /* defined(__EMX__) || !defined(HAVE_UINT) */
|
||||
|
||||
typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
|
||||
typedef __int64 longlong;
|
||||
#ifndef HAVE_SIGSET_T
|
||||
typedef int sigset_t;
|
||||
#endif
|
||||
#define longlong_defined
|
||||
/* off_t should not be __int64 because of conflicts in header files;
|
||||
Use my_off_t or os_off_t instead */
|
||||
/*
|
||||
off_t should not be __int64 because of conflicts in header files;
|
||||
Use my_off_t or os_off_t instead
|
||||
*/
|
||||
#ifndef HAVE_OFF_T
|
||||
typedef long off_t;
|
||||
#endif
|
||||
typedef __int64 os_off_t;
|
||||
#ifdef _WIN64
|
||||
typedef UINT_PTR rf_SetTimer;
|
||||
#else
|
||||
#ifndef HAVE_SIZE_T
|
||||
typedef unsigned int size_t;
|
||||
#endif
|
||||
typedef uint rf_SetTimer;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -425,6 +425,8 @@ int __void__;
|
|||
#endif
|
||||
|
||||
#if defined(__EMX__) || !defined(HAVE_UINT)
|
||||
#undef HAVE_UINT
|
||||
#define HAVE_UINT
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
|
|
|
@ -638,6 +638,7 @@ extern uint dirname_part(my_string to,const char *name);
|
|||
extern uint dirname_length(const char *name);
|
||||
#define base_name(A) (A+dirname_length(A))
|
||||
extern int test_if_hard_path(const char *dir_name);
|
||||
extern my_bool has_path(const char *name);
|
||||
extern char *convert_dirname(char *to, const char *from, const char *from_end);
|
||||
extern void to_unix_path(my_string name);
|
||||
extern my_string fn_ext(const char *name);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
|
||||
#endif
|
||||
#include <my_getopt.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if INT_MAX > 32767
|
||||
#define BITS_SAVED 32
|
||||
|
@ -1996,7 +1997,9 @@ static void write_bits (register ulong value, register uint bits)
|
|||
{
|
||||
reg3 uint byte_buff;
|
||||
bits= (uint) -file_buffer.bits;
|
||||
byte_buff=file_buffer.current_byte | (uint) (value >> bits);
|
||||
DBUG_ASSERT(bits <= 8 * sizeof(value));
|
||||
byte_buff= (file_buffer.current_byte |
|
||||
((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
|
||||
#if BITS_SAVED == 32
|
||||
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
|
||||
*file_buffer.pos++= (byte) (byte_buff >> 16) ;
|
||||
|
@ -2004,7 +2007,9 @@ static void write_bits (register ulong value, register uint bits)
|
|||
*file_buffer.pos++= (byte) (byte_buff >> 8) ;
|
||||
*file_buffer.pos++= (byte) byte_buff;
|
||||
|
||||
value&=(1 << bits)-1;
|
||||
DBUG_ASSERT(bits <= 8 * sizeof(ulong));
|
||||
if (bits != 8 * sizeof(value))
|
||||
value&= (((ulong) 1) << bits) - 1;
|
||||
#if BITS_SAVED == 16
|
||||
if (bits >= sizeof(uint))
|
||||
{
|
||||
|
|
|
@ -80,7 +80,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
|
|||
continue; /* Skip comments */
|
||||
}
|
||||
|
||||
if (!test_if_hard_path(buff))
|
||||
if (!has_path(buff))
|
||||
{
|
||||
VOID(strmake(name_buff+dir_length,buff,
|
||||
sizeof(name_buff)-1-dir_length));
|
||||
|
|
|
@ -192,6 +192,8 @@ select count(*) from t3;
|
|||
count(*)
|
||||
1199
|
||||
rename table t3 to t4;
|
||||
Warnings:
|
||||
Error 7 Error on rename of './test/t3.ARN' to './test/t4.ARN' (Errcode: 2)
|
||||
select * from t4 where fld3='bonfire';
|
||||
auto fld1 companynr fld3 fld4 fld5 fld6
|
||||
1191 068504 00 bonfire corresponds positively
|
||||
|
|
|
@ -128,3 +128,20 @@ t2.value64=t1.value64;
|
|||
value64 value32 value64 value32
|
||||
9223372036854775807 2 9223372036854775807 4
|
||||
drop table t1, t2;
|
||||
create table t1 select 1 as 'a';
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` bigint(1) NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 select 9223372036854775809 as 'a';
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` bigint(19) unsigned NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
select * from t1;
|
||||
a
|
||||
9223372036854775809
|
||||
drop table t1;
|
||||
|
|
|
@ -4,12 +4,11 @@ CAST(1-2 AS UNSIGNED)
|
|||
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
|
||||
CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
|
||||
-1
|
||||
select CONVERT('-1',UNSIGNED);
|
||||
CONVERT('-1',UNSIGNED)
|
||||
18446744073709551615
|
||||
select CAST('10 ' as unsigned integer);
|
||||
CAST('10 ' as unsigned integer)
|
||||
10
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: '10 '
|
||||
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
|
||||
cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
|
||||
18446744073709551611 18446744073709551611
|
||||
|
@ -100,6 +99,41 @@ select 10E+0+'a';
|
|||
10
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'a'
|
||||
select cast('18446744073709551616' as unsigned);
|
||||
cast('18446744073709551616' as unsigned)
|
||||
18446744073709551615
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: '18446744073709551616'
|
||||
select cast('18446744073709551616' as signed);
|
||||
cast('18446744073709551616' as signed)
|
||||
-1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: '18446744073709551616'
|
||||
select cast('9223372036854775809' as signed);
|
||||
cast('9223372036854775809' as signed)
|
||||
-9223372036854775807
|
||||
Warnings:
|
||||
Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
|
||||
select cast('-1' as unsigned);
|
||||
cast('-1' as unsigned)
|
||||
18446744073709551615
|
||||
Warnings:
|
||||
Warning 1105 Cast to unsigned converted negative integer to it's positive complement
|
||||
select cast('abc' as signed);
|
||||
cast('abc' as signed)
|
||||
0
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: 'abc'
|
||||
select cast('1a' as signed);
|
||||
cast('1a' as signed)
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: '1a'
|
||||
select cast('' as signed);
|
||||
cast('' as signed)
|
||||
0
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect INTEGER value: ''
|
||||
set names binary;
|
||||
select cast(_latin1'test' as char character set latin2);
|
||||
cast(_latin1'test' as char character set latin2)
|
||||
|
@ -255,6 +289,39 @@ timediff(cast('2004-12-30 12:00:00' as time), '12:00:00')
|
|||
select timediff(cast('1 12:00:00' as time), '12:00:00');
|
||||
timediff(cast('1 12:00:00' as time), '12:00:00')
|
||||
24:00:00
|
||||
select cast(18446744073709551615 as unsigned);
|
||||
cast(18446744073709551615 as unsigned)
|
||||
18446744073709551615
|
||||
select cast(18446744073709551615 as signed);
|
||||
cast(18446744073709551615 as signed)
|
||||
-1
|
||||
select cast('18446744073709551615' as unsigned);
|
||||
cast('18446744073709551615' as unsigned)
|
||||
18446744073709551615
|
||||
select cast('18446744073709551615' as signed);
|
||||
cast('18446744073709551615' as signed)
|
||||
-1
|
||||
Warnings:
|
||||
Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
|
||||
select cast('9223372036854775807' as signed);
|
||||
cast('9223372036854775807' as signed)
|
||||
9223372036854775807
|
||||
select cast(concat('184467440','73709551615') as unsigned);
|
||||
cast(concat('184467440','73709551615') as unsigned)
|
||||
18446744073709551615
|
||||
select cast(concat('184467440','73709551615') as signed);
|
||||
cast(concat('184467440','73709551615') as signed)
|
||||
-1
|
||||
Warnings:
|
||||
Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
|
||||
select cast(repeat('1',20) as unsigned);
|
||||
cast(repeat('1',20) as unsigned)
|
||||
11111111111111111111
|
||||
select cast(repeat('1',20) as signed);
|
||||
cast(repeat('1',20) as signed)
|
||||
-7335632962598440505
|
||||
Warnings:
|
||||
Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
|
||||
select cast('1.2' as decimal(3,2));
|
||||
cast('1.2' as decimal(3,2))
|
||||
1.20
|
||||
|
|
|
@ -801,5 +801,5 @@ CREATE TABLE t1 (st varchar(100));
|
|||
INSERT INTO t1 VALUES ("Fake string");
|
||||
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
|
||||
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
||||
ERROR HY000: Unknown error
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -461,9 +461,9 @@ Note 1003 select issimple(multipoint(point(3,6),point(4,10))) AS `issimple(Multi
|
|||
create table t1 (a geometry not null);
|
||||
insert into t1 values (GeomFromText('Point(1 2)'));
|
||||
insert into t1 values ('Garbage');
|
||||
ERROR HY000: Unknown error
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert IGNORE into t1 values ('Garbage');
|
||||
ERROR HY000: Unknown error
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
alter table t1 add spatial index(a);
|
||||
drop table t1;
|
||||
create table t1(a geometry not null, spatial index(a));
|
||||
|
@ -655,3 +655,13 @@ t1 where object_id=85984;
|
|||
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
|
||||
85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469)
|
||||
drop table t1;
|
||||
create table t1 (fl geometry);
|
||||
insert into t1 values (1);
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values (1.11);
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values ("qwerty");
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
insert into t1 values (pointfromtext('point(1,1)'));
|
||||
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
|
||||
drop table t1;
|
||||
|
|
|
@ -702,3 +702,12 @@ c
|
|||
val-74
|
||||
val-98
|
||||
drop table t1,t2;
|
||||
create table t1 (b int4 unsigned not null);
|
||||
insert into t1 values(3000000000);
|
||||
select * from t1;
|
||||
b
|
||||
3000000000
|
||||
select min(b) from t1;
|
||||
min(b)
|
||||
3000000000
|
||||
drop table t1;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
drop table if exists t1;
|
||||
create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
|
||||
select * from t1;
|
||||
c1 c2 stamp
|
||||
|
|
|
@ -13,6 +13,26 @@ a
|
|||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 0
|
||||
select * from t1;
|
||||
a
|
||||
2
|
||||
drop table t1;
|
||||
create table t1 (a int) engine=ndbcluster;
|
||||
insert into t1 value (2);
|
||||
select * from t1;
|
||||
a
|
||||
2
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 0
|
||||
drop table t1;
|
||||
create table t1 (a int) engine=ndbcluster;
|
||||
insert into t1 value (2);
|
||||
select * from t1;
|
||||
ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster
|
||||
select * from t1;
|
||||
a
|
||||
2
|
||||
flush status;
|
||||
select * from t1;
|
||||
a
|
||||
|
@ -20,7 +40,7 @@ a
|
|||
update t1 set a=3 where a=2;
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 1
|
||||
Handler_discover 0
|
||||
create table t3 (a int not null primary key, b varchar(22),
|
||||
c int, last_col text) engine=ndb;
|
||||
insert into t3 values(1, 'Hi!', 89, 'Longtext column');
|
||||
|
|
|
@ -97,3 +97,29 @@ Variable_name Value
|
|||
Created_tmp_disk_tables 0
|
||||
Created_tmp_tables 2
|
||||
drop table t1;
|
||||
create temporary table t1 as select 'This is temp. table' A;
|
||||
create view t1 as select 'This is view' A;
|
||||
select * from t1;
|
||||
A
|
||||
This is temp. table
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TEMPORARY TABLE `t1` (
|
||||
`A` varchar(19) NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
show create view t1;
|
||||
View Create View
|
||||
t1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`t1` AS select _latin1'This is view' AS `A`
|
||||
drop view t1;
|
||||
select * from t1;
|
||||
A
|
||||
This is temp. table
|
||||
create view t1 as select 'This is view again' A;
|
||||
select * from t1;
|
||||
A
|
||||
This is temp. table
|
||||
drop table t1;
|
||||
select * from t1;
|
||||
A
|
||||
This is view again
|
||||
drop view t1;
|
||||
|
|
|
@ -764,3 +764,23 @@ non PS, 1.0 in parameter 1.0
|
|||
PS, 1.0 in parameter 1.0
|
||||
deallocate prepare stmt;
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
strippedproductid char(15) not null default '',
|
||||
zlevelprice decimal(10,2) default null,
|
||||
primary key (strippedproductid)
|
||||
);
|
||||
create table t2 (
|
||||
productid char(15) not null default '',
|
||||
zlevelprice char(21) default null,
|
||||
primary key (productid)
|
||||
);
|
||||
insert into t1 values ('002trans','49.99');
|
||||
insert into t1 values ('003trans','39.98');
|
||||
insert into t1 values ('004trans','31.18');
|
||||
insert INTO t2 SELECT * FROM t1;
|
||||
select * from t2;
|
||||
productid zlevelprice
|
||||
002trans 49.99
|
||||
003trans 39.98
|
||||
004trans 31.18
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -182,3 +182,44 @@ coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4)
|
|||
set session @honk=99;
|
||||
set one_shot @honk=99;
|
||||
ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server
|
||||
set @first_var= NULL;
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`@first_var` longblob
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
set @first_var= cast(NULL as signed integer);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`@first_var` bigint(20) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
set @first_var= NULL;
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`@first_var` bigint(20) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
set @first_var= concat(NULL);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`@first_var` longblob
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
set @first_var=1;
|
||||
set @first_var= cast(NULL as CHAR);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`@first_var` longtext
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
|
|
|
@ -104,3 +104,13 @@ t2.value64=t1.value64;
|
|||
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Test of CREATE ... SELECT and unsigned integers
|
||||
#
|
||||
create table t1 select 1 as 'a';
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
create table t1 select 9223372036854775809 as 'a';
|
||||
show create table t1;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
select CAST(1-2 AS UNSIGNED);
|
||||
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
|
||||
select CONVERT('-1',UNSIGNED);
|
||||
select CAST('10 ' as unsigned integer);
|
||||
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
|
||||
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
|
||||
|
@ -34,6 +33,15 @@ select 10+'a';
|
|||
select 10.0+cast('a' as decimal);
|
||||
select 10E+0+'a';
|
||||
|
||||
# out-of-range cases
|
||||
select cast('18446744073709551616' as unsigned);
|
||||
select cast('18446744073709551616' as signed);
|
||||
select cast('9223372036854775809' as signed);
|
||||
select cast('-1' as unsigned);
|
||||
select cast('abc' as signed);
|
||||
select cast('1a' as signed);
|
||||
select cast('' as signed);
|
||||
|
||||
#
|
||||
# Character set convertion
|
||||
#
|
||||
|
@ -132,6 +140,22 @@ select timediff(cast('2004-12-30 12:00:00' as time), '12:00:00');
|
|||
# Still we should not throw away "days" part of time value
|
||||
select timediff(cast('1 12:00:00' as time), '12:00:00');
|
||||
|
||||
#
|
||||
# Bug #7036: Casting from string to unsigned would cap value of result at
|
||||
# maximum signed value instead of maximum unsigned value
|
||||
#
|
||||
select cast(18446744073709551615 as unsigned);
|
||||
select cast(18446744073709551615 as signed);
|
||||
select cast('18446744073709551615' as unsigned);
|
||||
select cast('18446744073709551615' as signed);
|
||||
select cast('9223372036854775807' as signed);
|
||||
|
||||
select cast(concat('184467440','73709551615') as unsigned);
|
||||
select cast(concat('184467440','73709551615') as signed);
|
||||
|
||||
select cast(repeat('1',20) as unsigned);
|
||||
select cast(repeat('1',20) as signed);
|
||||
|
||||
#decimal-related additions
|
||||
select cast('1.2' as decimal(3,2));
|
||||
select 1e18 * cast('1.2' as decimal(3,2));
|
||||
|
|
|
@ -168,6 +168,6 @@ drop table t1;
|
|||
CREATE TABLE t1 (st varchar(100));
|
||||
INSERT INTO t1 VALUES ("Fake string");
|
||||
CREATE TABLE t2 (geom GEOMETRY NOT NULL, SPATIAL KEY gk(geom));
|
||||
--error 1105
|
||||
--error 1416
|
||||
INSERT INTO t2 SELECT GeomFromText(st) FROM t1;
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -165,9 +165,9 @@ explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimpl
|
|||
|
||||
create table t1 (a geometry not null);
|
||||
insert into t1 values (GeomFromText('Point(1 2)'));
|
||||
-- error 1105
|
||||
-- error 1416
|
||||
insert into t1 values ('Garbage');
|
||||
-- error 1105
|
||||
-- error 1416
|
||||
insert IGNORE into t1 values ('Garbage');
|
||||
alter table t1 add spatial index(a);
|
||||
|
||||
|
@ -359,3 +359,15 @@ select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
|
|||
t1 where object_id=85984;
|
||||
|
||||
drop table t1;
|
||||
|
||||
create table t1 (fl geometry);
|
||||
--error 1416
|
||||
insert into t1 values (1);
|
||||
--error 1416
|
||||
insert into t1 values (1.11);
|
||||
--error 1416
|
||||
insert into t1 values ("qwerty");
|
||||
--error 1416
|
||||
insert into t1 values (pointfromtext('point(1,1)'));
|
||||
|
||||
drop table t1;
|
||||
|
|
|
@ -515,3 +515,10 @@ explain select c from t2 where a = 2 and b = 'val-2' group by c;
|
|||
select c from t2 where a = 2 and b = 'val-2' group by c;
|
||||
drop table t1,t2;
|
||||
|
||||
# Test for BUG#9298 "Wrong handling of int4 unsigned columns in GROUP functions"
|
||||
# (the actual problem was with protocol code, not GROUP BY)
|
||||
create table t1 (b int4 unsigned not null);
|
||||
insert into t1 values(3000000000);
|
||||
select * from t1;
|
||||
select min(b) from t1;
|
||||
drop table t1;
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
# embedded server ignores 'delayed', so skip this
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# Bug #1078
|
||||
#
|
||||
|
|
|
@ -18,6 +18,30 @@ select * from t1;
|
|||
select * from t2;
|
||||
show status like 'handler_discover%';
|
||||
|
||||
# Check dropping and recreating table on same server
|
||||
connect (con1,localhost,,,test);
|
||||
connect (con2,localhost,,,test);
|
||||
connection con1;
|
||||
select * from t1;
|
||||
connection con2;
|
||||
drop table t1;
|
||||
create table t1 (a int) engine=ndbcluster;
|
||||
insert into t1 value (2);
|
||||
connection con1;
|
||||
select * from t1;
|
||||
|
||||
# Check dropping and recreating table on different server
|
||||
connection server2;
|
||||
show status like 'handler_discover%';
|
||||
drop table t1;
|
||||
create table t1 (a int) engine=ndbcluster;
|
||||
insert into t1 value (2);
|
||||
connection server1;
|
||||
# Currently a retry is required remotely
|
||||
--error 1296
|
||||
select * from t1;
|
||||
select * from t1;
|
||||
|
||||
# Connect to server2 and use the tables from there
|
||||
connection server2;
|
||||
flush status;
|
||||
|
|
|
@ -89,3 +89,18 @@ flush status;
|
|||
select * from t1 group by d;
|
||||
show status like "created_tmp%tables";
|
||||
drop table t1;
|
||||
|
||||
# Fix for BUG#8921: Check that temporary table is ingored by view commands.
|
||||
create temporary table t1 as select 'This is temp. table' A;
|
||||
create view t1 as select 'This is view' A;
|
||||
select * from t1;
|
||||
show create table t1;
|
||||
show create view t1;
|
||||
drop view t1;
|
||||
select * from t1;
|
||||
create view t1 as select 'This is view again' A;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
select * from t1;
|
||||
drop view t1;
|
||||
|
||||
|
|
|
@ -343,3 +343,31 @@ execute stmt using @a;
|
|||
select * from t1;
|
||||
deallocate prepare stmt;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# A test case for Bug#5673 "Rounding problem in 4.0.21 inserting decimal
|
||||
# value into a char field": this is a regression bug in 4.0 tree caused by
|
||||
# a fix for some other decimal conversion issue. The patch never was
|
||||
# approved to get into 4.0 (maybe because it was considered too intrusive)
|
||||
#
|
||||
|
||||
create table t1 (
|
||||
strippedproductid char(15) not null default '',
|
||||
zlevelprice decimal(10,2) default null,
|
||||
primary key (strippedproductid)
|
||||
);
|
||||
|
||||
create table t2 (
|
||||
productid char(15) not null default '',
|
||||
zlevelprice char(21) default null,
|
||||
primary key (productid)
|
||||
);
|
||||
|
||||
insert into t1 values ('002trans','49.99');
|
||||
insert into t1 values ('003trans','39.98');
|
||||
insert into t1 values ('004trans','31.18');
|
||||
|
||||
insert INTO t2 SELECT * FROM t1;
|
||||
|
||||
select * from t2;
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -119,3 +119,29 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4);
|
|||
set session @honk=99;
|
||||
--error 1382
|
||||
set one_shot @honk=99;
|
||||
|
||||
#
|
||||
# Bug #6598: problem with cast(NULL as signed integer);
|
||||
#
|
||||
|
||||
set @first_var= NULL;
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
set @first_var= cast(NULL as signed integer);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
set @first_var= NULL;
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
set @first_var= concat(NULL);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
set @first_var=1;
|
||||
set @first_var= cast(NULL as CHAR);
|
||||
create table t1 select @first_var;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
|
135
mysys/default.c
135
mysys/default.c
|
@ -409,6 +409,56 @@ static int search_default_file(Process_option_func opt_handler,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Skip over keyword and get argument after keyword
|
||||
|
||||
SYNOPSIS
|
||||
get_argument()
|
||||
keyword Include directive keyword
|
||||
kwlen Length of keyword
|
||||
ptr Pointer to the keword in the line under process
|
||||
line line number
|
||||
|
||||
RETURN
|
||||
0 error
|
||||
# Returns pointer to the argument after the keyword.
|
||||
*/
|
||||
|
||||
static char *get_argument(const char *keyword, uint kwlen,
|
||||
char *ptr, char *name, uint line)
|
||||
{
|
||||
char *end;
|
||||
|
||||
/* Skip over "include / includedir keyword" and following whitespace */
|
||||
|
||||
for (ptr+= kwlen - 1;
|
||||
my_isspace(&my_charset_latin1, ptr[0]);
|
||||
ptr++)
|
||||
{}
|
||||
|
||||
/*
|
||||
Trim trailing whitespace from directory name
|
||||
The -1 below is for the newline added by fgets()
|
||||
Note that my_isspace() is true for \r and \n
|
||||
*/
|
||||
for (end= ptr + strlen(ptr) - 1;
|
||||
my_isspace(&my_charset_latin1, *(end - 1));
|
||||
end--)
|
||||
{}
|
||||
end[0]= 0; /* Cut off end space */
|
||||
|
||||
/* Print error msg if there is nothing after !include* directive */
|
||||
if (end <= ptr)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"error: Wrong '!%s' directive in config file: %s at line %d\n",
|
||||
keyword, name, line);
|
||||
return 0;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open a configuration file (if exists) and read given options from it
|
||||
|
||||
|
@ -497,40 +547,34 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
|
|||
continue;
|
||||
|
||||
/* Configuration File Directives */
|
||||
if ((*ptr == '!') && (recursion_level < max_recursion_level))
|
||||
if ((*ptr == '!'))
|
||||
{
|
||||
if (recursion_level >= max_recursion_level)
|
||||
{
|
||||
for (end= ptr + strlen(ptr) - 1;
|
||||
my_isspace(&my_charset_latin1, *(end - 1));
|
||||
end--)
|
||||
{}
|
||||
end[0]= 0;
|
||||
fprintf(stderr,
|
||||
"Warning: skipping '%s' directive as maximum include"
|
||||
"recursion level was reached in file %s at line %d\n",
|
||||
ptr, name, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip over `!' and following whitespace */
|
||||
for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
|
||||
{}
|
||||
|
||||
if ((!strncmp(ptr, includedir_keyword, sizeof(includedir_keyword) - 1))
|
||||
&& my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
|
||||
if ((!strncmp(ptr, includedir_keyword,
|
||||
sizeof(includedir_keyword) - 1)) &&
|
||||
my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
|
||||
{
|
||||
/* skip over "includedir" and following whitespace */
|
||||
for (ptr+= sizeof(includedir_keyword) - 1;
|
||||
my_isspace(&my_charset_latin1, ptr[0]); ptr++)
|
||||
{}
|
||||
|
||||
/* trim trailing whitespace from directory name */
|
||||
end= ptr + strlen(ptr) - 1;
|
||||
/* fgets() stores the newline character in the buffer */
|
||||
if ((end[0] == '\n') || (end[0] == '\r') ||
|
||||
my_isspace(&my_charset_latin1, end[0]))
|
||||
{
|
||||
for (; my_isspace(&my_charset_latin1, *(end - 1)); end--)
|
||||
{}
|
||||
end[0]= 0;
|
||||
}
|
||||
|
||||
/* print error msg if there is nothing after !includedir directive */
|
||||
if (end == ptr)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"error: Wrong !includedir directive in config "
|
||||
"file: %s at line %d\n",
|
||||
name,line);
|
||||
goto err;
|
||||
}
|
||||
if (!(ptr= get_argument(includedir_keyword,
|
||||
sizeof(includedir_keyword),
|
||||
ptr, name, line)))
|
||||
goto err;
|
||||
|
||||
if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
|
||||
goto err;
|
||||
|
@ -559,28 +603,13 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
|
|||
|
||||
my_dirend(search_dir);
|
||||
}
|
||||
else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1))
|
||||
&& my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword) - 1]))
|
||||
else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
|
||||
my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
|
||||
{
|
||||
/* skip over `include' and following whitespace */
|
||||
for (ptr+= sizeof(include_keyword) - 1;
|
||||
my_isspace(&my_charset_latin1, ptr[0]); ptr++)
|
||||
{}
|
||||
|
||||
/* trim trailing whitespace from filename */
|
||||
end= ptr + strlen(ptr) - 1;
|
||||
for (; my_isspace(&my_charset_latin1, *(end - 1)) ; end--)
|
||||
{}
|
||||
end[0]= 0;
|
||||
|
||||
if (end == ptr)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"error: Wrong !include directive in config "
|
||||
"file: %s at line %d\n",
|
||||
name,line);
|
||||
goto err;
|
||||
}
|
||||
if (!(ptr= get_argument(include_keyword,
|
||||
sizeof(include_keyword), ptr,
|
||||
name, line)))
|
||||
goto err;
|
||||
|
||||
search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
|
||||
recursion_level + 1);
|
||||
|
@ -588,14 +617,6 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
|
|||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (recursion_level >= max_recursion_level)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"warning: skipping !include directive as maximum include"
|
||||
"recursion level was reached in file %s at line %d\n",
|
||||
name, line);
|
||||
}
|
||||
|
||||
if (*ptr == '[') /* Group name */
|
||||
{
|
||||
|
|
|
@ -1025,8 +1025,8 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
|
|||
for a too long time (this time is determined by parameter age_threshold).
|
||||
*/
|
||||
|
||||
static inline void unreg_request(KEY_CACHE *keycache,
|
||||
BLOCK_LINK *block, int at_end)
|
||||
static void unreg_request(KEY_CACHE *keycache,
|
||||
BLOCK_LINK *block, int at_end)
|
||||
{
|
||||
if (! --block->requests)
|
||||
{
|
||||
|
@ -1045,10 +1045,13 @@ static inline void unreg_request(KEY_CACHE *keycache,
|
|||
}
|
||||
link_block(keycache, block, hot, (my_bool)at_end);
|
||||
block->last_hit_time= keycache->keycache_time;
|
||||
if (++keycache->keycache_time - keycache->used_ins->last_hit_time >
|
||||
keycache->keycache_time++;
|
||||
|
||||
block= keycache->used_ins;
|
||||
/* Check if we should link a hot block to the warm block */
|
||||
if (block && keycache->keycache_time - block->last_hit_time >
|
||||
keycache->age_threshold)
|
||||
{
|
||||
block= keycache->used_ins;
|
||||
unlink_block(keycache, block);
|
||||
link_block(keycache, block, 0, 0);
|
||||
if (block->temperature != BLOCK_WARM)
|
||||
|
|
|
@ -192,3 +192,25 @@ int test_if_hard_path(register const char *dir_name)
|
|||
return FALSE;
|
||||
#endif
|
||||
} /* test_if_hard_path */
|
||||
|
||||
|
||||
/*
|
||||
Test if a name contains an (absolute or relative) path.
|
||||
|
||||
SYNOPSIS
|
||||
has_path()
|
||||
name The name to test.
|
||||
|
||||
RETURN
|
||||
TRUE name contains a path.
|
||||
FALSE name does not contain a path.
|
||||
*/
|
||||
|
||||
my_bool has_path(const char *name)
|
||||
{
|
||||
return test(strchr(name, FN_LIBCHAR))
|
||||
#ifdef FN_DEVCHAR
|
||||
|| test(strchr(name, FN_DEVCHAR))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
|
@ -76,8 +76,11 @@ public:
|
|||
Changed, ///< The object has been modified in memory
|
||||
///< and has to be commited in NDB Kernel for
|
||||
///< changes to take effect
|
||||
Retrieved ///< The object exist and has been read
|
||||
Retrieved, ///< The object exist and has been read
|
||||
///< into main memory from NDB Kernel
|
||||
Invalid ///< The object has been invalidated
|
||||
///< and should not be used
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1528,6 +1528,7 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
|
|||
// If in local cache it must be in global
|
||||
if (!cachedImpl)
|
||||
abort();
|
||||
cachedImpl->m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(cachedImpl);
|
||||
m_globalHash->unlock();
|
||||
}
|
||||
|
@ -1832,8 +1833,8 @@ NdbDictionaryImpl::dropTable(const char * name)
|
|||
|
||||
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
|
||||
m_localHash.drop(internalTableName);
|
||||
|
||||
m_globalHash->lock();
|
||||
tab->m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(tab);
|
||||
m_globalHash->unlock();
|
||||
DBUG_RETURN(dropTable(name));
|
||||
|
@ -1877,10 +1878,11 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
|
|||
int ret = m_receiver.dropTable(impl);
|
||||
if(ret == 0 || m_error.code == 709){
|
||||
const char * internalTableName = impl.m_internalName.c_str();
|
||||
|
||||
|
||||
m_localHash.drop(internalTableName);
|
||||
|
||||
m_globalHash->lock();
|
||||
impl.m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(&impl);
|
||||
m_globalHash->unlock();
|
||||
|
||||
|
@ -1978,6 +1980,7 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
|
|||
|
||||
m_localHash.drop(internalTableName);
|
||||
m_globalHash->lock();
|
||||
impl.m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(&impl);
|
||||
m_globalHash->unlock();
|
||||
return 0;
|
||||
|
@ -2244,8 +2247,8 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
|
|||
m_ndb.internalizeTableName(indexName); // Index is also a table
|
||||
|
||||
m_localHash.drop(internalIndexName);
|
||||
|
||||
m_globalHash->lock();
|
||||
idx->m_table->m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(idx->m_table);
|
||||
m_globalHash->unlock();
|
||||
return dropIndex(indexName, tableName);
|
||||
|
@ -2279,8 +2282,8 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
|
|||
int ret = m_receiver.dropIndex(impl, *timpl);
|
||||
if(ret == 0){
|
||||
m_localHash.drop(internalIndexName);
|
||||
|
||||
m_globalHash->lock();
|
||||
impl.m_table->m_status = NdbDictionary::Object::Invalid;
|
||||
m_globalHash->drop(impl.m_table);
|
||||
m_globalHash->unlock();
|
||||
}
|
||||
|
|
|
@ -447,35 +447,6 @@ const char **ha_archive::bas_ext() const
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Rename all files that this handler defines in bas_ext list
|
||||
|
||||
NOTE Don't care if the .arn file is missing
|
||||
*/
|
||||
int ha_archive::rename_table(const char * from, const char * to)
|
||||
{
|
||||
DBUG_ENTER("ha_archive::rename_table");
|
||||
DBUG_PRINT("enter", ("from: %s, to: %s", from, to));
|
||||
for (const char **ext=bas_ext(); *ext ; ext++)
|
||||
{
|
||||
// Check if the .arn file exists before rename
|
||||
if (!my_strcasecmp(system_charset_info, *ext, ARN))
|
||||
{
|
||||
char name[FN_REFLEN];
|
||||
(void)strxnmov(name, FN_REFLEN, from, ARN, NullS);
|
||||
if (access(name, F_OK))
|
||||
{
|
||||
DBUG_PRINT("info", ("%s does not exist on disk, skipping it", name));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (rename_file_ext(from,to,*ext))
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
When opening a file we:
|
||||
Create/get our shared structure.
|
||||
|
|
|
@ -104,7 +104,6 @@ public:
|
|||
int end_bulk_insert();
|
||||
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
||||
enum thr_lock_type lock_type);
|
||||
int rename_table(const char * from, const char * to);
|
||||
};
|
||||
|
||||
handlerton *archive_db_init(void);
|
||||
|
|
30
sql/field.cc
30
sql/field.cc
|
@ -7267,12 +7267,38 @@ void Field_geom::sql_type(String &res) const
|
|||
}
|
||||
|
||||
|
||||
int Field_geom::store(double nr)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(longlong nr)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store_decimal(const my_decimal *)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
|
||||
{
|
||||
if (!length)
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
else
|
||||
{
|
||||
if (from == Geometry::bad_geometry_data.ptr())
|
||||
goto err;
|
||||
// Check given WKB
|
||||
uint32 wkb_type;
|
||||
if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
|
||||
|
@ -7280,7 +7306,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
|
|||
wkb_type= uint4korr(from + WKB_HEADER_SIZE);
|
||||
if (wkb_type < (uint32) Geometry::wkb_point ||
|
||||
wkb_type > (uint32) Geometry::wkb_end)
|
||||
return -1;
|
||||
goto err;
|
||||
Field_blob::store_length(length);
|
||||
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
|
||||
{ // Must make a copy
|
||||
|
@ -7293,6 +7319,8 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
|
|||
|
||||
err:
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER(ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
String *val_int_as_str(String *val_buffer, my_bool unsigned_flag);
|
||||
virtual Item_result result_type () const=0;
|
||||
virtual Item_result cmp_type () const { return result_type(); }
|
||||
virtual Item_result cast_to_int_type () const { return result_type(); }
|
||||
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
|
||||
static Item_result result_merge_type(enum_field_types);
|
||||
bool eq(Field *field)
|
||||
|
@ -1189,9 +1190,9 @@ public:
|
|||
enum_field_types type() const { return FIELD_TYPE_GEOMETRY; }
|
||||
void sql_type(String &str) const;
|
||||
int store(const char *to, uint length, CHARSET_INFO *charset);
|
||||
int store(double nr) { return 1; }
|
||||
int store(longlong nr) { return 1; }
|
||||
int store_decimal(const my_decimal *) { return 1; }
|
||||
int store(double nr);
|
||||
int store(longlong nr);
|
||||
int store_decimal(const my_decimal *);
|
||||
void get_key_image(char *buff,uint length,imagetype type);
|
||||
};
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
@ -1216,6 +1217,7 @@ public:
|
|||
}
|
||||
enum_field_types type() const { return FIELD_TYPE_STRING; }
|
||||
enum Item_result cmp_type () const { return INT_RESULT; }
|
||||
enum Item_result cast_to_int_type () const { return INT_RESULT; }
|
||||
enum ha_base_keytype key_type() const;
|
||||
int store(const char *to,uint length,CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "ha_blackhole.h"
|
||||
|
||||
|
||||
static const char *ha_black_hole_exts[] = {
|
||||
static const char *ha_blackhole_exts[] = {
|
||||
NullS
|
||||
};
|
||||
|
||||
|
|
|
@ -1632,7 +1632,7 @@ innobase_report_binlog_offset_and_commit(
|
|||
#endif /* HAVE_REPLICATION */
|
||||
trx->flush_log_later = TRUE;
|
||||
|
||||
innobase_commit(thd, trx_handle);
|
||||
innobase_commit(thd, TRUE);
|
||||
|
||||
trx->flush_log_later = FALSE;
|
||||
|
||||
|
|
|
@ -400,6 +400,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
|
|||
const char **table_names, **pos;
|
||||
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
|
||||
THD *thd= current_thd;
|
||||
uint dirlgt= dirname_length(name);
|
||||
DBUG_ENTER("ha_myisammrg::create");
|
||||
|
||||
if (!(table_names= (const char**)
|
||||
|
@ -413,11 +414,30 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
|
|||
tbl= find_temporary_table(thd, tables->db, tables->table_name);
|
||||
if (!tbl)
|
||||
{
|
||||
uint length= my_snprintf(buff,FN_REFLEN,"%s%s/%s",
|
||||
mysql_real_data_home,
|
||||
/*
|
||||
Construct the path to the MyISAM table. Try to meet two conditions:
|
||||
1.) Allow to include MyISAM tables from different databases, and
|
||||
2.) allow for moving DATADIR around in the file system.
|
||||
The first means that we need paths in the .MRG file. The second
|
||||
means that we should not have absolute paths in the .MRG file.
|
||||
The best, we can do, is to use 'mysql_data_home', which is '.'
|
||||
in mysqld and may be an absolute path in an embedded server.
|
||||
This means that it might not be possible to move the DATADIR of
|
||||
an embedded server without changing the paths in the .MRG file.
|
||||
*/
|
||||
uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home,
|
||||
tables->db, tables->table_name);
|
||||
if (!(table_name= thd->strmake(buff, length)))
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
/*
|
||||
If a MyISAM table is in the same directory as the MERGE table,
|
||||
we use the table name without a path. This means that the
|
||||
DATADIR can easily be moved even for an embedded server as long
|
||||
as the MyISAM tables are from the same database as the MERGE table.
|
||||
*/
|
||||
if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
|
||||
table_name= tables->table_name;
|
||||
else
|
||||
if (! (table_name= thd->strmake(buff, length)))
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
}
|
||||
else
|
||||
table_name= (*tbl)->s->path;
|
||||
|
|
|
@ -418,11 +418,28 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
|
|||
# The mapped error code
|
||||
*/
|
||||
|
||||
void ha_ndbcluster::invalidateDictionaryCache()
|
||||
void ha_ndbcluster::invalidate_dictionary_cache(bool global)
|
||||
{
|
||||
NDBDICT *dict= get_ndb()->getDictionary();
|
||||
DBUG_ENTER("invalidate_dictionary_cache");
|
||||
DBUG_PRINT("info", ("invalidating %s", m_tabname));
|
||||
dict->invalidateTable(m_tabname);
|
||||
|
||||
if (global)
|
||||
{
|
||||
const NDBTAB *tab= dict->getTable(m_tabname);
|
||||
if (!tab)
|
||||
DBUG_VOID_RETURN;
|
||||
if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
|
||||
{
|
||||
// Global cache has already been invalidated
|
||||
dict->removeCachedTable(m_tabname);
|
||||
global= FALSE;
|
||||
}
|
||||
else
|
||||
dict->invalidateTable(m_tabname);
|
||||
}
|
||||
else
|
||||
dict->removeCachedTable(m_tabname);
|
||||
table->s->version=0L; /* Free when thread is ready */
|
||||
/* Invalidate indexes */
|
||||
for (uint i= 0; i < table->s->keys; i++)
|
||||
|
@ -434,18 +451,28 @@ void ha_ndbcluster::invalidateDictionaryCache()
|
|||
switch(idx_type) {
|
||||
case(PRIMARY_KEY_ORDERED_INDEX):
|
||||
case(ORDERED_INDEX):
|
||||
dict->invalidateIndex(index->getName(), m_tabname);
|
||||
if (global)
|
||||
dict->invalidateIndex(index->getName(), m_tabname);
|
||||
else
|
||||
dict->removeCachedIndex(index->getName(), m_tabname);
|
||||
break;
|
||||
case(UNIQUE_ORDERED_INDEX):
|
||||
dict->invalidateIndex(index->getName(), m_tabname);
|
||||
if (global)
|
||||
dict->invalidateIndex(index->getName(), m_tabname);
|
||||
else
|
||||
dict->removeCachedIndex(index->getName(), m_tabname);
|
||||
case(UNIQUE_INDEX):
|
||||
dict->invalidateIndex(unique_index->getName(), m_tabname);
|
||||
if (global)
|
||||
dict->invalidateIndex(unique_index->getName(), m_tabname);
|
||||
else
|
||||
dict->removeCachedIndex(unique_index->getName(), m_tabname);
|
||||
break;
|
||||
case(PRIMARY_KEY_INDEX):
|
||||
case(UNDEFINED_INDEX):
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
int ha_ndbcluster::ndb_err(NdbTransaction *trans)
|
||||
|
@ -457,7 +484,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
|
|||
ERR_PRINT(err);
|
||||
switch (err.classification) {
|
||||
case NdbError::SchemaError:
|
||||
invalidateDictionaryCache();
|
||||
invalidate_dictionary_cache(TRUE);
|
||||
|
||||
if (err.code==284)
|
||||
{
|
||||
|
@ -882,7 +909,14 @@ int ha_ndbcluster::get_metadata(const char *path)
|
|||
|
||||
if (!(tab= dict->getTable(m_tabname)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
|
||||
// Check if thread has stale local cache
|
||||
if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
|
||||
{
|
||||
invalidate_dictionary_cache(FALSE);
|
||||
if (!(tab= dict->getTable(m_tabname)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
|
||||
}
|
||||
/*
|
||||
Compare FrmData in NDB with frm file from disk.
|
||||
*/
|
||||
|
@ -901,7 +935,7 @@ int ha_ndbcluster::get_metadata(const char *path)
|
|||
if (!invalidating_ndb_table)
|
||||
{
|
||||
DBUG_PRINT("info", ("Invalidating table"));
|
||||
invalidateDictionaryCache();
|
||||
invalidate_dictionary_cache(TRUE);
|
||||
invalidating_ndb_table= TRUE;
|
||||
}
|
||||
else
|
||||
|
@ -927,7 +961,7 @@ int ha_ndbcluster::get_metadata(const char *path)
|
|||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
|
||||
m_tableVersion= tab->getObjectVersion();
|
||||
m_table_version= tab->getObjectVersion();
|
||||
m_table= (void *)tab;
|
||||
m_table_info= NULL; // Set in external lock
|
||||
|
||||
|
@ -3269,15 +3303,25 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
|
|||
void *tab_info;
|
||||
if (!(tab= dict->getTable(m_tabname, &tab_info)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
|
||||
if (m_table != (void *)tab || m_tableVersion != tab->getObjectVersion())
|
||||
DBUG_PRINT("info", ("Table schema version: %d",
|
||||
tab->getObjectVersion()));
|
||||
// Check if thread has stale local cache
|
||||
if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
|
||||
{
|
||||
invalidate_dictionary_cache(FALSE);
|
||||
if (!(tab= dict->getTable(m_tabname, &tab_info)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
DBUG_PRINT("info", ("Table schema version: %d",
|
||||
tab->getObjectVersion()));
|
||||
}
|
||||
if (m_table != (void *)tab || m_table_version < tab->getObjectVersion())
|
||||
{
|
||||
/*
|
||||
The table has been altered, refresh the index list
|
||||
*/
|
||||
build_index_list(ndb, table, ILBP_OPEN);
|
||||
m_table= (void *)tab;
|
||||
m_tableVersion = tab->getObjectVersion();
|
||||
m_table_version = tab->getObjectVersion();
|
||||
}
|
||||
m_table_info= tab_info;
|
||||
}
|
||||
|
@ -3321,7 +3365,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
|
|||
thd_ndb->stmt= NULL;
|
||||
}
|
||||
}
|
||||
m_table= NULL;
|
||||
m_table_info= NULL;
|
||||
|
||||
/*
|
||||
|
@ -4036,7 +4079,13 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
|||
dict= ndb->getDictionary();
|
||||
if (!(orig_tab= dict->getTable(m_tabname)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
|
||||
// Check if thread has stale local cache
|
||||
if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
|
||||
{
|
||||
dict->removeCachedTable(m_tabname);
|
||||
if (!(orig_tab= dict->getTable(m_tabname)))
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
}
|
||||
m_table= (void *)orig_tab;
|
||||
// Change current database to that of target table
|
||||
set_dbname(to);
|
||||
|
@ -4159,7 +4208,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
|
|||
m_active_trans(NULL),
|
||||
m_active_cursor(NULL),
|
||||
m_table(NULL),
|
||||
m_tableVersion(-1),
|
||||
m_table_version(-1),
|
||||
m_table_info(NULL),
|
||||
m_table_flags(HA_REC_NOT_IN_SEQ |
|
||||
HA_NULL_IN_KEY |
|
||||
|
@ -4409,7 +4458,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
|
|||
DBUG_RETURN(1);
|
||||
ERR_RETURN(err);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("Found table %s", tab->getName()));
|
||||
|
||||
len= tab->getFrmLength();
|
||||
|
|
|
@ -558,7 +558,7 @@ private:
|
|||
void print_results();
|
||||
|
||||
ulonglong get_auto_increment();
|
||||
void invalidateDictionaryCache();
|
||||
void invalidate_dictionary_cache(bool global);
|
||||
int ndb_err(NdbTransaction*);
|
||||
bool uses_blob_value(bool all_fields);
|
||||
|
||||
|
@ -596,7 +596,7 @@ private:
|
|||
NdbTransaction *m_active_trans;
|
||||
NdbScanOperation *m_active_cursor;
|
||||
void *m_table;
|
||||
int m_tableVersion;
|
||||
int m_table_version;
|
||||
void *m_table_info;
|
||||
char m_dbname[FN_HEADLEN];
|
||||
//char m_schemaname[FN_HEADLEN];
|
||||
|
|
|
@ -185,9 +185,10 @@ enum db_type ha_checktype(enum db_type database_type)
|
|||
thd= current_thd;
|
||||
return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
|
||||
(enum db_type) thd->variables.table_type :
|
||||
(enum db_type) global_system_variables.table_type !=
|
||||
DB_TYPE_UNKNOWN ?
|
||||
(enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM);
|
||||
((enum db_type) global_system_variables.table_type !=
|
||||
DB_TYPE_UNKNOWN ?
|
||||
(enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
|
||||
);
|
||||
} /* ha_checktype */
|
||||
|
||||
|
||||
|
@ -1772,13 +1773,17 @@ int handler::delete_table(const char *name)
|
|||
|
||||
int handler::rename_table(const char * from, const char * to)
|
||||
{
|
||||
DBUG_ENTER("handler::rename_table");
|
||||
for (const char **ext=bas_ext(); *ext ; ext++)
|
||||
int error= 0;
|
||||
for (const char **ext= bas_ext(); *ext ; ext++)
|
||||
{
|
||||
if (rename_file_ext(from,to,*ext))
|
||||
DBUG_RETURN(my_errno);
|
||||
if (rename_file_ext(from, to, *ext))
|
||||
{
|
||||
if ((error=my_errno) != ENOENT)
|
||||
break;
|
||||
error= 0;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -177,7 +177,14 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors)
|
|||
&tmp_errno)))
|
||||
{
|
||||
DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno));
|
||||
add_wrong_ip(in);
|
||||
/*
|
||||
Don't cache responses when the DSN server is down, as otherwise
|
||||
transient DNS failure may leave any number of clients (those
|
||||
that attempted to connect during the outage) unable to connect
|
||||
indefinitely.
|
||||
*/
|
||||
if (tmp_errno == HOST_NOT_FOUND || tmp_error == NO_DATA)
|
||||
add_wrong_ip(in);
|
||||
my_gethostbyname_r_free();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
|
@ -302,7 +302,8 @@ public:
|
|||
{ return save_in_field(field, 1); }
|
||||
virtual bool send(Protocol *protocol, String *str);
|
||||
virtual bool eq(const Item *, bool binary_cmp) const;
|
||||
virtual Item_result result_type () const { return REAL_RESULT; }
|
||||
virtual Item_result result_type() const { return REAL_RESULT; }
|
||||
virtual Item_result cast_to_int_type() const { return result_type(); }
|
||||
virtual enum_field_types field_type() const;
|
||||
virtual enum Type type() const =0;
|
||||
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
|
||||
|
@ -738,6 +739,10 @@ public:
|
|||
{
|
||||
return field->result_type();
|
||||
}
|
||||
Item_result cast_to_int_type() const
|
||||
{
|
||||
return field->cast_to_int_type();
|
||||
}
|
||||
enum_field_types field_type() const
|
||||
{
|
||||
return field->type();
|
||||
|
|
|
@ -904,6 +904,58 @@ void Item_func_signed::print(String *str)
|
|||
}
|
||||
|
||||
|
||||
longlong Item_func_signed::val_int_from_str(int *error)
|
||||
{
|
||||
char buff[MAX_FIELD_WIDTH], *end;
|
||||
String tmp(buff,sizeof(buff), &my_charset_bin), *res;
|
||||
longlong value;
|
||||
|
||||
/*
|
||||
For a string result, we must first get the string and then convert it
|
||||
to a longlong
|
||||
*/
|
||||
|
||||
if (!(res= args[0]->val_str(&tmp)))
|
||||
{
|
||||
null_value= 1;
|
||||
*error= 0;
|
||||
return 0;
|
||||
}
|
||||
null_value= 0;
|
||||
end= (char*) res->ptr()+ res->length();
|
||||
value= my_strtoll10(res->ptr(), &end, error);
|
||||
if (*error > 0 || end != res->ptr()+ res->length())
|
||||
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_TRUNCATED_WRONG_VALUE,
|
||||
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
|
||||
res->c_ptr());
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_signed::val_int()
|
||||
{
|
||||
longlong value;
|
||||
int error;
|
||||
|
||||
if (args[0]->cast_to_int_type() != STRING_RESULT)
|
||||
{
|
||||
value= args[0]->val_int();
|
||||
null_value= args[0]->null_value;
|
||||
return value;
|
||||
}
|
||||
|
||||
value= val_int_from_str(&error);
|
||||
if (value < 0 && error == 0)
|
||||
{
|
||||
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
|
||||
"Cast to signed converted positive out-of-range integer to "
|
||||
"it's negative complement");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void Item_func_unsigned::print(String *str)
|
||||
{
|
||||
str->append("cast(", 5);
|
||||
|
@ -913,6 +965,27 @@ void Item_func_unsigned::print(String *str)
|
|||
}
|
||||
|
||||
|
||||
longlong Item_func_unsigned::val_int()
|
||||
{
|
||||
longlong value;
|
||||
int error;
|
||||
|
||||
if (args[0]->cast_to_int_type() != STRING_RESULT)
|
||||
{
|
||||
value= args[0]->val_int();
|
||||
null_value= args[0]->null_value;
|
||||
return value;
|
||||
}
|
||||
|
||||
value= val_int_from_str(&error);
|
||||
if (error < 0)
|
||||
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
|
||||
"Cast to unsigned converted negative integer to it's "
|
||||
"positive complement");
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
String *Item_decimal_typecast::val_str(String *str)
|
||||
{
|
||||
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
|
||||
|
@ -3271,7 +3344,8 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
|||
from the argument if the argument is NULL
|
||||
and the variable has previously been initialized.
|
||||
*/
|
||||
if (!entry->collation.collation || !args[0]->null_value)
|
||||
null_item= (args[0]->type() == NULL_ITEM);
|
||||
if (!entry->collation.collation || !null_item)
|
||||
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
|
||||
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
|
||||
cached_result_type= args[0]->result_type();
|
||||
|
@ -3315,8 +3389,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
|
|||
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
||||
if (entry->value && entry->value != pos)
|
||||
my_free(entry->value,MYF(0));
|
||||
entry->value=0;
|
||||
entry->length=0;
|
||||
entry->value= 0;
|
||||
entry->length= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3355,9 +3429,9 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
|
|||
if (type == DECIMAL_RESULT)
|
||||
((my_decimal*)entry->value)->fix_buffer_pointer();
|
||||
entry->length= length;
|
||||
entry->type=type;
|
||||
entry->collation.set(cs, dv);
|
||||
}
|
||||
entry->type=type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3366,6 +3440,12 @@ bool
|
|||
Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
|
||||
CHARSET_INFO *cs, Derivation dv)
|
||||
{
|
||||
/*
|
||||
If we set a variable explicitely to NULL then keep the old
|
||||
result type of the variable
|
||||
*/
|
||||
if ((null_value= args[0]->null_value) && null_item)
|
||||
type= entry->type; // Don't change type of item
|
||||
if (::update_hash(entry, (null_value= args[0]->null_value),
|
||||
ptr, length, type, cs, dv))
|
||||
{
|
||||
|
|
|
@ -262,12 +262,8 @@ public:
|
|||
null_value= args[0]->null_value;
|
||||
return tmp;
|
||||
}
|
||||
longlong val_int()
|
||||
{
|
||||
longlong tmp= args[0]->val_int();
|
||||
null_value= args[0]->null_value;
|
||||
return tmp;
|
||||
}
|
||||
longlong val_int();
|
||||
longlong val_int_from_str(int *error);
|
||||
void fix_length_and_dec()
|
||||
{ max_length=args[0]->max_length; unsigned_flag=0; }
|
||||
void print(String *str);
|
||||
|
@ -281,6 +277,7 @@ public:
|
|||
const char *func_name() const { return "cast_as_unsigned"; }
|
||||
void fix_length_and_dec()
|
||||
{ max_length=args[0]->max_length; unsigned_flag=1; }
|
||||
longlong val_int();
|
||||
void print(String *str);
|
||||
};
|
||||
|
||||
|
@ -1071,6 +1068,7 @@ class Item_func_set_user_var :public Item_func
|
|||
char buffer[MAX_FIELD_WIDTH];
|
||||
String value;
|
||||
my_decimal decimal_buff;
|
||||
bool null_item;
|
||||
union
|
||||
{
|
||||
longlong vint;
|
||||
|
|
|
@ -55,8 +55,11 @@ String *Item_func_geometry_from_text::val_str(String *str)
|
|||
return 0;
|
||||
str->length(0);
|
||||
str->q_append(srid);
|
||||
if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
|
||||
return 0;
|
||||
if (!Geometry::create_from_wkt(&buffer, &trs, str, 0))
|
||||
/* We shouldn't return NULL here as NULL is a legal spatial object */
|
||||
/* Geometry::bad_spatial_data will produce error message beeing stored*/
|
||||
/* in GEOMETRY field */
|
||||
return &Geometry::bad_geometry_data;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
51
sql/lock.cc
51
sql/lock.cc
|
@ -82,7 +82,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count);
|
|||
static void print_lock_error(int error, const char *);
|
||||
|
||||
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
|
||||
bool ignore_global_read_lock)
|
||||
{
|
||||
MYSQL_LOCK *sql_lock;
|
||||
TABLE *write_lock_used;
|
||||
|
@ -93,7 +94,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
|
|||
if (!(sql_lock = get_lock_data(thd,tables,count, 0,&write_lock_used)))
|
||||
break;
|
||||
|
||||
if (global_read_lock && write_lock_used)
|
||||
if (global_read_lock && write_lock_used && ! ignore_global_read_lock)
|
||||
{
|
||||
/*
|
||||
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
|
||||
|
@ -949,3 +950,49 @@ bool make_global_read_lock_block_commit(THD *thd)
|
|||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set protection against global read lock.
|
||||
|
||||
SYNOPSIS
|
||||
set_protect_against_global_read_lock()
|
||||
void
|
||||
|
||||
RETURN
|
||||
FALSE OK, no global read lock exists.
|
||||
TRUE Error, global read lock exists already.
|
||||
*/
|
||||
|
||||
bool set_protect_against_global_read_lock(void)
|
||||
{
|
||||
bool global_read_lock_exists;
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
if (! (global_read_lock_exists= test(global_read_lock)))
|
||||
protect_against_global_read_lock++;
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
return global_read_lock_exists;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Unset protection against global read lock.
|
||||
|
||||
SYNOPSIS
|
||||
unset_protect_against_global_read_lock()
|
||||
void
|
||||
|
||||
RETURN
|
||||
void
|
||||
*/
|
||||
|
||||
void unset_protect_against_global_read_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
protect_against_global_read_lock--;
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
pthread_cond_broadcast(&COND_refresh);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1151,7 +1151,8 @@ extern pthread_t signal_thread;
|
|||
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **table,uint count);
|
||||
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
|
||||
bool ignore_global_read_lock= FALSE);
|
||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
|
||||
|
@ -1165,6 +1166,8 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
|
|||
bool is_not_commit);
|
||||
void start_waiting_global_read_lock(THD *thd);
|
||||
bool make_global_read_lock_block_commit(THD *thd);
|
||||
bool set_protect_against_global_read_lock(void);
|
||||
void unset_protect_against_global_read_lock(void);
|
||||
|
||||
/* Lock based on name */
|
||||
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
|
||||
|
|
|
@ -820,7 +820,7 @@ bool Protocol_simple::store_long(longlong from)
|
|||
#endif
|
||||
char buff[20];
|
||||
return net_store_data((char*) buff,
|
||||
(uint) (int10_to_str((int) from,buff, -10)-buff));
|
||||
(uint) (int10_to_str((long int)from,buff, (from <0)?-10:10)-buff));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5344,3 +5344,5 @@ ER_SP_NOT_VAR_ARG 42000
|
|||
eng "OUT or INOUT argument %d for routine %s is not a variable"
|
||||
ER_SP_NO_RETSET_IN_FUNC 0A000
|
||||
eng "Not allowed to return a result set from a function"
|
||||
ER_CANT_CREATE_GEOMETRY_OBJECT 22003
|
||||
eng "Cannot get geometry object from data you send to the GEOMETRY field"
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
/***************************** Gis_class_info *******************************/
|
||||
|
||||
String Geometry::bad_geometry_data("Bad object", &my_charset_bin);
|
||||
|
||||
Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_end+1]=
|
||||
{
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
|
|
|
@ -173,6 +173,8 @@ public:
|
|||
static void operator delete(void *ptr, void *buffer)
|
||||
{}
|
||||
|
||||
static String bad_geometry_data;
|
||||
|
||||
enum wkbType
|
||||
{
|
||||
wkb_point= 1,
|
||||
|
|
|
@ -3858,11 +3858,8 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
|
|||
TABLE *table= field->table;
|
||||
if (field == table->next_number_field)
|
||||
table->auto_increment_field_not_null= TRUE;
|
||||
if ((value->save_in_field(field, 0) < 0) && !ignore_errors)
|
||||
{
|
||||
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
|
||||
if (value->save_in_field(field, 0) == -1)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(thd->net.report_error);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||
}
|
||||
if (values.elements != table->s->fields)
|
||||
{
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
|
||||
return -1;
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
@ -112,7 +112,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||
int res;
|
||||
if (fields.elements != values.elements)
|
||||
{
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
|
||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1117,27 +1117,42 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||
{
|
||||
int error;
|
||||
delayed_insert *tmp;
|
||||
TABLE *table;
|
||||
DBUG_ENTER("delayed_get_table");
|
||||
|
||||
if (!table_list->db)
|
||||
table_list->db=thd->db;
|
||||
|
||||
/* no match; create a new thread to handle the table */
|
||||
/* Find the thread which handles this table. */
|
||||
if (!(tmp=find_handler(thd,table_list)))
|
||||
{
|
||||
/* Don't create more than max_insert_delayed_threads */
|
||||
/*
|
||||
No match. Create a new thread to handle the table, but
|
||||
no more than max_insert_delayed_threads.
|
||||
*/
|
||||
if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
|
||||
DBUG_RETURN(0);
|
||||
thd->proc_info="Creating delayed handler";
|
||||
pthread_mutex_lock(&LOCK_delayed_create);
|
||||
if (!(tmp=find_handler(thd,table_list))) // Was just created
|
||||
/*
|
||||
The first search above was done without LOCK_delayed_create.
|
||||
Another thread might have created the handler in between. Search again.
|
||||
*/
|
||||
if (! (tmp= find_handler(thd, table_list)))
|
||||
{
|
||||
/*
|
||||
Avoid that a global read lock steps in while we are creating the
|
||||
new thread. It would block trying to open the table. Hence, the
|
||||
DI thread and this thread would wait until after the global
|
||||
readlock is gone. If the read lock exists already, we leave with
|
||||
no table and then switch to non-delayed insert.
|
||||
*/
|
||||
if (set_protect_against_global_read_lock())
|
||||
goto err;
|
||||
if (!(tmp=new delayed_insert()))
|
||||
{
|
||||
thd->fatal_error();
|
||||
my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert));
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
DBUG_RETURN(0);
|
||||
goto err1;
|
||||
}
|
||||
pthread_mutex_lock(&LOCK_thread_count);
|
||||
thread_count++;
|
||||
|
@ -1146,10 +1161,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||
!(tmp->thd.query=my_strdup(table_list->table_name,MYF(MY_WME))))
|
||||
{
|
||||
delete tmp;
|
||||
thd->fatal_error();
|
||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
DBUG_RETURN(0);
|
||||
goto err1;
|
||||
}
|
||||
tmp->table_list= *table_list; // Needed to open table
|
||||
tmp->table_list.db= tmp->thd.db;
|
||||
|
@ -1165,10 +1178,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||
pthread_mutex_unlock(&tmp->mutex);
|
||||
tmp->unlock();
|
||||
delete tmp;
|
||||
thd->fatal_error();
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
|
||||
DBUG_RETURN(0);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* Wait until table is open */
|
||||
|
@ -1178,6 +1189,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||
pthread_cond_wait(&tmp->cond_client,&tmp->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&tmp->mutex);
|
||||
unset_protect_against_global_read_lock();
|
||||
thd->proc_info="got old table";
|
||||
if (tmp->thd.killed)
|
||||
{
|
||||
|
@ -1189,28 +1201,34 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||
thd->net.last_errno=tmp->thd.net.last_errno;
|
||||
}
|
||||
tmp->unlock();
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
DBUG_RETURN(0); // Continue with normal insert
|
||||
goto err;
|
||||
}
|
||||
if (thd->killed)
|
||||
{
|
||||
tmp->unlock();
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
DBUG_RETURN(0);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&tmp->mutex);
|
||||
TABLE *table=tmp->get_local_table(thd);
|
||||
table= tmp->get_local_table(thd);
|
||||
pthread_mutex_unlock(&tmp->mutex);
|
||||
tmp->unlock();
|
||||
if (table)
|
||||
thd->di=tmp;
|
||||
else if (tmp->thd.is_fatal_error)
|
||||
thd->fatal_error();
|
||||
/* Unlock the delayed insert object after its last access. */
|
||||
tmp->unlock();
|
||||
DBUG_RETURN((table_list->table=table));
|
||||
|
||||
err1:
|
||||
thd->fatal_error();
|
||||
unset_protect_against_global_read_lock();
|
||||
err:
|
||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||
DBUG_RETURN(0); // Continue with normal insert
|
||||
}
|
||||
|
||||
|
||||
|
@ -1433,6 +1451,14 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
|
|||
thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED;
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
|
||||
/*
|
||||
Wait until the client runs into pthread_cond_wait(),
|
||||
where we free it after the table is opened and di linked in the list.
|
||||
If we did not wait here, the client might detect the opened table
|
||||
before it is linked to the list. It would release LOCK_delayed_create
|
||||
and allow another thread to create another handler for the same table,
|
||||
since it does not find one in the list.
|
||||
*/
|
||||
pthread_mutex_lock(&di->mutex);
|
||||
#if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */
|
||||
if (my_thread_init())
|
||||
|
@ -1547,8 +1573,17 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
|
|||
|
||||
if (di->tables_in_use && ! thd->lock)
|
||||
{
|
||||
/* request for new delayed insert */
|
||||
if (!(thd->lock=mysql_lock_tables(thd,&di->table,1)))
|
||||
/*
|
||||
Request for new delayed insert.
|
||||
Lock the table, but avoid to be blocked by a global read lock.
|
||||
If we got here while a global read lock exists, then one or more
|
||||
inserts started before the lock was requested. These are allowed
|
||||
to complete their work before the server returns control to the
|
||||
client which requested the global read lock. The delayed insert
|
||||
handler will close the table and finish when the outstanding
|
||||
inserts are done.
|
||||
*/
|
||||
if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, TRUE)))
|
||||
{
|
||||
/* Fatal error */
|
||||
di->dead= 1;
|
||||
|
|
|
@ -3010,6 +3010,10 @@ unsent_create_error:
|
|||
goto error;
|
||||
#else
|
||||
{
|
||||
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
|
||||
if (lex->only_view)
|
||||
first_table->skip_temporary= 1;
|
||||
|
||||
if (check_db_used(thd, all_tables) ||
|
||||
check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
|
||||
&first_table->grant.privilege, 0, 0))
|
||||
|
|
|
@ -2223,7 +2223,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
|
|||
my_pthread_setprio(pthread_self(), QUERY_PRIOR);
|
||||
|
||||
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
||||
(void) stmt->cursor->fetch(num_rows);
|
||||
stmt->cursor->fetch(num_rows);
|
||||
thd->protocol= &thd->protocol_simple; // Use normal protocol
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -91,7 +91,15 @@ enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
|
|||
|
||||
class JOIN;
|
||||
|
||||
typedef int (*Next_select_func)(JOIN *,struct st_join_table *,bool);
|
||||
enum enum_nested_loop_state
|
||||
{
|
||||
NESTED_LOOP_KILLED= -2, NESTED_LOOP_ERROR= -1,
|
||||
NESTED_LOOP_OK= 0, NESTED_LOOP_NO_MORE_ROWS= 1,
|
||||
NESTED_LOOP_QUERY_LIMIT= 3, NESTED_LOOP_CURSOR_LIMIT= 4
|
||||
};
|
||||
|
||||
typedef enum_nested_loop_state
|
||||
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
|
||||
typedef int (*Read_record_func)(struct st_join_table *tab);
|
||||
|
||||
|
||||
|
@ -162,6 +170,11 @@ class JOIN :public Sql_alloc
|
|||
uint send_group_parts;
|
||||
bool sort_and_group,first_record,full_join,group, no_field_update;
|
||||
bool do_send_rows;
|
||||
/*
|
||||
TRUE when we want to resume nested loop iterations when
|
||||
fetching data from a cursor
|
||||
*/
|
||||
bool resume_nested_loop;
|
||||
table_map const_table_map,found_const_table_map,outer_join;
|
||||
ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
|
||||
/*
|
||||
|
@ -263,6 +276,7 @@ class JOIN :public Sql_alloc
|
|||
sort_and_group= 0;
|
||||
first_record= 0;
|
||||
do_send_rows= 1;
|
||||
resume_nested_loop= FALSE;
|
||||
send_records= 0;
|
||||
found_records= 0;
|
||||
fetch_limit= HA_POS_ERROR;
|
||||
|
@ -374,7 +388,7 @@ public:
|
|||
void reset_thd(THD *thd);
|
||||
|
||||
int open(JOIN *join);
|
||||
int fetch(ulong num_rows);
|
||||
void fetch(ulong num_rows);
|
||||
void reset() { join= 0; }
|
||||
bool is_open() const { return join != 0; }
|
||||
void close();
|
||||
|
|
|
@ -685,6 +685,9 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
|
|||
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
|
||||
while ((field=it++))
|
||||
{
|
||||
/*
|
||||
regfield don't have to be deleted as it's allocated with sql_alloc()
|
||||
*/
|
||||
Field *regfield=make_field((char*) buff+field->offset,field->length,
|
||||
null_pos,
|
||||
null_count & 7,
|
||||
|
@ -696,7 +699,8 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
|
|||
field->interval,
|
||||
field->field_name,
|
||||
&table);
|
||||
DBUG_ASSERT(regfield);
|
||||
if (!regfield)
|
||||
goto err; // End of memory
|
||||
|
||||
if (!(field->flags & NOT_NULL_FLAG))
|
||||
null_count++;
|
||||
|
@ -730,7 +734,6 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
|
|||
regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
|
||||
else
|
||||
regfield->reset();
|
||||
delete regfield;
|
||||
}
|
||||
|
||||
/* Fill not used startpos */
|
||||
|
|
212
tests/index_corrupt.pl
Executable file
212
tests/index_corrupt.pl
Executable file
|
@ -0,0 +1,212 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# This is a test for a key cache bug (bug #10167)
|
||||
# To expose the bug mysqld should be started with --key-buffer-size=64K
|
||||
#
|
||||
|
||||
$opt_loop_count=100000; # Change this to make test harder/easier
|
||||
|
||||
##################### Standard benchmark inits ##############################
|
||||
|
||||
use DBI;
|
||||
use Getopt::Long;
|
||||
use Benchmark;
|
||||
|
||||
package main;
|
||||
|
||||
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
|
||||
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
|
||||
$opt_host=$opt_user=$opt_password=""; $opt_db="test";
|
||||
|
||||
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in",
|
||||
"skip-delete","verbose","fast-insert","lock-tables","debug","fast",
|
||||
"force","user=s","password=s") || die "Aborted";
|
||||
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
|
||||
|
||||
$firsttable = "bench_f1";
|
||||
$secondtable = "bench_f2";
|
||||
$kill_file= "/tmp/mysqltest_index_corrupt.$$";
|
||||
|
||||
####
|
||||
#### Start timeing and start test
|
||||
####
|
||||
|
||||
$start_time=new Benchmark;
|
||||
if (!$opt_skip_create)
|
||||
{
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
$dbh->do("drop table if exists $firsttable, $secondtable");
|
||||
|
||||
print "Creating tables in $opt_db\n";
|
||||
$dbh->do("create table $firsttable (
|
||||
c_pollid INTEGER NOT NULL,
|
||||
c_time BIGINT NOT NULL,
|
||||
c_data DOUBLE NOT NULL,
|
||||
c_error INTEGER NOT NULL,
|
||||
c_warning INTEGER NOT NULL,
|
||||
c_okay INTEGER NOT NULL,
|
||||
c_unknown INTEGER NOT NULL,
|
||||
c_rolled_up BIT NOT NULL,
|
||||
INDEX t_mgmt_hist_r_i1 (c_pollid),
|
||||
INDEX t_mgmt_hist_r_i2 (c_time),
|
||||
INDEX t_mgmt_hist_r_i3 (c_rolled_up))") or die $DBI::errstr;
|
||||
|
||||
$dbh->do("create table $secondtable (
|
||||
c_pollid INTEGER NOT NULL,
|
||||
c_min_time BIGINT NOT NULL,
|
||||
c_max_time BIGINT NOT NULL,
|
||||
c_min_data DOUBLE NOT NULL,
|
||||
c_max_data DOUBLE NOT NULL,
|
||||
c_avg_data DOUBLE NOT NULL,
|
||||
c_error INTEGER NOT NULL,
|
||||
c_warning INTEGER NOT NULL,
|
||||
c_okay INTEGER NOT NULL,
|
||||
c_unknown INTEGER NOT NULL,
|
||||
c_rolled_up BIT NOT NULL,
|
||||
INDEX t_mgmt_hist_d_i1 (c_pollid),
|
||||
INDEX t_mgmt_hist_d_i2 (c_min_time),
|
||||
INDEX t_mgmt_hist_d_i3 (c_max_time),
|
||||
INDEX t_mgmt_hist_d_i4 (c_rolled_up))") or die $DBI::errstr;
|
||||
|
||||
|
||||
$dbh->disconnect; $dbh=0; # Close handler
|
||||
}
|
||||
$|= 1; # Autoflush
|
||||
|
||||
####
|
||||
#### Start the tests
|
||||
####
|
||||
|
||||
print "Running tests\n";
|
||||
insert_in_bench() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||
select_from_bench() if (($pid=fork()) == 0); $work{$pid}="insert-select;
|
||||
delete_from_bench() if (($pid=fork()) == 0); $work{$pid}="delete";
|
||||
|
||||
$errors=0;
|
||||
while (($pid=wait()) != -1)
|
||||
{
|
||||
$ret=$?/256;
|
||||
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
|
||||
$errors++ if ($ret != 0);
|
||||
}
|
||||
|
||||
if (!$opt_skip_delete && !$errors)
|
||||
{
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
$dbh->do("drop table $firsttable, $secondtable");
|
||||
}
|
||||
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||
|
||||
$end_time=new Benchmark;
|
||||
print "Total time: " .
|
||||
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||
|
||||
unlink $kill_file;
|
||||
|
||||
exit(0);
|
||||
|
||||
#
|
||||
# Insert records in the two tables
|
||||
#
|
||||
|
||||
sub insert_in_bench
|
||||
{
|
||||
my ($dbh,$rows,$found,$i);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
for ($rows= 1; $rows <= $opt_loop_count ; $rows++)
|
||||
{
|
||||
$c_pollid = sprintf("%d",rand 1000);
|
||||
$c_time = sprintf("%d",rand 100000);
|
||||
$c_data = rand 1000000;
|
||||
$test = rand 1;
|
||||
$c_error=0;
|
||||
$c_warning=0;
|
||||
$c_okay=0;
|
||||
$c_unknown=0;
|
||||
if ($test < .8) {
|
||||
$c_okay=1;
|
||||
} elsif ($test <.9) {
|
||||
$c_error=1;
|
||||
} elsif ($test <.95) {
|
||||
$c_warning=1;
|
||||
} else {
|
||||
$c_unknown=1;
|
||||
}
|
||||
$statement = "INSERT INTO $firsttable (c_pollid, c_time, c_data, c_error
|
||||
, c_warning, c_okay, c_unknown, c_rolled_up) ".
|
||||
"VALUES ($c_pollid,$c_time,$c_data,$c_error,$c_warning,$c_okay,$c_unknown,0)";
|
||||
$cursor = $dbh->prepare($statement);
|
||||
$cursor->execute();
|
||||
$cursor->finish();
|
||||
}
|
||||
|
||||
$dbh->disconnect; $dbh=0;
|
||||
print "insert_in_bench: Inserted $rows rows\n";
|
||||
|
||||
# Kill other threads
|
||||
open(KILLFILE, "> $kill_file");
|
||||
close(KILLFILE);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
sub select_from_bench
|
||||
{
|
||||
my ($dbh,$rows,$cursor);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
for ($rows= 1; $rows < $opt_loop_count ; $rows++)
|
||||
{
|
||||
$t_value = rand 100000;
|
||||
$t_value2 = $t_value+10000;
|
||||
$statement = "INSERT INTO $secondtable (c_pollid, c_min_time, c_max_time
|
||||
, c_min_data, c_max_data, c_avg_data, c_error, c_warning, c_okay, c_unknown, c_rolled_up) SELECT c_pollid, MIN(c_time), MAX(c_time), MIN(c_data), MAX(c_data), AVG(c_data), SUM(c_error), SUM(c_warning), SUM(c_okay), SUM(c_unknown), 0 FROM $firsttable WHERE (c_time>=$t_value) AND (c_time<$t_value2) AND (c_rolled_up=0) GROUP BY c_pollid";
|
||||
$cursor = $dbh->prepare($statement);
|
||||
$cursor->execute();
|
||||
$cursor->finish();
|
||||
sleep 1;
|
||||
if (-e $kill_file)
|
||||
{
|
||||
last;
|
||||
}
|
||||
}
|
||||
print "select_from_bench: insert-select executed $rows times\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
sub delete_from_bench
|
||||
{
|
||||
my ($dbh,$row, $t_value, $t2_value, $statement, $cursor);
|
||||
|
||||
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||
$opt_user, $opt_password,
|
||||
{ PrintError => 0}) || die $DBI::errstr;
|
||||
|
||||
for ($rows= 1; $rows < $opt_loop_count ; $rows++)
|
||||
{
|
||||
$t_value = rand 50000;
|
||||
$t2_value = $t_value + 50001;
|
||||
$statement = "DELETE FROM $firsttable WHERE (c_time>$t_value) AND (c_time<$t2_value)";
|
||||
$cursor = $dbh->prepare($statement);
|
||||
$cursor->execute();
|
||||
$cursor->finish();
|
||||
sleep 10;
|
||||
if (-e $kill_file)
|
||||
{
|
||||
last;
|
||||
}
|
||||
}
|
||||
print "delete: delete executed $rows times\n";
|
||||
exit(0);
|
||||
}
|
|
@ -7046,6 +7046,7 @@ static void test_set_option()
|
|||
bug #89 (reported by mark@mysql.com)
|
||||
*/
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
static void test_prepare_grant()
|
||||
{
|
||||
int rc;
|
||||
|
@ -7138,7 +7139,7 @@ static void test_prepare_grant()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Test a crash when invalid/corrupted .frm is used in the
|
||||
|
@ -12597,7 +12598,7 @@ static void test_bug8330()
|
|||
const char *stmt_text;
|
||||
MYSQL_STMT *stmt[2];
|
||||
int i, rc;
|
||||
char *query= "select a,b from t1 where a=?";
|
||||
const char *query= "select a,b from t1 where a=?";
|
||||
MYSQL_BIND bind[2];
|
||||
long lval[2];
|
||||
|
||||
|
@ -12788,7 +12789,7 @@ static void test_bug8722()
|
|||
}
|
||||
|
||||
|
||||
MYSQL_STMT *open_cursor(char *query)
|
||||
MYSQL_STMT *open_cursor(const char *query)
|
||||
{
|
||||
int rc;
|
||||
const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
|
||||
|
@ -12854,6 +12855,59 @@ static void test_bug9159()
|
|||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
/* Crash when opening a cursor to a query with DISTICNT and no key */
|
||||
|
||||
static void test_bug9520()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[1];
|
||||
char a[6];
|
||||
ulong a_len;
|
||||
int rc, row_count= 0;
|
||||
|
||||
myheader("test_bug9520");
|
||||
|
||||
mysql_query(mysql, "drop table if exists t1");
|
||||
mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
|
||||
" primary key (a, b, c))");
|
||||
rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
|
||||
" ('a', 'b', 'c'), ('k', 'l', 'm')");
|
||||
myquery(rc);
|
||||
|
||||
stmt= open_cursor("select distinct b from t1");
|
||||
|
||||
/*
|
||||
Not crashes with:
|
||||
stmt= open_cursor("select distinct a from t1");
|
||||
*/
|
||||
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_execute(stmt, rc);
|
||||
|
||||
bzero(bind, sizeof(bind));
|
||||
bind[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[0].buffer= (char*) a;
|
||||
bind[0].buffer_length= sizeof(a);
|
||||
bind[0].length= &a_len;
|
||||
|
||||
mysql_stmt_bind_result(stmt, bind);
|
||||
|
||||
while (!(rc= mysql_stmt_fetch(stmt)))
|
||||
row_count++;
|
||||
|
||||
DIE_UNLESS(rc == MYSQL_NO_DATA);
|
||||
|
||||
printf("Fetched %d rows\n", row_count);
|
||||
DBUG_ASSERT(row_count == 3);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
rc= mysql_query(mysql, "drop table t1");
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
*/
|
||||
|
@ -13079,6 +13133,7 @@ static struct my_tests_st my_tests[]= {
|
|||
{ "test_bug8722", test_bug8722 },
|
||||
{ "test_bug8880", test_bug8880 },
|
||||
{ "test_bug9159", test_bug9159 },
|
||||
{ "test_bug9520", test_bug9520 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue