Merge willster.(none):/home/stewart/Documents/MySQL/5.1/ndb

into  willster.(none):/home/stewart/Documents/MySQL/5.1/pending


include/my_sys.h:
  Auto merged
This commit is contained in:
unknown 2006-11-02 17:25:53 +11:00
commit d712fa8893
100 changed files with 3369 additions and 882 deletions

View file

@ -66,7 +66,7 @@ INSTALL-BINARY: mysql.info $(GT)
# It is not in BitKeeper, but is downloaded from intranet by Bootstrap.
dist-hook:
if [ -e $(srcdir)/manual.chm ] ; then \
cp $(srcdir)/manual.chm $(distdir); \
cp -f $(srcdir)/manual.chm $(distdir); \
fi
# Don't update the files from bitkeeper

View file

@ -65,6 +65,9 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock
ADD_EXECUTABLE(mysqlimport mysqlimport.c)
TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32)
ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c)
TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32)
ADD_EXECUTABLE(mysqlshow mysqlshow.c)
TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32)

View file

@ -253,6 +253,29 @@ AC_DEFUN([MYSQL_PLUGIN_ACTIONS],[
])
])
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS
dnl
dnl SYNOPSIS
dnl MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS([name],[file name])
dnl
dnl DESCRIPTION
dnl Some modules in plugins keep dependance on structures
dnl declared in sql/ (THD class usually)
dnl That has to be fixed in the future, but until then
dnl we have to recompile these modules when we want to
dnl to compile server parts with the different #defines
dnl Normally it happens when we compile the embedded server
dnl Thus one should mark such files in his handler using this macro
dnl (currently only one such a file per plugin is supported)
dnl
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS],[
MYSQL_REQUIRE_PLUGIN([$1])
m4_define([MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS_]AS_TR_CPP([$1]), [$2])
])
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CONFIGURE_PLUGINS
dnl
@ -282,6 +305,9 @@ AC_DEFUN([MYSQL_CONFIGURE_PLUGINS],[
AC_SUBST([mysql_pg_dirs])
AC_SUBST([mysql_se_unittest_dirs])
AC_SUBST([mysql_pg_unittest_dirs])
AC_SUBST([condition_dependent_plugin_modules])
AC_SUBST([condition_dependent_plugin_links])
AC_SUBST([condition_dependent_plugin_includes])
])
])
])
@ -307,6 +333,7 @@ AC_DEFUN([_MYSQL_EMIT_CHECK_PLUGIN],[
[MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]),
[MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
[MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
[MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS_]AS_TR_CPP([$1]),
[MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1])
)
])
@ -402,6 +429,11 @@ dnl Although this is "pretty", it breaks libmysqld build
mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
[with_plugin_]$2=yes
AC_MSG_RESULT([yes])
m4_ifdef([$11],[
condition_dependent_plugin_modules="$condition_dependent_plugin_modules m4_bregexp($11, [[^/]+$], [\&])"
condition_dependent_plugin_links="$condition_dependent_plugin_links $6/$11"
condition_dependent_plugin_includes="$condition_dependent_plugin_includes -I[\$(top_srcdir)]/$6/m4_bregexp($11, [^.+[/$]], [\&])"
])
fi
m4_ifdef([$6],[
if test -n "$mysql_use_plugin_dir" ; then

View file

@ -1441,9 +1441,9 @@ fi
# dlopen, dlerror
case "$with_mysqld_ldflags " in
*"-static "*)
*"-all-static "*)
# No need to check for dlopen when mysqld is linked with
# -all-static or -static as it won't be able to load any functions.
# -all-static as it won't be able to load any functions.
# NOTE! It would be better if it was possible to test if dlopen
# can be used, but a good way to test it couldn't be found

View file

@ -120,6 +120,8 @@ enum my_lex_states
struct charset_info_st;
/* See strings/CHARSET_INFO.txt for information about this structure */
typedef struct my_collation_handler_st
{
my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
@ -162,6 +164,7 @@ extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler;
extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler;
/* See strings/CHARSET_INFO.txt about information on this structure */
typedef struct my_charset_handler_st
{
my_bool (*init)(struct charset_info_st *, void *(*alloc)(uint));
@ -228,6 +231,7 @@ extern MY_CHARSET_HANDLER my_charset_8bit_handler;
extern MY_CHARSET_HANDLER my_charset_ucs2_handler;
/* See strings/CHARSET_INFO.txt about information on this structure */
typedef struct charset_info_st
{
uint number;

View file

@ -229,12 +229,17 @@ enum ha_base_keytype {
#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */
#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
#if MYSQL_VERSION_ID < 0x50200
/*
Key has a part that can have end space. If this is an unique key
we have to handle it differently from other unique keys as we can find
many matching rows for one key (because end space are not compared)
*/
#define HA_END_SPACE_KEY 4096
#define HA_END_SPACE_KEY 0 /* was: 4096 */
#else
#error HA_END_SPACE_KEY is obsolete, please remove it
#endif
/* These flags can be added to key-seg-flag */

View file

@ -614,12 +614,17 @@ C_MODE_END
#define _STATIC_VARARGS(X) X
#define _PC(X) X
/* The DBUG_ON flag always takes precedence over default DBUG_OFF */
#if defined(DBUG_ON) && defined(DBUG_OFF)
#undef DBUG_OFF
#endif
#if defined(_lint) && !defined(DBUG_OFF)
#define DBUG_OFF
/* We might be forced to turn debug off, if not turned off already */
#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF)
# define DBUG_OFF
# ifdef DBUG_ON
# undef DBUG_ON
# endif
#endif
#include <my_dbug.h>

View file

@ -341,12 +341,18 @@ typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
#ifdef THREAD
typedef struct st_io_cache_share
{
/* to sync on reads into buffer */
pthread_mutex_t mutex;
pthread_cond_t cond;
int count, total;
/* actual IO_CACHE that filled the buffer */
struct st_io_cache *active;
pthread_mutex_t mutex; /* To sync on reads into buffer. */
pthread_cond_t cond; /* To wait for signals. */
pthread_cond_t cond_writer; /* For a synchronized writer. */
/* Offset in file corresponding to the first byte of buffer. */
my_off_t pos_in_file;
/* If a synchronized write cache is the source of the data. */
struct st_io_cache *source_cache;
byte *buffer; /* The read buffer. */
byte *read_end; /* Behind last valid byte of buffer. */
int running_threads; /* threads not in lock. */
int total_threads; /* threads sharing the cache. */
int error; /* Last error. */
#ifdef NOT_YET_IMPLEMENTED
/* whether the structure should be free'd */
my_bool alloced;
@ -720,8 +726,8 @@ extern void setup_io_cache(IO_CACHE* info);
extern int _my_b_read(IO_CACHE *info,byte *Buffer,uint Count);
#ifdef THREAD
extern int _my_b_read_r(IO_CACHE *info,byte *Buffer,uint Count);
extern void init_io_cache_share(IO_CACHE *info,
IO_CACHE_SHARE *s, uint num_threads);
extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
IO_CACHE *write_cache, uint num_threads);
extern void remove_io_thread(IO_CACHE *info);
#endif
extern int _my_b_seq_read(IO_CACHE *info,byte *Buffer,uint Count);

View file

@ -419,7 +419,7 @@ typedef struct st_mi_check_param
uint testflag, key_cache_block_size;
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair, force_sort, calc_checksum;
my_bool retry_repair, force_sort;
char temp_filename[FN_REFLEN],*isam_file_name;
MY_TMPDIR *tmpdir;
int tmpfile_createflag;

View file

@ -293,12 +293,6 @@ typedef struct st_mysql
/* needed for embedded server - no net buffer to store the 'info' */
char *info_buffer;
#endif
/*
In embedded server it points to the statement that is processed
in the current query. We store some results directly in statement
fields then.
*/
struct st_mysql_stmt *current_stmt;
} MYSQL;
typedef struct st_mysql_res {

View file

@ -32,7 +32,8 @@ INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \
-I$(top_srcdir)/regex \
$(openssl_includes) @ZLIB_INCLUDES@
$(openssl_includes) @ZLIB_INCLUDES@ \
@condition_dependent_plugin_includes@
noinst_LIBRARIES = libmysqld_int.a
pkglib_LIBRARIES = libmysqld.a
@ -77,6 +78,8 @@ libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
libmysqld_a_SOURCES=
sqlstoragesources = $(EXTRA_libmysqld_a_SOURCES)
storagesources = @condition_dependent_plugin_modules@
storagesourceslinks = @condition_dependent_plugin_links@
# automake misses these
sql_yacc.cc sql_yacc.h: $(top_srcdir)/sql/sql_yacc.yy
@ -170,12 +173,19 @@ link_sources:
@LN_CP_F@ `find $(srcdir)/../sql -name "$$f"` "$$f"; \
done; \
fi; \
if test -n "$(storagesources)" ; \
then \
rm -f $(storagesources); \
for f in $(storagesourceslinks); do \
@LN_CP_F@ $(top_srcdir)/$$f . ; \
done; \
fi; \
rm -f client_settings.h; \
@LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
clean-local:
rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlstoragesources) | sed "s;\.lo;.c;g"` \
rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlstoragesources) $(storagesources) | sed "s;\.lo;.c;g"` \
$(top_srcdir)/linked_libmysqld_sources; \
rm -f client_settings.h

View file

@ -100,7 +100,6 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
mysql->affected_rows= ~(my_ulonglong) 0;
mysql->field_count= 0;
net->last_errno= 0;
mysql->current_stmt= stmt;
thd->store_globals(); // Fix if more than one connect
/*

View file

@ -321,6 +321,24 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
DROP TABLE t1,t2;
#
# Bug#22781: SQL_BIG_RESULT fails to influence sort plan
#
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB;
INSERT INTO t1 VALUES ( 1 , 1 , 1);
INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1;
EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b;
EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b;
DROP TABLE t1;
#
# Test of behaviour with CREATE ... SELECT
#

View file

@ -1155,6 +1155,81 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
set names utf8;
create table t1 (s1 char(5) character set utf8);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_general_ci from t1 where s1 like 'ペテ%';
before_delete_general_ci
ペテルグル
delete from t1 where s1 = 'Y';
select s1 as after_delete_general_ci from t1 where s1 like 'ペテ%';
after_delete_general_ci
ペテルグル
drop table t1;
set names utf8;
create table t1 (s1 char(5) character set utf8 collate utf8_unicode_ci);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_unicode_ci from t1 where s1 like 'ペテ%';
before_delete_unicode_ci
ペテルグル
delete from t1 where s1 = 'Y';
select s1 as after_delete_unicode_ci from t1 where s1 like 'ペテ%';
after_delete_unicode_ci
ペテルグル
drop table t1;
set names utf8;
create table t1 (s1 char(5) character set utf8 collate utf8_bin);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_bin from t1 where s1 like 'ペテ%';
before_delete_bin
ペテルグル
delete from t1 where s1 = 'Y';
select s1 as after_delete_bin from t1 where s1 like 'ペテ%';
after_delete_bin
ペテルグル
drop table t1;
set names utf8;
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_general_ci;
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as gci1 from t1 where a like 'さしすせそかきくけこあいうえお%';
gci1
さしすせそかきくけこあいうえお
select a as gci2 from t1 where a like 'あいうえおかきくけこさしすせそ';
gci2
あいうえおかきくけこさしすせそ
drop table t1;
set names utf8;
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_unicode_ci;
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as uci1 from t1 where a like 'さしすせそかきくけこあいうえお%';
uci1
さしすせそかきくけこあいうえお
select a as uci2 from t1 where a like 'あいうえおかきくけこさしすせそ';
uci2
あいうえおかきくけこさしすせそ
drop table t1;
set names utf8;
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_bin;
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as bin1 from t1 where a like 'さしすせそかきくけこあいうえお%';
bin1
さしすせそかきくけこあいうえお
select a as bin2 from t1 where a like 'あいうえおかきくけこさしすせそ';
bin2
あいうえおかきくけこさしすせそ
drop table t1;
SET NAMES utf8;
CREATE TABLE t1 (id int PRIMARY KEY,
a varchar(16) collate utf8_unicode_ci NOT NULL default '',

View file

@ -74,11 +74,6 @@ grp group_concat(c order by 1)
1 a
2 b,c
3 C,D,d,d,D,E
select grp,group_concat(c order by "c") from t1 group by grp;
grp group_concat(c order by "c")
1 a
2 b,c
3 C,D,d,d,D,E
select grp,group_concat(distinct c order by c) from t1 group by grp;
grp group_concat(distinct c order by c)
1 a

View file

@ -1143,9 +1143,9 @@ EXPLAIN EXTENDED
SELECT * FROM t1 INNER JOIN t2 ON code=id
WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 const PRIMARY PRIMARY 12 const 1 100.00 Using index
1 SIMPLE t1 ref code code 13 const 3 100.00 Using where; Using index
1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
DROP TABLE t1,t2;
End of 5.0 tests

View file

@ -862,3 +862,14 @@ CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
CREATE TABLE t1 (foo GEOMETRY NOT NULL, SPATIAL INDEX(foo) );
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(1,1)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(1,0)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(0,1)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(0,0)));
SELECT 1 FROM t1 WHERE foo != PointFromWKB(POINT(0,0));
1
1
1
1
DROP TABLE t1;

View file

@ -303,10 +303,10 @@ spid sum(userid)
1 1
explain select sql_big_result score,count(*) from t1 group by score desc;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL score 3 NULL 8 Using index
1 SIMPLE t1 index NULL score 3 NULL 8 Using index; Using filesort
explain select sql_big_result score,count(*) from t1 group by score desc order by null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL score 3 NULL 8 Using index
1 SIMPLE t1 index NULL score 3 NULL 8 Using index; Using filesort
select sql_big_result score,count(*) from t1 group by score desc;
score count(*)
3 5
@ -775,6 +775,55 @@ select sql_buffer_result max(f1)+1 from t1;
max(f1)+1
3
drop table t1;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1),(2);
SELECT a FROM t1 GROUP BY 'a';
a
1
SELECT a FROM t1 GROUP BY "a";
a
1
SELECT a FROM t1 GROUP BY `a`;
a
1
2
set sql_mode=ANSI_QUOTES;
SELECT a FROM t1 GROUP BY "a";
a
1
2
SELECT a FROM t1 GROUP BY 'a';
a
1
SELECT a FROM t1 GROUP BY `a`;
a
1
2
set sql_mode='';
SELECT a FROM t1 HAVING 'a' > 1;
a
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT a FROM t1 HAVING "a" > 1;
a
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
SELECT a FROM t1 HAVING `a` > 1;
a
2
SELECT a FROM t1 ORDER BY 'a' DESC;
a
1
2
SELECT a FROM t1 ORDER BY "a" DESC;
a
1
2
SELECT a FROM t1 ORDER BY `a` DESC;
a
2
1
DROP TABLE t1;
create table t1 (c1 char(3), c2 char(3));
create table t2 (c3 char(3), c4 char(3));
insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2');
@ -821,6 +870,69 @@ a b real_b
68 France France
DROP VIEW v1;
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, key (b));
INSERT INTO t1 VALUES (1, 1);
INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20) FROM t1;
INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20) FROM t1;
INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20) FROM t1;
INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20) FROM t1;
INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20) FROM t1;
INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20) FROM t1;
INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20) FROM t1;
SELECT MIN(b), MAX(b) from t1;
MIN(b) MAX(b)
0 19
EXPLAIN SELECT b, sum(1) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL b 5 NULL 128 Using index
EXPLAIN SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL b 5 NULL 128 Using index; Using filesort
SELECT b, sum(1) FROM t1 GROUP BY b;
b sum(1)
0 6
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 6
10 6
11 6
12 6
13 6
14 6
15 6
16 6
17 6
18 6
19 6
SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b;
b sum(1)
0 6
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 6
10 6
11 6
12 6
13 6
14 6
15 6
16 6
17 6
18 6
19 6
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, KEY(a));
INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2;

View file

@ -2162,3 +2162,23 @@ t1;
id2 id3 id5 id4 id3 id6 id5 id1
1 1 1 1 1 1 1 1
DROP TABLE t1,t2,t3,t4,t5,t6;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b), KEY b (b));
INSERT INTO t1 VALUES (1,1),(1,2),(1,0),(1,3);
explain SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY,b PRIMARY 8 NULL 1 Using where; Using index for group-by
SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
MAX(b) a
1 1
SELECT MIN(b), a FROM t1 WHERE b > 1 AND a = 1 GROUP BY a;
MIN(b) a
2 1
CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c));
INSERT INTO t2 SELECT a,b,b FROM t1;
explain SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY PRIMARY 12 NULL 1 Using where; Using index for group-by
SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
MIN(c)
2
DROP TABLE t1,t2;

View file

@ -2063,15 +2063,15 @@ i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1

View file

@ -290,6 +290,22 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB;
INSERT INTO t1 VALUES ( 1 , 1 , 1);
INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20), 1 FROM t1;
INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1;
EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL b 5 NULL 128
EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort
DROP TABLE t1;
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(1,2);
CREATE TABLE t2 (primary key (a)) select * from t1;

View file

@ -629,7 +629,7 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref PRIMARY,files PRIMARY 35 const,const 1 Using where
1 SIMPLE t2 const PRIMARY,files PRIMARY 35 const,const 1
DROP TABLE t2, t1;
create table t1 (x int, y int, index xy(x, y));
create table t2 (x int, y int, index xy(x, y));

View file

@ -1611,15 +1611,15 @@ i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1

View file

@ -796,6 +796,132 @@ a b
xxxxxxxxx bbbbbb
xxxxxxxxx bbbbbb
DROP TABLE t1;
SET @@myisam_repair_threads=2;
SHOW VARIABLES LIKE 'myisam_repair%';
Variable_name Value
myisam_repair_threads 2
CREATE TABLE t1 (
`_id` int(11) NOT NULL default '0',
`url` text,
`email` text,
`description` text,
`loverlap` int(11) default NULL,
`roverlap` int(11) default NULL,
`lneighbor_id` int(11) default NULL,
`rneighbor_id` int(11) default NULL,
`length_` int(11) default NULL,
`sequence` mediumtext,
`name` text,
`_obj_class` text NOT NULL,
PRIMARY KEY (`_id`),
UNIQUE KEY `sequence_name_index` (`name`(50)),
KEY (`length_`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES
(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''),
(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''),
(3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample3',''),
(4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample4',''),
(5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample5',''),
(6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample6',''),
(7,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample7',''),
(8,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample8',''),
(9,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample9','');
SELECT _id FROM t1;
_id
1
2
3
4
5
6
7
8
9
DELETE FROM t1 WHERE _id < 8;
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Dynamic 2 # # # # 140 # # # # # #
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Dynamic 2 # # # # 0 # # # # # #
SELECT _id FROM t1;
_id
8
9
DROP TABLE t1;
CREATE TABLE t1 (
`_id` int(11) NOT NULL default '0',
`url` text,
`email` text,
`description` text,
`loverlap` int(11) default NULL,
`roverlap` int(11) default NULL,
`lneighbor_id` int(11) default NULL,
`rneighbor_id` int(11) default NULL,
`length_` int(11) default NULL,
`sequence` mediumtext,
`name` text,
`_obj_class` text NOT NULL,
PRIMARY KEY (`_id`),
UNIQUE KEY `sequence_name_index` (`name`(50)),
KEY (`length_`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO t1 VALUES
(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''),
(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''),
(3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample3',''),
(4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample4',''),
(5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample5',''),
(6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample6',''),
(7,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample7',''),
(8,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample8',''),
(9,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample9','');
SELECT _id FROM t1;
_id
1
2
3
4
5
6
7
8
9
DELETE FROM t1 WHERE _id < 8;
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Dynamic 2 # # # # 140 # # # # # #
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
REPAIR TABLE t1 QUICK;
Table Op Msg_type Msg_text
test.t1 repair status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Dynamic 2 # # # # 140 # # # # # #
SELECT _id FROM t1;
_id
8
9
DROP TABLE t1;
SET @@myisam_repair_threads=1;
SHOW VARIABLES LIKE 'myisam_repair%';
Variable_name Value
myisam_repair_threads 1
set storage_engine=MyISAM;
drop table if exists t1,t2,t3;
--- Testing varchar ---
@ -1002,15 +1128,15 @@ i 10
select sql_big_result v,count(c) from t1 group by v limit 10;
v count(c)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
i 10
select c,count(*) from t1 group by c limit 10;
c count(*)
a 1

View file

@ -592,6 +592,21 @@ a max(b)
NULL 2
a 1
drop table t1;
create table t1 (a varchar(22) not null , b int);
insert into t1 values ("2006-07-01 21:30", 1), ("2006-07-01 23:30", 10);
select left(a,10), a, sum(b) from t1 group by 1,2 with rollup;
left(a,10) a sum(b)
2006-07-01 2006-07-01 21:30 1
2006-07-01 2006-07-01 23:30 10
2006-07-01 NULL 11
NULL NULL 11
select left(a,10) x, a, sum(b) from t1 group by x,a with rollup;
x a sum(b)
2006-07-01 2006-07-01 21:30 1
2006-07-01 2006-07-01 23:30 10
2006-07-01 NULL 11
NULL NULL 11
drop table t1;
CREATE TABLE t1(id int, type char(1));
INSERT INTO t1 VALUES
(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),

View file

@ -499,54 +499,6 @@ create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
deallocate prepare stmt;
CREATE TABLE t1(
ID int(10) unsigned NOT NULL auto_increment,
Member_ID varchar(15) NOT NULL default '',
Action varchar(12) NOT NULL,
Action_Date datetime NOT NULL,
Track varchar(15) default NULL,
User varchar(12) default NULL,
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
CURRENT_TIMESTAMP,
PRIMARY KEY (ID),
KEY Action (Action),
KEY Action_Date (Action_Date)
);
INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
('666666', 'Disenrolled', '2006-06-01', 'CAD' );
PREPARE STMT FROM
"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
WHERE Member_ID=? AND Action='Enrolled' AND
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
WHERE Member_ID=?
GROUP BY Track
HAVING Track>='CAD' AND
MAX(Action_Date)>'2006-03-01')";
SET @id='111111';
EXECUTE STMT USING @id,@id;
GROUP_CONCAT(Track SEPARATOR ', ')
NULL
SET @id='222222';
EXECUTE STMT USING @id,@id;
GROUP_CONCAT(Track SEPARATOR ', ')
CAD
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
End of 4.1 tests
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
@ -564,77 +516,6 @@ SELECT FOUND_ROWS();
FOUND_ROWS()
2
deallocate prepare stmt;
create table t1 (a char(3) not null, b char(3) not null,
c char(3) not null, primary key (a, b, c));
create table t2 like t1;
prepare stmt from
"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
where t1.a=1";
execute stmt;
a
execute stmt;
a
execute stmt;
a
prepare stmt from
"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
left outer join t2 t3 on t3.a=? where t1.a=?";
set @a:=1, @b:=1, @c:=1;
execute stmt using @a, @b, @c;
a b c a b c
execute stmt using @a, @b, @c;
a b c a b c
execute stmt using @a, @b, @c;
a b c a b c
deallocate prepare stmt;
drop table t1,t2;
SET @aux= "SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS A,
INFORMATION_SCHEMA.COLUMNS B
WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
AND A.TABLE_NAME = B.TABLE_NAME
AND A.COLUMN_NAME = B.COLUMN_NAME AND
A.TABLE_NAME = 'user'";
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
39
execute my_stmt;
COUNT(*)
39
execute my_stmt;
COUNT(*)
39
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
create table t1 (id int)|
insert into t1 values(1)|
create procedure p1(a int, b int)
begin
declare c int;
select max(id)+1 into c from t1;
insert into t1 select a+b;
insert into t1 select a-b;
insert into t1 select a-c;
end|
set @a= 3, @b= 4|
prepare stmt from "call p1(?, ?)"|
execute stmt using @a, @b|
execute stmt using @a, @b|
select * from t1|
id
1
7
-1
1
7
-1
-5
deallocate prepare stmt|
drop procedure p1|
drop table t1|
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
@ -698,47 +579,6 @@ id
3
deallocate prepare stmt;
drop table t1, t2;
create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
prepare stmt from "select * from t1 limit ?, ?";
set @offset=0, @limit=1;
execute stmt using @offset, @limit;
a
1
select * from t1 limit 0, 1;
a
1
set @offset=3, @limit=2;
execute stmt using @offset, @limit;
a
4
5
select * from t1 limit 3, 2;
a
4
5
prepare stmt from "select * from t1 limit ?";
execute stmt using @limit;
a
1
2
prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
set @offset=9;
set @limit=2;
execute stmt using @offset, @limit;
a
10
1
prepare stmt from "(select * from t1 limit ?, ?) union all
(select * from t1 limit ?, ?) order by a limit ?";
execute stmt using @offset, @limit, @offset, @limit, @limit;
a
10
10
drop table t1;
deallocate prepare stmt;
create table t1 (id int);
prepare stmt from "insert into t1 (id) select id from t1 union select id from t1";
execute stmt;
@ -839,15 +679,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
select ? from t1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1
drop table t1;
CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
EXECUTE b12651;
1
DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2;
DEALLOCATE PREPARE b12651;
prepare stmt from "select @@time_zone";
execute stmt;
@@time_zone
@ -1064,6 +895,194 @@ select @@max_prepared_stmt_count, @@prepared_stmt_count;
@@max_prepared_stmt_count @@prepared_stmt_count
3 0
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
drop table if exists t1;
create temporary table if not exists t1 (a1 int);
prepare stmt from "delete t1 from t1 where (cast(a1/3 as unsigned) * 3) = a1";
drop temporary table t1;
create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
deallocate prepare stmt;
CREATE TABLE t1(
ID int(10) unsigned NOT NULL auto_increment,
Member_ID varchar(15) NOT NULL default '',
Action varchar(12) NOT NULL,
Action_Date datetime NOT NULL,
Track varchar(15) default NULL,
User varchar(12) default NULL,
Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
CURRENT_TIMESTAMP,
PRIMARY KEY (ID),
KEY Action (Action),
KEY Action_Date (Action_Date)
);
INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
('111111', 'Enrolled', '2006-03-01', 'CAD' ),
('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
('222222', 'Enrolled', '2006-03-07', 'CAD' ),
('222222', 'Enrolled', '2006-03-07', 'CHF' ),
('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
('333333', 'Enrolled', '2006-03-01', 'CAD' ),
('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
('444444', 'Enrolled', '2006-03-01', 'CAD' ),
('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
('555555', 'Enrolled', '2006-07-21', 'CAD' ),
('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
('666666', 'Enrolled', '2006-02-09', 'CAD' ),
('666666', 'Enrolled', '2006-05-12', 'CHF' ),
('666666', 'Disenrolled', '2006-06-01', 'CAD' );
PREPARE STMT FROM
"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
WHERE Member_ID=? AND Action='Enrolled' AND
(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
WHERE Member_ID=?
GROUP BY Track
HAVING Track>='CAD' AND
MAX(Action_Date)>'2006-03-01')";
SET @id='111111';
EXECUTE STMT USING @id,@id;
GROUP_CONCAT(Track SEPARATOR ', ')
NULL
SET @id='222222';
EXECUTE STMT USING @id,@id;
GROUP_CONCAT(Track SEPARATOR ', ')
CAD
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
End of 4.1 tests
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
ERROR 42000: FUNCTION test.char_length does not exist
drop table t1;
create table t1 (a char(3) not null, b char(3) not null,
c char(3) not null, primary key (a, b, c));
create table t2 like t1;
prepare stmt from
"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b)
where t1.a=1";
execute stmt;
a
execute stmt;
a
execute stmt;
a
prepare stmt from
"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from
(t1 left outer join t2 on t2.a=? and t1.b=t2.b)
left outer join t2 t3 on t3.a=? where t1.a=?";
set @a:=1, @b:=1, @c:=1;
execute stmt using @a, @b, @c;
a b c a b c
execute stmt using @a, @b, @c;
a b c a b c
execute stmt using @a, @b, @c;
a b c a b c
deallocate prepare stmt;
drop table t1,t2;
SET @aux= "SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS A,
INFORMATION_SCHEMA.COLUMNS B
WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA
AND A.TABLE_NAME = B.TABLE_NAME
AND A.COLUMN_NAME = B.COLUMN_NAME AND
A.TABLE_NAME = 'user'";
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
39
execute my_stmt;
COUNT(*)
39
execute my_stmt;
COUNT(*)
39
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
create table t1 (id int)|
insert into t1 values(1)|
create procedure p1(a int, b int)
begin
declare c int;
select max(id)+1 into c from t1;
insert into t1 select a+b;
insert into t1 select a-b;
insert into t1 select a-c;
end|
set @a= 3, @b= 4|
prepare stmt from "call p1(?, ?)"|
execute stmt using @a, @b|
execute stmt using @a, @b|
select * from t1|
id
1
7
-1
1
7
-1
-5
deallocate prepare stmt|
drop procedure p1|
drop table t1|
create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
prepare stmt from "select * from t1 limit ?, ?";
set @offset=0, @limit=1;
execute stmt using @offset, @limit;
a
1
select * from t1 limit 0, 1;
a
1
set @offset=3, @limit=2;
execute stmt using @offset, @limit;
a
4
5
select * from t1 limit 3, 2;
a
4
5
prepare stmt from "select * from t1 limit ?";
execute stmt using @limit;
a
1
2
prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
set @offset=9;
set @limit=2;
execute stmt using @offset, @limit;
a
10
1
prepare stmt from "(select * from t1 limit ?, ?) union all
(select * from t1 limit ?, ?) order by a limit ?";
execute stmt using @offset, @limit, @offset, @limit, @limit;
a
10
10
drop table t1;
deallocate prepare stmt;
CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
EXECUTE b12651;
1
DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2;
DEALLOCATE PREPARE b12651;
create table t1 (id int);
prepare ins_call from "insert into t1 (id) values (1)";
execute ins_call;
@ -1365,22 +1384,26 @@ create procedure proc_1() reset query cache;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin reset query cache; return 1; end|
ERROR 0A000: RESET is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 0A000: FLUSH is not allowed in stored function or trigger
ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
drop procedure proc_1;
prepare abc from "reset query cache";
execute abc;
execute abc;
execute abc;
deallocate prepare abc;
create procedure proc_1() reset master;
drop procedure proc_1;
create function func_1() returns int begin reset master; return 1; end|
ERROR 0A000: RESET is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 0A000: FLUSH is not allowed in stored function or trigger
ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
drop procedure proc_1;
prepare abc from "reset master";
execute abc;
execute abc;
@ -1390,11 +1413,13 @@ create procedure proc_1() reset slave;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin reset slave; return 1; end|
ERROR 0A000: RESET is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 0A000: FLUSH is not allowed in stored function or trigger
ERROR 0A000: RESET is not allowed in stored function or trigger
drop function func_1;
drop procedure proc_1;
prepare abc from "reset slave";
execute abc;
execute abc;
@ -1429,13 +1454,13 @@ call proc_1();
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush hosts; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush hosts";
execute abc;
execute abc;
@ -1445,13 +1470,13 @@ create procedure proc_1() flush privileges;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush privileges; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush privileges";
deallocate prepare abc;
create procedure proc_1() flush tables with read lock;
@ -1461,9 +1486,13 @@ call proc_1();
unlock tables;
call proc_1();
unlock tables;
drop procedure proc_1;
create function func_1() returns int begin flush tables with read lock; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
drop procedure proc_1;
prepare abc from "flush tables with read lock";
execute abc;
execute abc;
@ -1474,13 +1503,13 @@ create procedure proc_1() flush tables;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush tables; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush tables";
execute abc;
execute abc;
@ -1540,13 +1569,13 @@ mysql user 0 0
mysql general_log 1 0
mysql host 0 0
flush tables;
drop procedure proc_1;
create function func_1() returns int begin flush tables; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
flush tables;
select Host, User from mysql.user limit 0;
Host User
@ -1603,13 +1632,13 @@ create procedure proc_1() flush logs;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush logs; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush logs";
execute abc;
execute abc;
@ -1619,13 +1648,13 @@ create procedure proc_1() flush status;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush status; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush status";
execute abc;
execute abc;
@ -1635,39 +1664,39 @@ create procedure proc_1() flush slave;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush slave; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush slave";
execute abc;
execute abc;
execute abc;
deallocate prepare abc;
create procedure proc_1() flush master;
drop procedure proc_1;
create function func_1() returns int begin flush master; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush master";
deallocate prepare abc;
create procedure proc_1() flush des_key_file;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush des_key_file; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush des_key_file";
execute abc;
execute abc;
@ -1677,13 +1706,13 @@ create procedure proc_1() flush user_resources;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
create function func_1() returns int begin flush user_resources; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
create function func_1() returns int begin call proc_1(); return 1; end|
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
ERROR 0A000: FLUSH is not allowed in stored function or trigger
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
drop procedure proc_1;
prepare abc from "flush user_resources";
execute abc;
execute abc;
@ -1763,18 +1792,6 @@ Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
execute abc;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
deallocate prepare abc;
create procedure proc_1() show scheduler status;
drop procedure proc_1;
create function func_1() returns int begin show scheduler status; return 1; end|
ERROR 0A000: Not allowed to return a result set from a function
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
drop function func_1;
ERROR 42000: FUNCTION test.func_1 does not exist
prepare abc from "show scheduler status";
ERROR HY000: This command is not supported in the prepared statement protocol yet
deallocate prepare abc;
ERROR HY000: Unknown prepared statement handler (abc) given to DEALLOCATE PREPARE
drop procedure if exists a;
create procedure a() select 42;
create procedure proc_1(a char(2)) show create procedure a;
@ -1952,11 +1969,11 @@ ERROR HY000: No paths allowed for shared library
drop procedure proc_1;
create procedure proc_1() install plugin my_plug soname 'some_plugin.so';
call proc_1();
ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 0 cannot open shared object file: No such file or directory)
ERROR HY000: Can't open shared library
call proc_1();
ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 22 cannot open shared object file: No such file or directory)
ERROR HY000: Can't open shared library
call proc_1();
ERROR HY000: Can't open shared library '/work/mysql-5.1-runtime/mysql-test/lib/mysql/some_plugin.so' (errno: 22 cannot open shared object file: No such file or directory)
ERROR HY000: Can't open shared library
drop procedure proc_1;
create function func_1() returns int begin install plugin my_plug soname '/tmp/plugin'; return 1; end|
ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
@ -2086,7 +2103,7 @@ drop user pstest_xyz@localhost;
deallocate prepare abc;
drop event if exists xyz;
create function func_1() returns int begin create event xyz on schedule at now() do select 123; return 1; end|
ERROR 0A000: Not allowed to return a result set from a function
ERROR HY000: Recursivity of EVENT DDL statements is forbidden when body is present
select func_1(), func_1(), func_1() from dual;
ERROR 42000: FUNCTION test.func_1 does not exist
drop function func_1;

View file

@ -54,3 +54,13 @@ Tables_in_test
t2
t4
drop table t2, t4;
create table t1(f1 int);
create view v1 as select * from t1;
alter table v1 rename to v2;
alter table v1 rename to v2;
ERROR 42S02: Table 'test.v1' doesn't exist
rename table v2 to v1;
rename table v2 to v1;
ERROR 42S01: Table 'v1' already exists
drop view v1;
drop table t1;

View file

@ -52,6 +52,44 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
t1 1 a 1 a A 5 NULL NULL YES BTREE
SET myisam_repair_threads=@@global.myisam_repair_threads;
DROP TABLE t1;
CREATE TABLE t1(a INT);
USE mysql;
REPAIR TABLE test.t1 USE_FRM;
Table Op Msg_type Msg_text
test.t1 repair status OK
USE test;
DROP TABLE t1;
CREATE TABLE t1(a CHAR(255), KEY(a));
SET myisam_sort_buffer_size=4096;
INSERT INTO t1 VALUES
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0');
Warnings:
Error 1034 sort_buffer_size is to small
Error 1034 Number of rows changed from 0 to 157
SET myisam_repair_threads=2;
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair error sort_buffer_size is to small
test.t1 repair warning Number of rows changed from 0 to 157
test.t1 repair status OK
SET myisam_repair_threads=@@global.myisam_repair_threads;
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
DROP TABLE t1;
DROP TABLE IF EXISTS tt1;
CREATE TEMPORARY TABLE tt1 (c1 INT);
REPAIR TABLE tt1 USE_FRM;

View file

@ -3517,3 +3517,97 @@ id a b c d e
2 NULL NULL NULL 2 40
2 NULL NULL NULL 2 50
DROP TABLE t1,t2,t3;
create table t1 (c1 varchar(1), c2 int, c3 int, c4 int, c5 int, c6 int,
c7 int, c8 int, c9 int, fulltext key (`c1`));
select distinct match (`c1`) against ('z') , c2, c3, c4,c5, c6,c7, c8
from t1 where c9=1 order by c2, c2;
match (`c1`) against ('z') c2 c3 c4 c5 c6 c7 c8
drop table t1;
CREATE TABLE t1 (pk varchar(10) PRIMARY KEY, fk varchar(16));
CREATE TABLE t2 (pk varchar(16) PRIMARY KEY, fk varchar(10));
INSERT INTO t1 VALUES
('d','dddd'), ('i','iii'), ('a','aa'), ('b','bb'), ('g','gg'),
('e','eee'), ('c','cccc'), ('h','hhh'), ('j','jjj'), ('f','fff');
INSERT INTO t2 VALUES
('jjj', 'j'), ('cc','c'), ('ccc','c'), ('aaa', 'a'), ('jjjj','j'),
('hhh','h'), ('gg','g'), ('fff','f'), ('ee','e'), ('ffff','f'),
('bbb','b'), ('ff','f'), ('cccc','c'), ('dddd','d'), ('jj','j'),
('aaaa','a'), ('bb','b'), ('eeee','e'), ('aa','a'), ('hh','h');
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk < 'c' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
CREATE TABLE t2 (a int, b varchar(20) NOT NULL,
PRIMARY KEY (a), UNIQUE KEY (b));
INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c');
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
EXPLAIN SELECT t1.a FROM t1 LEFT JOIN t2 ON t2.b=t1.b WHERE t1.a=3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 const b b 22 const 1 Using index
DROP TABLE t1,t2;
CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
INSERT INTO t1 VALUES
(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
(6,63,67), (5,55,58), (3,38,39), (8,81,89);
INSERT INTO t2 VALUES
(21,210), (41,410), (82,820), (83,830), (84,840),
(65,650), (51,510), (37,370), (94,940), (76,760),
(22,220), (33,330), (40,400), (95,950), (38,380),
(67,670), (88,880), (57,570), (96,960), (97,970);
INSERT INTO t3 VALUES
(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si si 5 NULL 4 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si si 5 NULL 2 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
DROP TABLE t1,t2,t3;

View file

@ -363,12 +363,12 @@ INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 ref PRIMARY PRIMARY 37 const 1 100.00 Using where; Using index
4 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 100.00 Using where; Using index
2 SUBQUERY t8 ref PRIMARY PRIMARY 37 const 1 100.00 Using where
3 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 100.00 Using where; Using index
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
Warnings:
Note 1003 select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))
Note 1003 select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@ -3458,6 +3458,32 @@ id select_type table type possible_keys key key_len ref rows Extra
4 UNION t12 system NULL NULL NULL NULL 0 const row not found
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b));
insert into t1 (a) values (FLOOR(rand() * 100));
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
SELECT a,
(SELECT REPEAT(' ',250) FROM t1 i1
WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a
FROM t1 ORDER BY a LIMIT 5;
a a
0 NULL
0 NULL
0 NULL
0 NULL
0 NULL
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT);
CREATE TABLE t2 (a INT);
INSERT INTO t2 values (1);

View file

@ -779,3 +779,14 @@ select f1 from t1 where f1 in (select f1 from t1);
f1
40
drop table t1;
create table t1 as
select from_days(s) as date,t
from (select 1 as s,'t' as t union select null, null ) as sub1;
select group_concat(t) from t1 group by week(date)/10;
group_concat(t)
t
Warnings:
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '0000-00-00'
Warning 1292 Incorrect datetime value: '0000-00-00'
drop table t1;

View file

@ -1745,3 +1745,12 @@ create table t1 (a set('x','y') default 'x');
alter table t1 alter a set default 'z';
ERROR 42000: Invalid default value for 'a'
drop table t1;
create table t1 (f1 int);
alter table t1 add f2 enum(0xFFFF);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` int(11) DEFAULT NULL,
`f2` enum('ÿÿ') DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;

View file

@ -2956,4 +2956,14 @@ View Create View
v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`))))))
DROP VIEW v1;
DROP TABLE t1, t2;
CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL);
CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION;
INSERT INTO v1 (val) VALUES (2);
INSERT INTO v1 (val) VALUES (4);
INSERT INTO v1 (val) VALUES (6);
ERROR HY000: CHECK OPTION failed 'test.v1'
UPDATE v1 SET val=6 WHERE id=2;
ERROR HY000: CHECK OPTION failed 'test.v1'
DROP VIEW v1;
DROP TABLE t1;
End of 5.0 tests.

View file

@ -941,6 +941,76 @@ INSERT INTO t1 VALUES('uUABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbb
check table t1;
drop table t1;
#
# Bug#20471 LIKE search fails with indexed utf8 char column
#
set names utf8;
create table t1 (s1 char(5) character set utf8);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_general_ci from t1 where s1 like 'ペテ%';
delete from t1 where s1 = 'Y';
select s1 as after_delete_general_ci from t1 where s1 like 'ペテ%';
drop table t1;
set names utf8;
create table t1 (s1 char(5) character set utf8 collate utf8_unicode_ci);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_unicode_ci from t1 where s1 like 'ペテ%';
delete from t1 where s1 = 'Y';
select s1 as after_delete_unicode_ci from t1 where s1 like 'ペテ%';
drop table t1;
set names utf8;
create table t1 (s1 char(5) character set utf8 collate utf8_bin);
insert into t1 values
('a'),('b'),(null),('ペテルグル'),('ü'),('Y');
create index it1 on t1 (s1);
select s1 as before_delete_bin from t1 where s1 like 'ペテ%';
delete from t1 where s1 = 'Y';
select s1 as after_delete_bin from t1 where s1 like 'ペテ%';
drop table t1;
# additional tests from duplicate bug#20744 MySQL return no result
set names utf8;
--disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_general_ci;
--enable_warnings
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as gci1 from t1 where a like 'さしすせそかきくけこあいうえお%';
select a as gci2 from t1 where a like 'あいうえおかきくけこさしすせそ';
drop table t1;
set names utf8;
--disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_unicode_ci;
--enable_warnings
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as uci1 from t1 where a like 'さしすせそかきくけこあいうえお%';
select a as uci2 from t1 where a like 'あいうえおかきくけこさしすせそ';
drop table t1;
set names utf8;
--disable_warnings
create table t1 (a varchar(30) not null primary key)
engine=innodb default character set utf8 collate utf8_bin;
--enable_warnings
insert into t1 values ('あいうえおかきくけこさしすせそ');
insert into t1 values ('さしすせそかきくけこあいうえお');
select a as bin1 from t1 where a like 'さしすせそかきくけこあいうえお%';
select a as bin2 from t1 where a like 'あいうえおかきくけこさしすせそ';
drop table t1;
#
# Bug#14896: Comparison with a key in a partial index over mb chararacter field
#

View file

@ -23,7 +23,6 @@ ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t
#ndb_binlog_ignore_db : BUG#21279 2006-07-25 ingo Randomly throws a warning
ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
ps : BUG#21524 2006-08-08 pgalbraith 'ps' test fails in --ps-protocol test AMD64 bit
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 Seems to pass currently

View file

@ -32,7 +32,6 @@ select grp,group_concat(d order by a desc) from t1 group by grp;
select grp,group_concat(a order by a,d+c-ascii(c)-a) from t1 group by grp;
select grp,group_concat(a order by d+c-ascii(c),a) from t1 group by grp;
select grp,group_concat(c order by 1) from t1 group by grp;
select grp,group_concat(c order by "c") from t1 group by grp;
select grp,group_concat(distinct c order by c) from t1 group by grp;
select grp,group_concat(distinct c order by c desc) from t1 group by grp;
explain extended select grp,group_concat(distinct c order by c desc) from t1 group by grp;

View file

@ -231,4 +231,14 @@ INSERT INTO t1 (c1) VALUES (
CHECK TABLE t1 EXTENDED;
DROP TABLE t1;
#
# Bug #21888: Query on GEOMETRY field using PointFromWKB() results in lost connection
#
CREATE TABLE t1 (foo GEOMETRY NOT NULL, SPATIAL INDEX(foo) );
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(1,1)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(1,0)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(0,1)));
INSERT INTO t1 (foo) VALUES (PointFromWKB(POINT(0,0)));
SELECT 1 FROM t1 WHERE foo != PointFromWKB(POINT(0,0));
DROP TABLE t1;
# End of 4.1 tests

View file

@ -609,6 +609,30 @@ select sql_buffer_result max(f1) is null from t1;
select sql_buffer_result max(f1)+1 from t1;
drop table t1;
#
# BUG#14019-4.1-opt
#
CREATE TABLE t1(a INT); INSERT INTO t1 VALUES (1),(2);
SELECT a FROM t1 GROUP BY 'a';
SELECT a FROM t1 GROUP BY "a";
SELECT a FROM t1 GROUP BY `a`;
set sql_mode=ANSI_QUOTES;
SELECT a FROM t1 GROUP BY "a";
SELECT a FROM t1 GROUP BY 'a';
SELECT a FROM t1 GROUP BY `a`;
set sql_mode='';
SELECT a FROM t1 HAVING 'a' > 1;
SELECT a FROM t1 HAVING "a" > 1;
SELECT a FROM t1 HAVING `a` > 1;
SELECT a FROM t1 ORDER BY 'a' DESC;
SELECT a FROM t1 ORDER BY "a" DESC;
SELECT a FROM t1 ORDER BY `a` DESC;
DROP TABLE t1;
# End of 4.1 tests
#
@ -656,6 +680,28 @@ where t2.b=v1.a GROUP BY t2.b;
DROP VIEW v1;
DROP TABLE t1,t2;
#
# Bug#22781: SQL_BIG_RESULT fails to influence sort plan
#
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, key (b));
INSERT INTO t1 VALUES (1, 1);
INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20) FROM t1;
INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20) FROM t1;
INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20) FROM t1;
INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20) FROM t1;
INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20) FROM t1;
INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20) FROM t1;
INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20) FROM t1;
SELECT MIN(b), MAX(b) from t1;
EXPLAIN SELECT b, sum(1) FROM t1 GROUP BY b;
EXPLAIN SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b;
SELECT b, sum(1) FROM t1 GROUP BY b;
SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b;
DROP TABLE t1;
#
# Bug #21174: Index degrades sort performance and
# optimizer does not honor IGNORE INDEX

View file

@ -819,3 +819,19 @@ SELECT * FROM
t1;
DROP TABLE t1,t2,t3,t4,t5,t6;
#
# Bug#22342: No results returned for query using max and group by
#
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b), KEY b (b));
INSERT INTO t1 VALUES (1,1),(1,2),(1,0),(1,3);
explain SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
SELECT MIN(b), a FROM t1 WHERE b > 1 AND a = 1 GROUP BY a;
CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c));
INSERT INTO t2 SELECT a,b,b FROM t1;
explain SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
DROP TABLE t1,t2;

View file

@ -755,6 +755,97 @@ SELECT * FROM t1;
DROP TABLE t1;
#
# Bug#8283 - OPTIMIZE TABLE causes data loss
#
SET @@myisam_repair_threads=2;
SHOW VARIABLES LIKE 'myisam_repair%';
#
# Test OPTIMIZE. This creates a new data file.
CREATE TABLE t1 (
`_id` int(11) NOT NULL default '0',
`url` text,
`email` text,
`description` text,
`loverlap` int(11) default NULL,
`roverlap` int(11) default NULL,
`lneighbor_id` int(11) default NULL,
`rneighbor_id` int(11) default NULL,
`length_` int(11) default NULL,
`sequence` mediumtext,
`name` text,
`_obj_class` text NOT NULL,
PRIMARY KEY (`_id`),
UNIQUE KEY `sequence_name_index` (`name`(50)),
KEY (`length_`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
#
INSERT INTO t1 VALUES
(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''),
(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''),
(3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample3',''),
(4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample4',''),
(5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample5',''),
(6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample6',''),
(7,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample7',''),
(8,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample8',''),
(9,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample9','');
#
SELECT _id FROM t1;
DELETE FROM t1 WHERE _id < 8;
--replace_column 6 # 7 # 8 # 9 # 11 # 12 # 13 # 14 # 15 # 16 #
SHOW TABLE STATUS LIKE 't1';
CHECK TABLE t1 EXTENDED;
OPTIMIZE TABLE t1;
CHECK TABLE t1 EXTENDED;
--replace_column 6 # 7 # 8 # 9 # 11 # 12 # 13 # 14 # 15 # 16 #
SHOW TABLE STATUS LIKE 't1';
SELECT _id FROM t1;
DROP TABLE t1;
#
# Test REPAIR QUICK. This retains the old data file.
CREATE TABLE t1 (
`_id` int(11) NOT NULL default '0',
`url` text,
`email` text,
`description` text,
`loverlap` int(11) default NULL,
`roverlap` int(11) default NULL,
`lneighbor_id` int(11) default NULL,
`rneighbor_id` int(11) default NULL,
`length_` int(11) default NULL,
`sequence` mediumtext,
`name` text,
`_obj_class` text NOT NULL,
PRIMARY KEY (`_id`),
UNIQUE KEY `sequence_name_index` (`name`(50)),
KEY (`length_`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
#
INSERT INTO t1 VALUES
(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''),
(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''),
(3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample3',''),
(4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample4',''),
(5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample5',''),
(6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample6',''),
(7,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample7',''),
(8,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample8',''),
(9,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample9','');
#
SELECT _id FROM t1;
DELETE FROM t1 WHERE _id < 8;
--replace_column 6 # 7 # 8 # 9 # 11 # 12 # 13 # 14 # 15 # 16 #
SHOW TABLE STATUS LIKE 't1';
CHECK TABLE t1 EXTENDED;
REPAIR TABLE t1 QUICK;
CHECK TABLE t1 EXTENDED;
--replace_column 6 # 7 # 8 # 9 # 11 # 12 # 13 # 14 # 15 # 16 #
SHOW TABLE STATUS LIKE 't1';
SELECT _id FROM t1;
DROP TABLE t1;
#
SET @@myisam_repair_threads=1;
SHOW VARIABLES LIKE 'myisam_repair%';
# Test varchar
#

View file

@ -283,6 +283,15 @@ select a, max(b) from t1 group by a with rollup;
select distinct a, max(b) from t1 group by a with rollup;
drop table t1;
#
# Bug #20825: rollup puts non-equal values together
#
create table t1 (a varchar(22) not null , b int);
insert into t1 values ("2006-07-01 21:30", 1), ("2006-07-01 23:30", 10);
select left(a,10), a, sum(b) from t1 group by 1,2 with rollup;
select left(a,10) x, a, sum(b) from t1 group by x,a with rollup;
drop table t1;
# End of 4.1 tests
#
@ -318,4 +327,3 @@ SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
# End of 4.1 tests

View file

@ -354,14 +354,14 @@ create table t1 (a int, b int);
insert into t1 (a, b) values (1,1), (1,2), (2,1), (2,2);
prepare stmt from
"explain select * from t1 where t1.a=2 and t1.a=t1.b and t1.b > 1 + ?";
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=5;
execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
execute stmt using @v;
set @v=0;
execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
execute stmt using @v;
set @v=5;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
execute stmt using @v;
drop table t1;
deallocate prepare stmt;
@ -1447,13 +1447,15 @@ create procedure proc_1() reset query cache;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset query cache; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
drop procedure proc_1;
prepare abc from "reset query cache";
execute abc;
execute abc;
@ -1462,13 +1464,15 @@ deallocate prepare abc;
create procedure proc_1() reset master;
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset master; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
drop procedure proc_1;
prepare abc from "reset master";
execute abc;
execute abc;
@ -1480,13 +1484,15 @@ create procedure proc_1() reset slave;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin reset slave; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
drop procedure proc_1;
prepare abc from "reset slave";
execute abc;
execute abc;
@ -1527,15 +1533,15 @@ call proc_1();
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush hosts; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush hosts";
execute abc;
execute abc;
@ -1547,15 +1553,15 @@ create procedure proc_1() flush privileges;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush privileges; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush privileges";
deallocate prepare abc;
@ -1567,11 +1573,15 @@ call proc_1();
unlock tables;
call proc_1();
unlock tables;
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables with read lock; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
drop function func_1;
drop procedure proc_1;
prepare abc from "flush tables with read lock";
execute abc;
execute abc;
@ -1584,15 +1594,15 @@ create procedure proc_1() flush tables;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush tables";
execute abc;
execute abc;
@ -1622,15 +1632,15 @@ select Host, User from mysql.user limit 0;
select Host, Db from mysql.host limit 0;
show open tables from mysql;
flush tables;
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush tables; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
flush tables;
select Host, User from mysql.user limit 0;
select Host, Db from mysql.host limit 0;
@ -1659,15 +1669,15 @@ create procedure proc_1() flush logs;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush logs; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush logs";
execute abc;
execute abc;
@ -1679,15 +1689,15 @@ create procedure proc_1() flush status;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush status; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush status";
execute abc;
execute abc;
@ -1699,15 +1709,15 @@ create procedure proc_1() flush slave;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush slave; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush slave";
execute abc;
execute abc;
@ -1716,15 +1726,15 @@ deallocate prepare abc;
create procedure proc_1() flush master;
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush master; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush master";
deallocate prepare abc;
@ -1733,15 +1743,15 @@ create procedure proc_1() flush des_key_file;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush des_key_file; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush des_key_file";
execute abc;
execute abc;
@ -1753,15 +1763,15 @@ create procedure proc_1() flush user_resources;
call proc_1();
call proc_1();
call proc_1();
drop procedure proc_1;
delimiter |;
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function func_1() returns int begin flush user_resources; return 1; end|
create function func_1() returns int begin call proc_1(); return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
drop procedure proc_1;
prepare abc from "flush user_resources";
execute abc;
execute abc;
@ -1865,22 +1875,6 @@ execute abc;
deallocate prepare abc;
create procedure proc_1() show scheduler status;
drop procedure proc_1;
delimiter |;
--error ER_SP_NO_RETSET
create function func_1() returns int begin show scheduler status; return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST
select func_1(), func_1(), func_1() from dual;
--error ER_SP_DOES_NOT_EXIST
drop function func_1;
--error ER_UNSUPPORTED_PS
prepare abc from "show scheduler status";
--error ER_UNKNOWN_STMT_HANDLER
deallocate prepare abc;
--disable_warnings
drop procedure if exists a;
--enable_warnings
@ -1997,10 +1991,13 @@ call proc_1();
call proc_1();
drop procedure proc_1;
create procedure proc_1() install plugin my_plug soname 'some_plugin.so';
--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
--replace_regex /(Can\'t open shared library).*$/\1/
--error ER_CANT_OPEN_LIBRARY
call proc_1();
drop procedure proc_1;
@ -2150,7 +2147,7 @@ drop event if exists xyz;
#drop event xyz;
#drop procedure proc_1;
delimiter |;
--error ER_SP_NO_RETSET
--error ER_EVENT_RECURSIVITY_FORBIDDEN
create function func_1() returns int begin create event xyz on schedule at now() do select 123; return 1; end|
delimiter ;|
--error ER_SP_DOES_NOT_EXIST

View file

@ -72,4 +72,17 @@ disconnect con2;
disconnect con1;
connection default;
#
# Bug#14959: ALTER TABLE isn't able to rename a view
#
create table t1(f1 int);
create view v1 as select * from t1;
alter table v1 rename to v2;
--error 1146
alter table v1 rename to v2;
rename table v2 to v1;
--error 1050
rename table v2 to v1;
drop view v1;
drop table t1;
# End of 4.1 tests

View file

@ -45,6 +45,44 @@ SHOW INDEX FROM t1;
SET myisam_repair_threads=@@global.myisam_repair_threads;
DROP TABLE t1;
#
# BUG#22562 - REPAIR TABLE .. USE_FRM causes server crash on Windows and
# server hangs on Linux
#
CREATE TABLE t1(a INT);
USE mysql;
REPAIR TABLE test.t1 USE_FRM;
USE test;
DROP TABLE t1;
#
# BUG#23175 - MYISAM crash/repair failed during repair
#
CREATE TABLE t1(a CHAR(255), KEY(a));
SET myisam_sort_buffer_size=4096;
INSERT INTO t1 VALUES
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0');
SET myisam_repair_threads=2;
REPAIR TABLE t1;
SET myisam_repair_threads=@@global.myisam_repair_threads;
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
DROP TABLE t1;
# End of 4.1 tests
# End of 5.0 tests

View file

@ -2997,5 +2997,99 @@ SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
SELECT * FROM t1 LEFT JOIN t2 ON t2.b=t1.a INNER JOIN t3 ON t3.d=t1.id
WHERE t1.id=2;
DROP TABLE t1,t2,t3;
#
# Bug#20503: Server crash due to the ORDER clause isn't taken into account
# while space allocation
#
create table t1 (c1 varchar(1), c2 int, c3 int, c4 int, c5 int, c6 int,
c7 int, c8 int, c9 int, fulltext key (`c1`));
select distinct match (`c1`) against ('z') , c2, c3, c4,c5, c6,c7, c8
from t1 where c9=1 order by c2, c2;
drop table t1;
#
# Bug #22735: no equality propagation for BETWEEN and IN with STRING arguments
#
CREATE TABLE t1 (pk varchar(10) PRIMARY KEY, fk varchar(16));
CREATE TABLE t2 (pk varchar(16) PRIMARY KEY, fk varchar(10));
INSERT INTO t1 VALUES
('d','dddd'), ('i','iii'), ('a','aa'), ('b','bb'), ('g','gg'),
('e','eee'), ('c','cccc'), ('h','hhh'), ('j','jjj'), ('f','fff');
INSERT INTO t2 VALUES
('jjj', 'j'), ('cc','c'), ('ccc','c'), ('aaa', 'a'), ('jjjj','j'),
('hhh','h'), ('gg','g'), ('fff','f'), ('ee','e'), ('ffff','f'),
('bbb','b'), ('ff','f'), ('cccc','c'), ('dddd','d'), ('jj','j'),
('aaaa','a'), ('bb','b'), ('eeee','e'), ('aa','a'), ('hh','h');
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk < 'c' AND t2.pk=t1.fk;
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
DROP TABLE t1,t2;
#
# Bug #22367: Optimizer uses ref join type instead of eq_ref for simple
# join on strings
#
CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
CREATE TABLE t2 (a int, b varchar(20) NOT NULL,
PRIMARY KEY (a), UNIQUE KEY (b));
INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c');
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
EXPLAIN SELECT t1.a FROM t1 LEFT JOIN t2 ON t2.b=t1.b WHERE t1.a=3;
DROP TABLE t1,t2;
#
# Bug #19579: predicates that become sargable after reading const tables
# are not taken into account by optimizer
#
CREATE TABLE t1(id int PRIMARY KEY, b int, e int);
CREATE TABLE t2(i int, a int, INDEX si(i), INDEX ai(a));
CREATE TABLE t3(a int PRIMARY KEY, c char(4), INDEX ci(c));
INSERT INTO t1 VALUES
(1,10,19), (2,20,22), (4,41,42), (9,93,95), (7, 77,79),
(6,63,67), (5,55,58), (3,38,39), (8,81,89);
INSERT INTO t2 VALUES
(21,210), (41,410), (82,820), (83,830), (84,840),
(65,650), (51,510), (37,370), (94,940), (76,760),
(22,220), (33,330), (40,400), (95,950), (38,380),
(67,670), (88,880), (57,570), (96,960), (97,970);
INSERT INTO t3 VALUES
(210,'bb'), (950,'ii'), (400,'ab'), (500,'ee'), (220,'gg'),
(440,'gg'), (310,'eg'), (380,'ee'), (840,'bb'), (830,'ff'),
(230,'aa'), (960,'ii'), (410,'aa'), (510,'ee'), (290,'bb'),
(450,'gg'), (320,'dd'), (390,'hh'), (850,'jj'), (860,'ff');
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
EXPLAIN
SELECT t3.a FROM t1,t2,t3
WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
DROP TABLE t1,t2,t3;

View file

@ -2370,6 +2370,32 @@ explain select * from t1 where not exists
DROP TABLE t1;
#
# Bug#21798: memory leak during query execution with subquery in column
# list using a function
#
CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b));
insert into t1 (a) values (FLOOR(rand() * 100));
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
insert into t1 (a) select FLOOR(rand() * 100) from t1;
SELECT a,
(SELECT REPEAT(' ',250) FROM t1 i1
WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a
FROM t1 ORDER BY a LIMIT 5;
DROP TABLE t1;
#
# Bug #21540: Subqueries with no from and aggregate functions return
# wrong results

View file

@ -385,3 +385,12 @@ insert into t1 values (40);
flush tables;
select f1 from t1 where f1 in (select f1 from t1);
drop table t1;
#
# Bug#22183: Unhandled NULL caused server crash
#
create table t1 as
select from_days(s) as date,t
from (select 1 as s,'t' as t union select null, null ) as sub1;
select group_concat(t) from t1 group by week(date)/10;
drop table t1;

View file

@ -127,4 +127,13 @@ create table t1 (a set('x','y') default 'x');
alter table t1 alter a set default 'z';
drop table t1;
#
# Bug#20922 mysql removes a name of first column in a table
#
create table t1 (f1 int);
alter table t1 add f2 enum(0xFFFF);
show create table t1;
drop table t1;
# End of 4.1 tests

View file

@ -2884,4 +2884,19 @@ SHOW CREATE VIEW v1;
DROP VIEW v1;
DROP TABLE t1, t2;
#
# Bug #16813 (WITH CHECK OPTION doesn't work with UPDATE)
#
CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL);
CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION;
INSERT INTO v1 (val) VALUES (2);
INSERT INTO v1 (val) VALUES (4);
-- error 1369
INSERT INTO v1 (val) VALUES (6);
-- error 1369
UPDATE v1 SET val=6 WHERE id=2;
DROP VIEW v1;
DROP TABLE t1;
--echo End of 5.0 tests.

View file

@ -70,7 +70,6 @@ static void my_aiowait(my_aio_result *result);
#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
/*
Setup internal pointers inside IO_CACHE
@ -502,65 +501,366 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
DBUG_RETURN(0);
}
#ifdef THREAD
/* Prepare IO_CACHE for shared use */
void init_io_cache_share(IO_CACHE *info, IO_CACHE_SHARE *s, uint num_threads)
/*
Prepare IO_CACHE for shared use.
SYNOPSIS
init_io_cache_share()
read_cache A read cache. This will be copied for
every thread after setup.
cshare The share.
write_cache If non-NULL a write cache that is to be
synchronized with the read caches.
num_threads Number of threads sharing the cache
including the write thread if any.
DESCRIPTION
The shared cache is used so: One IO_CACHE is initialized with
init_io_cache(). This includes the allocation of a buffer. Then a
share is allocated and init_io_cache_share() is called with the io
cache and the share. Then the io cache is copied for each thread. So
every thread has its own copy of IO_CACHE. But the allocated buffer
is shared because cache->buffer is the same for all caches.
One thread reads data from the file into the buffer. All threads
read from the buffer, but every thread maintains its own set of
pointers into the buffer. When all threads have used up the buffer
contents, one of the threads reads the next block of data into the
buffer. To accomplish this, each thread enters the cache lock before
accessing the buffer. They wait in lock_io_cache() until all threads
joined the lock. The last thread entering the lock is in charge of
reading from file to buffer. It wakes all threads when done.
Synchronizing a write cache to the read caches works so: Whenever
the write buffer needs a flush, the write thread enters the lock and
waits for all other threads to enter the lock too. They do this when
they have used up the read buffer. When all threads are in the lock,
the write thread copies the write buffer to the read buffer and
wakes all threads.
share->running_threads is the number of threads not being in the
cache lock. When entering lock_io_cache() the number is decreased.
When the thread that fills the buffer enters unlock_io_cache() the
number is reset to the number of threads. The condition
running_threads == 0 means that all threads are in the lock. Bumping
up the number to the full count is non-intuitive. But increasing the
number by one for each thread that leaves the lock could lead to a
solo run of one thread. The last thread to join a lock reads from
file to buffer, wakes the other threads, processes the data in the
cache and enters the lock again. If no other thread left the lock
meanwhile, it would think it's the last one again and read the next
block...
The share has copies of 'error', 'buffer', 'read_end', and
'pos_in_file' from the thread that filled the buffer. We may not be
able to access this information directly from its cache because the
thread may be removed from the share before the variables could be
copied by all other threads. Or, if a write buffer is synchronized,
it would change its 'pos_in_file' after waking the other threads,
possibly before they could copy its value.
However, the 'buffer' variable in the share is for a synchronized
write cache. It needs to know where to put the data. Otherwise it
would need access to the read cache of one of the threads that is
not yet removed from the share.
RETURN
void
*/
void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
IO_CACHE *write_cache, uint num_threads)
{
DBUG_ASSERT(info->type == READ_CACHE);
pthread_mutex_init(&s->mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init (&s->cond, 0);
s->total=s->count=num_threads-1;
s->active=0;
info->share=s;
info->read_function=_my_b_read_r;
info->current_pos= info->current_end= 0;
DBUG_ENTER("init_io_cache_share");
DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx "
"write_cache: 0x%lx threads: %u",
read_cache, cshare, write_cache, num_threads));
DBUG_ASSERT(num_threads > 1);
DBUG_ASSERT(read_cache->type == READ_CACHE);
DBUG_ASSERT(!write_cache || (write_cache->type == WRITE_CACHE));
pthread_mutex_init(&cshare->mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&cshare->cond, 0);
pthread_cond_init(&cshare->cond_writer, 0);
cshare->running_threads= num_threads;
cshare->total_threads= num_threads;
cshare->error= 0; /* Initialize. */
cshare->buffer= read_cache->buffer;
cshare->read_end= NULL; /* See function comment of lock_io_cache(). */
cshare->pos_in_file= 0; /* See function comment of lock_io_cache(). */
cshare->source_cache= write_cache; /* Can be NULL. */
read_cache->share= cshare;
read_cache->read_function= _my_b_read_r;
read_cache->current_pos= NULL;
read_cache->current_end= NULL;
if (write_cache)
write_cache->share= cshare;
DBUG_VOID_RETURN;
}
/*
Remove a thread from shared access to IO_CACHE
Every thread should do that on exit for not
to deadlock other threads
Remove a thread from shared access to IO_CACHE.
SYNOPSIS
remove_io_thread()
cache The IO_CACHE to be removed from the share.
NOTE
Every thread must do that on exit for not to deadlock other threads.
The last thread destroys the pthread resources.
A writer flushes its cache first.
RETURN
void
*/
void remove_io_thread(IO_CACHE *info)
void remove_io_thread(IO_CACHE *cache)
{
IO_CACHE_SHARE *s=info->share;
IO_CACHE_SHARE *cshare= cache->share;
uint total;
DBUG_ENTER("remove_io_thread");
pthread_mutex_lock(&s->mutex);
s->total--;
if (! s->count--)
pthread_cond_signal(&s->cond);
pthread_mutex_unlock(&s->mutex);
}
/* If the writer goes, it needs to flush the write cache. */
if (cache == cshare->source_cache)
flush_io_cache(cache);
static int lock_io_cache(IO_CACHE *info, my_off_t pos)
{
int total;
IO_CACHE_SHARE *s=info->share;
pthread_mutex_lock(&cshare->mutex);
DBUG_PRINT("io_cache_share", ("%s: 0x%lx",
(cache == cshare->source_cache) ?
"writer" : "reader", cache));
pthread_mutex_lock(&s->mutex);
if (!s->count)
/* Remove from share. */
total= --cshare->total_threads;
DBUG_PRINT("io_cache_share", ("remaining threads: %u", total));
/* Detach from share. */
cache->share= NULL;
/* If the writer goes, let the readers know. */
if (cache == cshare->source_cache)
{
s->count=s->total;
return 1;
DBUG_PRINT("io_cache_share", ("writer leaves"));
cshare->source_cache= NULL;
}
total=s->total;
s->count--;
while (!s->active || s->active->pos_in_file < pos)
pthread_cond_wait(&s->cond, &s->mutex);
/* If all threads are waiting for me to join the lock, wake them. */
if (!--cshare->running_threads)
{
DBUG_PRINT("io_cache_share", ("the last running thread leaves, wake all"));
pthread_cond_signal(&cshare->cond_writer);
pthread_cond_broadcast(&cshare->cond);
}
if (s->total < total &&
(!s->active || s->active->pos_in_file < pos))
return 1;
pthread_mutex_unlock(&cshare->mutex);
pthread_mutex_unlock(&s->mutex);
return 0;
if (!total)
{
DBUG_PRINT("io_cache_share", ("last thread removed, destroy share"));
pthread_cond_destroy (&cshare->cond_writer);
pthread_cond_destroy (&cshare->cond);
pthread_mutex_destroy(&cshare->mutex);
}
DBUG_VOID_RETURN;
}
static void unlock_io_cache(IO_CACHE *info)
/*
Lock IO cache and wait for all other threads to join.
SYNOPSIS
lock_io_cache()
cache The cache of the thread entering the lock.
pos File position of the block to read.
Unused for the write thread.
DESCRIPTION
Wait for all threads to finish with the current buffer. We want
all threads to proceed in concert. The last thread to join
lock_io_cache() will read the block from file and all threads start
to use it. Then they will join again for reading the next block.
The waiting threads detect a fresh buffer by comparing
cshare->pos_in_file with the position they want to process next.
Since the first block may start at position 0, we take
cshare->read_end as an additional condition. This variable is
initialized to NULL and will be set after a block of data is written
to the buffer.
RETURN
1 OK, lock in place, go ahead and read.
0 OK, unlocked, another thread did the read.
*/
static int lock_io_cache(IO_CACHE *cache, my_off_t pos)
{
pthread_cond_broadcast(&info->share->cond);
pthread_mutex_unlock(&info->share->mutex);
IO_CACHE_SHARE *cshare= cache->share;
DBUG_ENTER("lock_io_cache");
/* Enter the lock. */
pthread_mutex_lock(&cshare->mutex);
cshare->running_threads--;
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
"writer" : "reader", cache, (ulong) pos,
cshare->running_threads));
if (cshare->source_cache)
{
/* A write cache is synchronized to the read caches. */
if (cache == cshare->source_cache)
{
/* The writer waits until all readers are here. */
while (cshare->running_threads)
{
DBUG_PRINT("io_cache_share", ("writer waits in lock"));
pthread_cond_wait(&cshare->cond_writer, &cshare->mutex);
}
DBUG_PRINT("io_cache_share", ("writer awoke, going to copy"));
/* Stay locked. Leave the lock later by unlock_io_cache(). */
DBUG_RETURN(1);
}
/* The last thread wakes the writer. */
if (!cshare->running_threads)
{
DBUG_PRINT("io_cache_share", ("waking writer"));
pthread_cond_signal(&cshare->cond_writer);
}
/*
Readers wait until the data is copied from the writer. Another
reason to stop waiting is the removal of the write thread. If this
happens, we leave the lock with old data in the buffer.
*/
while ((!cshare->read_end || (cshare->pos_in_file < pos)) &&
cshare->source_cache)
{
DBUG_PRINT("io_cache_share", ("reader waits in lock"));
pthread_cond_wait(&cshare->cond, &cshare->mutex);
}
/*
If the writer was removed from the share while this thread was
asleep, we need to simulate an EOF condition. The writer cannot
reset the share variables as they might still be in use by readers
of the last block. When we awake here then because the last
joining thread signalled us. If the writer is not the last, it
will not signal. So it is safe to clear the buffer here.
*/
if (!cshare->read_end || (cshare->pos_in_file < pos))
{
DBUG_PRINT("io_cache_share", ("reader found writer removed. EOF"));
cshare->read_end= cshare->buffer; /* Empty buffer. */
cshare->error= 0; /* EOF is not an error. */
}
}
else
{
/*
There are read caches only. The last thread arriving in
lock_io_cache() continues with a locked cache and reads the block.
*/
if (!cshare->running_threads)
{
DBUG_PRINT("io_cache_share", ("last thread joined, going to read"));
/* Stay locked. Leave the lock later by unlock_io_cache(). */
DBUG_RETURN(1);
}
/*
All other threads wait until the requested block is read by the
last thread arriving. Another reason to stop waiting is the
removal of a thread. If this leads to all threads being in the
lock, we have to continue also. The first of the awaken threads
will then do the read.
*/
while ((!cshare->read_end || (cshare->pos_in_file < pos)) &&
cshare->running_threads)
{
DBUG_PRINT("io_cache_share", ("reader waits in lock"));
pthread_cond_wait(&cshare->cond, &cshare->mutex);
}
/* If the block is not yet read, continue with a locked cache and read. */
if (!cshare->read_end || (cshare->pos_in_file < pos))
{
DBUG_PRINT("io_cache_share", ("reader awoke, going to read"));
/* Stay locked. Leave the lock later by unlock_io_cache(). */
DBUG_RETURN(1);
}
/* Another thread did read the block already. */
}
DBUG_PRINT("io_cache_share", ("reader awoke, going to process %u bytes",
cshare->read_end ? (uint)
(cshare->read_end - cshare->buffer) : 0));
/*
Leave the lock. Do not call unlock_io_cache() later. The thread that
filled the buffer did this and marked all threads as running.
*/
pthread_mutex_unlock(&cshare->mutex);
DBUG_RETURN(0);
}
/*
Unlock IO cache.
SYNOPSIS
unlock_io_cache()
cache The cache of the thread leaving the lock.
NOTE
This is called by the thread that filled the buffer. It marks all
threads as running and awakes them. This must not be done by any
other thread.
Do not signal cond_writer. Either there is no writer or the writer
is the only one who can call this function.
The reason for resetting running_threads to total_threads before
waking all other threads is that it could be possible that this
thread is so fast with processing the buffer that it enters the lock
before even one other thread has left it. If every awoken thread
would increase running_threads by one, this thread could think that
he is again the last to join and would not wait for the other
threads to process the data.
RETURN
void
*/
static void unlock_io_cache(IO_CACHE *cache)
{
IO_CACHE_SHARE *cshare= cache->share;
DBUG_ENTER("unlock_io_cache");
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
"writer" : "reader",
cache, (ulong) cshare->pos_in_file,
cshare->total_threads));
cshare->running_threads= cshare->total_threads;
pthread_cond_broadcast(&cshare->cond);
pthread_mutex_unlock(&cshare->mutex);
DBUG_VOID_RETURN;
}
@ -569,7 +869,7 @@ static void unlock_io_cache(IO_CACHE *info)
SYNOPSIS
_my_b_read_r()
info IO_CACHE pointer
cache IO_CACHE pointer
Buffer Buffer to retrieve count bytes from file
Count Number of bytes to read into Buffer
@ -581,7 +881,7 @@ static void unlock_io_cache(IO_CACHE *info)
It works as follows: when a thread tries to read from a file (that
is, after using all the data from the (shared) buffer), it just
hangs on lock_io_cache(), wating for other threads. When the very
hangs on lock_io_cache(), waiting for other threads. When the very
last thread attempts a read, lock_io_cache() returns 1, the thread
does actual IO and unlock_io_cache(), which signals all the waiting
threads that data is in the buffer.
@ -601,16 +901,17 @@ static void unlock_io_cache(IO_CACHE *info)
1 Error: can't read requested characters
*/
int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count)
{
my_off_t pos_in_file;
uint length, diff_length, left_length;
IO_CACHE_SHARE *cshare= cache->share;
DBUG_ENTER("_my_b_read_r");
if ((left_length= (uint) (info->read_end - info->read_pos)))
if ((left_length= (uint) (cache->read_end - cache->read_pos)))
{
DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */
memcpy(Buffer, info->read_pos, (size_t) (left_length));
memcpy(Buffer, cache->read_pos, (size_t) (left_length));
Buffer+= left_length;
Count-= left_length;
}
@ -618,55 +919,133 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
{
int cnt, len;
pos_in_file= info->pos_in_file + (info->read_end - info->buffer);
pos_in_file= cache->pos_in_file + (cache->read_end - cache->buffer);
diff_length= (uint) (pos_in_file & (IO_SIZE-1));
length=IO_ROUND_UP(Count+diff_length)-diff_length;
length=(length <= info->read_length) ?
length + IO_ROUND_DN(info->read_length - length) :
length - IO_ROUND_UP(length - info->read_length) ;
if (info->type != READ_FIFO &&
(length > (info->end_of_file - pos_in_file)))
length= (uint) (info->end_of_file - pos_in_file);
length= ((length <= cache->read_length) ?
length + IO_ROUND_DN(cache->read_length - length) :
length - IO_ROUND_UP(length - cache->read_length));
if (cache->type != READ_FIFO &&
(length > (cache->end_of_file - pos_in_file)))
length= (uint) (cache->end_of_file - pos_in_file);
if (length == 0)
{
info->error= (int) left_length;
cache->error= (int) left_length;
DBUG_RETURN(1);
}
if (lock_io_cache(info, pos_in_file))
if (lock_io_cache(cache, pos_in_file))
{
info->share->active=info;
if (info->seek_not_done) /* File touched, do seek */
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
len=(int)my_read(info->file,info->buffer, length, info->myflags);
info->read_end=info->buffer + (len == -1 ? 0 : len);
info->error=(len == (int)length ? 0 : len);
info->pos_in_file=pos_in_file;
unlock_io_cache(info);
/* With a synchronized write/read cache we won't come here... */
DBUG_ASSERT(!cshare->source_cache);
/*
... unless the writer has gone before this thread entered the
lock. Simulate EOF in this case. It can be distinguished by
cache->file.
*/
if (cache->file < 0)
len= 0;
else
{
if (cache->seek_not_done) /* File touched, do seek */
VOID(my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0)));
len= (int) my_read(cache->file, cache->buffer, length, cache->myflags);
}
DBUG_PRINT("io_cache_share", ("read %d bytes", len));
cache->read_end= cache->buffer + (len == -1 ? 0 : len);
cache->error= (len == (int)length ? 0 : len);
cache->pos_in_file= pos_in_file;
/* Copy important values to the share. */
cshare->error= cache->error;
cshare->read_end= cache->read_end;
cshare->pos_in_file= pos_in_file;
/* Mark all threads as running and wake them. */
unlock_io_cache(cache);
}
else
{
info->error= info->share->active->error;
info->read_end= info->share->active->read_end;
info->pos_in_file= info->share->active->pos_in_file;
len= (int) (info->error == -1 ? -1 : info->read_end-info->buffer);
/*
With a synchronized write/read cache readers always come here.
Copy important values from the share.
*/
cache->error= cshare->error;
cache->read_end= cshare->read_end;
cache->pos_in_file= cshare->pos_in_file;
len= (int) ((cache->error == -1) ? -1 : cache->read_end - cache->buffer);
}
info->read_pos=info->buffer;
info->seek_not_done=0;
cache->read_pos= cache->buffer;
cache->seek_not_done= 0;
if (len <= 0)
{
info->error= (int) left_length;
DBUG_PRINT("io_cache_share", ("reader error. len %d left %u",
len, left_length));
cache->error= (int) left_length;
DBUG_RETURN(1);
}
cnt= ((uint) len > Count) ? (int) Count : len;
memcpy(Buffer, info->read_pos, (size_t) cnt);
memcpy(Buffer, cache->read_pos, (size_t) cnt);
Count -= cnt;
Buffer+= cnt;
left_length+= cnt;
info->read_pos+= cnt;
cache->read_pos+= cnt;
}
DBUG_RETURN(0);
}
#endif
/*
Copy data from write cache to read cache.
SYNOPSIS
copy_to_read_buffer()
write_cache The write cache.
write_buffer The source of data, mostly the cache buffer.
write_length The number of bytes to copy.
NOTE
The write thread will wait for all read threads to join the cache
lock. Then it copies the data over and wakes the read threads.
RETURN
void
*/
static void copy_to_read_buffer(IO_CACHE *write_cache,
const byte *write_buffer, uint write_length)
{
IO_CACHE_SHARE *cshare= write_cache->share;
DBUG_ASSERT(cshare->source_cache == write_cache);
/*
write_length is usually less or equal to buffer_length.
It can be bigger if _my_b_write() is called with a big length.
*/
while (write_length)
{
uint copy_length= min(write_length, write_cache->buffer_length);
int __attribute__((unused)) rc;
rc= lock_io_cache(write_cache, write_cache->pos_in_file);
/* The writing thread does always have the lock when it awakes. */
DBUG_ASSERT(rc);
memcpy(cshare->buffer, write_buffer, copy_length);
cshare->error= 0;
cshare->read_end= cshare->buffer + copy_length;
cshare->pos_in_file= write_cache->pos_in_file;
/* Mark all threads as running and wake them. */
unlock_io_cache(write_cache);
write_buffer+= copy_length;
write_length-= copy_length;
}
}
#endif /*THREAD*/
/*
@ -1018,6 +1397,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=rest_length;
Count-=rest_length;
info->write_pos+=rest_length;
if (my_b_flush_io_cache(info,1))
return 1;
if (Count >= IO_SIZE)
@ -1030,6 +1410,23 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
}
if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP))
return info->error= -1;
#ifdef THREAD
/*
In case of a shared I/O cache with a writer we normally do direct
write cache to read cache copy. Simulate this here by direct
caller buffer to read cache copy. Do it after the write so that
the cache readers actions on the flushed part can go in parallel
with the write of the extra stuff. copy_to_read_buffer()
synchronizes writer and readers so that after this call the
readers can act on the extra stuff while the writer can go ahead
and prepare the next output. copy_to_read_buffer() relies on
info->pos_in_file.
*/
if (info->share)
copy_to_read_buffer(info, Buffer, length);
#endif
Count-=length;
Buffer+=length;
info->pos_in_file+=length;
@ -1050,6 +1447,14 @@ int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count)
{
uint rest_length,length;
#ifdef THREAD
/*
Assert that we cannot come here with a shared cache. If we do one
day, we might need to add a call to copy_to_read_buffer().
*/
DBUG_ASSERT(!info->share);
#endif
lock_append_buffer(info);
rest_length=(uint) (info->write_end - info->write_pos);
if (Count <= rest_length)
@ -1110,6 +1515,14 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count,
uint length;
int error=0;
#ifdef THREAD
/*
Assert that we cannot come here with a shared cache. If we do one
day, we might need to add a call to copy_to_read_buffer().
*/
DBUG_ASSERT(!info->share);
#endif
if (pos < info->pos_in_file)
{
/* Of no overlap, write everything without buffering */
@ -1186,6 +1599,17 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
if ((length=(uint) (info->write_pos - info->write_buffer)))
{
#ifdef THREAD
/*
In case of a shared I/O cache with a writer we do direct write
cache to read cache copy. Do it before the write here so that
the readers can work in parallel with the write.
copy_to_read_buffer() relies on info->pos_in_file.
*/
if (info->share)
copy_to_read_buffer(info, info->write_buffer, length);
#endif
pos_in_file=info->pos_in_file;
/*
If we have append cache, we always open the file with
@ -1265,16 +1689,10 @@ int end_io_cache(IO_CACHE *info)
#ifdef THREAD
/*
if IO_CACHE is shared between several threads, only one
thread needs to call end_io_cache() - just as init_io_cache()
should be called only once and then memcopy'ed
Every thread must call remove_io_thread(). The last one destroys
the share elements.
*/
if (info->share)
{
pthread_cond_destroy(&info->share->cond);
pthread_mutex_destroy(&info->share->mutex);
info->share=0;
}
DBUG_ASSERT(!info->share || !info->share->total_threads);
#endif
if ((pre_close=info->pre_close))

View file

@ -15,8 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* To avoid problems with alarms in debug code, we disable DBUG here */
#undef DBUG_OFF
#define DBUG_OFF
#define FORCE_DBUG_OFF
#include <my_global.h>
#if defined(THREAD) && !defined(DONT_USE_THR_ALARM)

View file

@ -72,7 +72,7 @@ multiple read locks.
*/
#if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG)
#define DBUG_OFF
#define FORCE_DBUG_OFF
#endif
#include "mysys_priv.h"

View file

@ -5,8 +5,11 @@
# stop on errors
set -e
sed -e "s/^DIST_COMMON/#DIST_COMMON/g" storage/ndb/Makefile.am > storage/ndb/Makefile.am.$$
mv storage/ndb/Makefile.am.$$ storage/ndb/Makefile.am
for package in . ./storage/innobase
# for package in . ./storage/innobase
for package in .
do
(cd $package
rm -rf config.cache autom4te.cache
@ -14,6 +17,7 @@ do
autoheader
libtoolize --force
aclocal
# automake --verbose --add-missing --force-missing
automake --add-missing --force-missing
autoconf)
done

View file

@ -24,5 +24,4 @@ base_configs=" \
--prefix=N:/mysql \
--without-mysqlmanager \
--without-man \
--without-csv-storage-engine \
"

View file

@ -8,7 +8,7 @@ fi
# The base path(in wineformat) where compilers, includes and
# libraries are installed
if test -z $MYDEV
if test -z "$MYDEV"
then
# the default is "F:/mydev"
export MYDEV="F:/mydev"

View file

@ -151,17 +151,18 @@ echo "making files writable..."
cd $target_dir
chmod -R u+rw,g+rw .
# edit the mvenv file
echo "updating the mwenv environment file..."
## # edit the mvenv file
## echo "updating the mwenv environment file..."
mwenv="./netware/BUILD/mwenv"
mv -f $mwenv $mwenv.org
sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \
-e "s;BUILD_DIR;$build_dir;g" \
-e "s;VERSION;$version;g" $mwenv.org > $mwenv
chmod +rwx $mwenv
## mv -f $mwenv $mwenv.org
## sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \
## -e "s;BUILD_DIR;$build_dir;g" \
## -e "s;VERSION;$version;g" $mwenv.org > $mwenv
## chmod +rwx $mwenv
PWD=`pwd`
SRC_DIR=`grep "^export MYDEV=" $mwenv | cut -d'=' -f2 | \
# This line will catch the default value only, let's hope it is correct
SRC_DIR=`grep "^ *export MYDEV=" $mwenv | cut -d'=' -f2 | \
sed -e 's;";;g' -e "s;^;echo ;g" -e "s;$;/\`basename $PWD\`;g" | /bin/sh`

View file

@ -253,8 +253,8 @@ $CP mysql-test/t/*.test $BASE/mysql-test/t
$CP mysql-test/t/*.imtest mysql-test/t/*.disabled $BASE/mysql-test/t
$CP mysql-test/t/*.opt mysql-test/t/*.slave-mi $BASE/mysql-test/t
$CP mysql-test/t/*.sh mysql-test/t/*.sql $BASE/mysql-test/t
$CP mysql-test/r/*.result mysql-test/r/*.require \
$BASE/mysql-test/r
$CP mysql-test/r/*.result $BASE/mysql-test/r
$CP mysql-test/r/*.require $BASE/mysql-test/r
$CP mysql-test/extra/binlog_tests/*.test $BASE/mysql-test/extra/binlog_tests
$CP mysql-test/extra/rpl_tests/*.test $BASE/mysql-test/extra/rpl_tests
@ -326,14 +326,16 @@ fi
# NDB Cluster
if [ x$NDBCLUSTER = x1 ]; then
( cd storage/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
( cd mysql-test/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
( cd storage/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
( cd mysql-test ; @MAKE@ DESTDIR=$BASE/ndb-stage install )
$CP $BASE/ndb-stage@bindir@/* $BASE/bin/.
$CP $BASE/ndb-stage@libexecdir@/* $BASE/bin/.
$CP $BASE/ndb-stage@pkglibdir@/* $BASE/lib/.
test -d $BASE/include/storage || mkdir $BASE/include/storage
$CP -r $BASE/ndb-stage@pkgincludedir@/storage/ndb $BASE/include/storage/
$CP -r $BASE/ndb-stage@prefix@/mysql-test/ndb $BASE/mysql-test/. || exit 1
$CP -r $BASE/ndb-stage@prefix@/mysql-test/std_data/ndb_backup50 $BASE/mysql-test/std_data/. || exit 1
$CP -r $BASE/ndb-stage@prefix@/mysql-test/std_data/ndb_backup51 $BASE/mysql-test/std_data/. || exit 1
rm -rf $BASE/ndb-stage
fi

View file

@ -1,41 +1,227 @@
#! /bin/sh
#!/bin/sh
NOINST_NAME=$1
# Exit if failing to copy, we want exact specifications, not
# just "what happen to be built".
set -e
mkdir $NOINST_NAME
mkdir $NOINST_NAME/bin
cp client/release/*.exe $NOINST_NAME/bin/
cp extra/release/*.exe $NOINST_NAME/bin/
mv $NOINST_NAME/bin/comp_err.exe $NOINST_NAME/bin/comp-err.exe
cp storage/myisam/release/*.exe $NOINST_NAME/bin/
cp server-tools/instance-manager/release/*.exe $NOINST_NAME/bin/
cp tests/release/*.exe $NOINST_NAME/bin/
cp libmysql/release/*.exe $NOINST_NAME/bin/
cp libmysql/release/libmysql.dll $NOINST_NAME/bin/
# ----------------------------------------------------------------------
# Read first argument that is the base name of the resulting TAR file.
# See usage() function below for a description on the arguments.
#
# NOTE: We will read the rest of the command line later on.
# NOTE: Pattern matching with "{..,..}" can't be used, not portable.
# ----------------------------------------------------------------------
cp sql/release/mysqld.exe $NOINST_NAME/bin/mysqld.exe
cp sql/debug/mysqld.exe $NOINST_NAME/bin/mysqld-debug.exe
# For Pro/Classic builds, do this instead:
# cp sql/release/mysqld.exe $NOINST_NAME/bin/mysqld-nt.exe
# cp sql/debug/mysqld.exe $NOINST_NAME/bin/mysqld-debug.exe
# FIXME FIXME "debug", own build or handled here?
# FIXME FIXME add way to copy from other builds executables
cp COPYING EXCEPTIONS-CLIENT $NOINST_NAME/
cp -dpR win/data $NOINST_NAME/data
mkdir $NOINST_NAME/Docs
cp Docs/INSTALL-BINARY Docs/manual.chm ChangeLog COPYING $NOINST_NAME/Docs/
usage()
{
echo <<EOF
Usage: make_win_bin_dist [ options ] package-base-name [ copy-defs... ]
# These will be filled in when we enable embedded.
mkdir -p $NOINST_NAME/Embedded/DLL/debug $NOINST_NAME/Embedded/DLL/release $NOINST_NAME/Embedded/static/release
This is a script to run from the top of a source tree built on Windows.
The "package-base-name" argument should be something like
mkdir -p $NOINST_NAME/examples/libmysqltest/debug $NOINST_NAME/examples/libmysqltest/release
cp libmysql/mytest.c libmysql/myTest.vcproj libmysql/release/myTest.exe $NOINST_NAME/examples/libmysqltest/
cp libmysql/debug/myTest.exe $NOINST_NAME/examples/libmysqltest/debug/
cp libmysql/release/myTest.exe $NOINST_NAME/examples/libmysqltest/release/
mysql-noinstall-5.0.25-win32 (or winx64)
mkdir -p $NOINST_NAME/examples/tests
cp tests/*.res tests/*.tst tests/*.pl tests/*.c $NOINST_NAME/examples/tests/
and will be the name of the directory of the unpacked ZIP (stripping
away the "noinstall" part of the ZIP file name if any) and the base
for the resulting package name.
mkdir -p $NOINST_NAME/include
Options are
--embedded Pack the embedded server and give error if not built.
The default is to pack it if it is built.
--no-embedded Don't pack the embedded server even if built
--debug Pack the debug binaries and give error if not built.
--no-debug Don't pack the debug binaries even if built
--only-debug The target for this build was "Debug", and we just
want to replace the normal binaries with debug
versions, i.e. no separate "debug" directories.
--exe-suffix=SUF Add a suffix to the "mysqld" binary.
As you might want to include files of directories from other builds
(like a "mysqld-max.exe" server), you can instruct this script do copy
them in for you. This is the "copy-def" arguments, and they are of the
form
relative-dest-name=source-name .....
i.e. can be something like
bin/mysqld-max.exe=../my-max-build/sql/release/mysqld.exe
If you specify a directory the whole directory will be copied.
EOF
exit 1
}
# ----------------------------------------------------------------------
# We need to be at the top of a source tree, check that we are
# ----------------------------------------------------------------------
if [ ! -d "sql" ] ; then
echo "You need to run this script from inside the source tree"
usage
fi
# ----------------------------------------------------------------------
# Actual argument processing, first part
# ----------------------------------------------------------------------
NOINST_NAME=""
TARGET="release"
PACK_EMBEDDED="" # Could be "no", "yes" or empty
PACK_DEBUG="" # Could be "no", "yes" or empty
EXE_SUFFIX=""
for arg do
shift
case "$arg" in
--embedded) PACK_EMBEDDED="yes" ;;
--no-embedded) PACK_EMBEDDED="no" ;;
--debug) PACK_DEBUG="yes" ;;
--no-debug) PACK_DEBUG="no" ;;
--only-debug) TARGET="debug" ; PACK_DEBUG="no" ;;
--exe-suffix=*) EXE_SUFFIX=`echo "$arg" | sed -e "s,--exe-suffix=,,"` ;;
-*)
echo "Unknown argument '$arg'"
usage
;;
*)
NOINST_NAME="$arg"
break
esac
done
if [ x"$NOINST_NAME" = x"" ] ; then
echo "No base package name given"
usage
fi
DESTDIR=`echo $NOINST_NAME | sed 's/-noinstall-/-/'`
if [ -e $DESTDIR ] ; then
echo "Please remove the old $DESTDIR before running this script"
usage
fi
# ----------------------------------------------------------------------
# Copy executables, and client DLL (FIXME why?)
# ----------------------------------------------------------------------
trap 'echo "Clearning up and exiting..." ; rm -fr $DESTDIR; exit 1' ERR
mkdir $DESTDIR
mkdir $DESTDIR/bin
cp client/$TARGET/*.exe $DESTDIR/bin/
cp extra/$TARGET/*.exe $DESTDIR/bin/
cp storage/myisam/$TARGET/*.exe $DESTDIR/bin/
cp server-tools/instance-manager/$TARGET/*.exe $DESTDIR/bin/
cp tests/$TARGET/*.exe $DESTDIR/bin/
cp libmysql/$TARGET/*.exe $DESTDIR/bin/
cp libmysql/$TARGET/libmysql.dll $DESTDIR/bin/
# FIXME really needed?!
mv $DESTDIR/bin/comp_err.exe $DESTDIR/bin/comp-err.exe
cp sql/$TARGET/mysqld.exe $DESTDIR/bin/mysqld$EXE_SUFFIX.exe
if [ x"$PACK_DEBUG" = "" -a -f "sql/debug/mysqld.exe" -o \
x"$PACK_DEBUG" = "yes" ] ; then
cp sql/debug/mysqld.exe $DESTDIR/bin/mysqld-debug.exe
cp sql/debug/mysqld.pdb $DESTDIR/bin/mysqld-debug.pdb
cp sql/debug/mysqld.map $DESTDIR/bin/mysqld-debug.map
fi
# ----------------------------------------------------------------------
# Copy data directory, readme files etc
# ----------------------------------------------------------------------
# FIXME is there ever a data directory to copy?
if [ -d win/data ] ; then
cp -pR win/data $DESTDIR/data
fi
# FIXME maybe a flag to define "release build", or do the
# check from the calling script that all these are there,
# and with the correct content.
mkdir $DESTDIR/Docs
cp Docs/INSTALL-BINARY $DESTDIR/Docs/
cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true
cp ChangeLog $DESTDIR/Docs/ || /bin/true
cp support-files/my-*.ini $DESTDIR/
if [ -f COPYING ] ; then
cp COPYING EXCEPTIONS-CLIENT $DESTDIR/
cp COPYING $DESTDIR/Docs/
fi
# ----------------------------------------------------------------------
# These will be filled in when we enable embedded. Note that if no
# argument is given, it is copied if exists, else a check is done.
# ----------------------------------------------------------------------
copy_embedded()
{
mkdir -p $DESTDIR/Embedded/DLL/release \
$DESTDIR/Embedded/static/release \
$DESTDIR/include
cp libmysqld/libmysqld.def $DESTDIR/include/
cp libmysqld/$TARGET/mysqlserver.lib $DESTDIR/Embedded/static/release/
cp libmysqld/$TARGET/libmysqld.dll $DESTDIR/Embedded/DLL/release/
cp libmysqld/$TARGET/libmysqld.exp $DESTDIR/Embedded/DLL/release/
cp libmysqld/$TARGET/libmysqld.lib $DESTDIR/Embedded/DLL/release/
if [ x"$PACK_DEBUG" = "" -a -f "libmysqld/debug/libmysqld.lib" -o \
x"$PACK_DEBUG" = "yes" ] ; then
mkdir -p $DESTDIR/Embedded/DLL/debug
cp libmysqld/debug/libmysqld.dll $DESTDIR/Embedded/DLL/debug/
cp libmysqld/debug/libmysqld.exp $DESTDIR/Embedded/DLL/debug/
cp libmysqld/debug/libmysqld.lib $DESTDIR/Embedded/DLL/debug/
fi
}
if [ x"$PACK_EMBEDDED" = "" -a \
-f "libmysqld/$TARGET/mysqlserver.lib" -a \
-f "libmysqld/$TARGET/libmysqld.lib" -o \
x"$PACK_EMBEDDED" = "yes" ] ; then
copy_embedded
fi
# ----------------------------------------------------------------------
# FIXME test stuff that is useless garbage?
# ----------------------------------------------------------------------
mkdir -p $DESTDIR/examples/libmysqltest/release
cp libmysql/mytest.c libmysql/myTest.vcproj libmysql/$TARGET/myTest.exe \
$DESTDIR/examples/libmysqltest/
cp libmysql/$TARGET/myTest.exe $DESTDIR/examples/libmysqltest/release/
if [ x"$PACK_DEBUG" = "" -a -f "libmysql/debug/myTest.exe" -o \
x"$PACK_DEBUG" = "yes" ] ; then
mkdir -p $DESTDIR/examples/libmysqltest/debug
cp libmysql/debug/myTest.exe $DESTDIR/examples/libmysqltest/debug/
fi
mkdir -p $DESTDIR/examples/tests
cp tests/*.res tests/*.tst tests/*.pl tests/*.c $DESTDIR/examples/tests/
mkdir -p $DESTDIR/examples/udf_example
cp sql/udf_example.def sql/udf_example.vcproj sql/udf_example.c $DESTDIR/examples/udf_example/
# ----------------------------------------------------------------------
# FIXME why not copy it all in "include"?!
# ----------------------------------------------------------------------
mkdir -p $DESTDIR/include
cp include/conf*.h \
include/mysql*.h \
include/errmsg.h \
@ -48,69 +234,122 @@ cp include/conf*.h \
include/m_string.h \
include/m_ctype.h \
include/my_global.h \
include/typelib.h $NOINST_NAME/include/
cp libmysql/libmysql.def $NOINST_NAME/include/
cp libmysqld/libmysqld.def $NOINST_NAME/include/
include/typelib.h $DESTDIR/include/
cp libmysql/libmysql.def $DESTDIR/include/
mkdir -p $NOINST_NAME/lib/debug $NOINST_NAME/lib/opt
cp libmysql/debug/libmysql.dll \
libmysql/debug/libmysql.lib \
client/debug/mysqlclient.lib \
mysys/debug/mysys.lib \
regex/debug/regex.lib \
strings/debug/strings.lib \
zlib/debug/zlib.lib $NOINST_NAME/lib/debug/
cp libmysql/release/libmysql.dll \
libmysql/release/libmysql.lib \
client/release/mysqlclient.lib \
regex/release/regex.lib \
strings/release/strings.lib \
zlib/release/zlib.lib $NOINST_NAME/lib/opt/
cp mysys/release/mysys.lib $NOINST_NAME/lib/opt/mysys_tls.lib
# ----------------------------------------------------------------------
# Client libraries, and other libraries
# FIXME why "libmysql.dll" installed both in "bin" and "lib/opt"?
# ----------------------------------------------------------------------
cp support-files/my-*.ini $NOINST_NAME/
mkdir -p $DESTDIR/lib/opt
cp libmysql/$TARGET/libmysql.dll \
libmysql/$TARGET/libmysql.lib \
client/$TARGET/mysqlclient.lib \
regex/$TARGET/regex.lib \
strings/$TARGET/strings.lib \
zlib/$TARGET/zlib.lib $DESTDIR/lib/opt/
mkdir -p $NOINST_NAME/mysql-test/include $NOINST_NAME/mysql-test/lib \
$NOINST_NAME/mysql-test/r $NOINST_NAME/mysql-test/std_data \
$NOINST_NAME/mysql-test/t $NOINST_NAME/mysql-test/extra
cp mysql-test/mysql-test-run.pl $NOINST_NAME/mysql-test/
cp mysql-test/README $NOINST_NAME/mysql-test/
cp mysql-test/install_test_db.sh $NOINST_NAME/mysql-test/install_test_db
cp mysql-test/include/*.inc $NOINST_NAME/mysql-test/include/
cp mysql-test/lib/*.pl $NOINST_NAME/mysql-test/lib/
cp mysql-test/lib/*.sql $NOINST_NAME/mysql-test/lib/
cp mysql-test/r/*.require $NOINST_NAME/mysql-test/r/
if [ x"$PACK_DEBUG" = "" -a -f "libmysql/debug/libmysql.lib" -o \
x"$PACK_DEBUG" = "yes" ] ; then
mkdir -p $DESTDIR/lib/debug
cp libmysql/debug/libmysql.dll \
libmysql/debug/libmysql.lib \
client/debug/mysqlclient.lib \
mysys/debug/mysys.lib \
regex/debug/regex.lib \
strings/debug/strings.lib \
zlib/debug/zlib.lib $DESTDIR/lib/debug/
fi
# FIXME sort this out...
cp mysys/$TARGET/mysys.lib $DESTDIR/lib/opt/mysys_tls.lib
# ----------------------------------------------------------------------
# Copy the test directory
# ----------------------------------------------------------------------
mkdir -p $DESTDIR/mysql-test/include $DESTDIR/mysql-test/lib \
$DESTDIR/mysql-test/r $DESTDIR/mysql-test/std_data \
$DESTDIR/mysql-test/t
cp mysql-test/mysql-test-run.pl $DESTDIR/mysql-test/
cp mysql-test/README $DESTDIR/mysql-test/
cp mysql-test/install_test_db.sh $DESTDIR/mysql-test/install_test_db
cp mysql-test/include/*.inc $DESTDIR/mysql-test/include/
cp mysql-test/lib/*.pl $DESTDIR/mysql-test/lib/
cp mysql-test/lib/*.sql $DESTDIR/mysql-test/lib/
cp mysql-test/r/*.require $DESTDIR/mysql-test/r/
# Need this trick, or we get "argument list too long".
ABS_DST=`pwd`/$NOINST_NAME
ABS_DST=`pwd`/$DESTDIR
(cd mysql-test/r/ && cp *.result $ABS_DST/mysql-test/r/)
cp mysql-test/std_data/* $NOINST_NAME/mysql-test/std_data/
cp mysql-test/t/*.disabled $NOINST_NAME/mysql-test/t/
cp mysql-test/t/*.opt $NOINST_NAME/mysql-test/t/
cp mysql-test/t/*.sh $NOINST_NAME/mysql-test/t/
cp mysql-test/t/*.slave-mi $NOINST_NAME/mysql-test/t/
cp mysql-test/t/*.sql $NOINST_NAME/mysql-test/t/
cp mysql-test/t/*.def $NOINST_NAME/mysql-test/t/
cp mysql-test/std_data/Moscow_leap $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/des_key_file $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/*.000001 $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/*.cnf $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/*.dat $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/*.frm $DESTDIR/mysql-test/std_data/
cp mysql-test/std_data/*.pem $DESTDIR/mysql-test/std_data/
cp mysql-test/t/*.opt $DESTDIR/mysql-test/t/
cp mysql-test/t/*.sh $DESTDIR/mysql-test/t/
cp mysql-test/t/*.slave-mi $DESTDIR/mysql-test/t/
cp mysql-test/t/*.sql $DESTDIR/mysql-test/t/
cp mysql-test/t/*.def $DESTDIR/mysql-test/t/
(cd mysql-test/t/ && cp *.test $ABS_DST/mysql-test/t/)
cp -dpR mysql-test/extra/* $NOINST_NAME/mysql-test/extra/
# This copies in the unsubstituted scripts (containing @VAR@), but that seems
# rather better than substituting random Unix paths and architecture names
# from the Unix bootstrap host. Not sure what the point is of including these
# shell scripts in the Windows packaging in any case.
mkdir -p $NOINST_NAME/scripts
# Note that this will not copy "extra" if a soft link
if [ -d mysql-test/extra ] ; then
mkdir -p $DESTDIR/mysql-test/extra
cp -pR mysql-test/extra/* $DESTDIR/mysql-test/extra/
fi
# ----------------------------------------------------------------------
# Copy what could be usable in the "scripts" directory. Currently
# only SQL files, others are bourne shell scripts or Perl scripts
# not really usable on Windows.
#
# But to be nice to the few Cygwin users we might have in 5.0 we
# continue to copy the stuff, but don't include it include it in
# the WiX install.
# ----------------------------------------------------------------------
mkdir -p $DESTDIR/scripts
# Uncomment and remove the for loop in 5.1
#cp scripts/*.sql $DESTDIR/scripts/
for i in `cd scripts && ls`; do \
if echo $i | grep -q '\.sh'; then \
cp scripts/$i $NOINST_NAME/scripts/`echo $i | sed -e 's/\.sh$//'`; \
else if [ $i = Makefile.am -o $i = Makefile.in -o -e scripts/$i.sh ] ; then \
cp scripts/$i $DESTDIR/scripts/`echo $i | sed -e 's/\.sh$//'`; \
elif [ $i = Makefile.am -o $i = Makefile.in -o -e scripts/$i.sh ] ; then \
: ; \
else \
cp scripts/$i $NOINST_NAME/scripts/$i; \
fi; fi; \
cp scripts/$i $DESTDIR/scripts/$i; \
fi; \
done
cp -dpR sql/share $NOINST_NAME/
cp -dpR sql-bench $NOINST_NAME/
rm -f $NOINST_NAME/sql-bench/*.sh $NOINST_NAME/sql-bench/Makefile*
cp -pR sql/share $DESTDIR/
zip -r $NOINST_NAME.zip $NOINST_NAME
rm -Rf $NOINST_NAME
# ----------------------------------------------------------------------
# Copy other files specified on command line DEST=SOURCE
# ----------------------------------------------------------------------
for arg do
dst=`echo $arg | sed 's/=.*$//'`
src=`echo $arg | sed 's/^.*=//'`
if [ x"$dst" = x"" -o x"$src" = x"" ] ; then
echo "Invalid specification of what to copy"
usage
fi
mkdir -p `dirname $DESTDIR/$dst`
cp -pR "$src" $DESTDIR/$dst
done
# ----------------------------------------------------------------------
# Finally creat the ZIP archive
# ----------------------------------------------------------------------
rm -f $NOINST_NAME.zip
zip -r $NOINST_NAME.zip $DESTDIR
rm -Rf $DESTDIR

View file

@ -27,7 +27,7 @@ INCLUDES = @ZLIB_INCLUDES@ \
WRAPLIBS= @WRAPLIBS@
SUBDIRS = share
libexec_PROGRAMS = mysqld
EXTRA_PROGRAMS = gen_lex_hash
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
LDADD = $(top_builddir)/vio/libvio.a \
@ -120,8 +120,9 @@ DEFS = -DMYSQL_SERVER \
-DLIBDIR="\"$(MYSQLLIBdir)\"" \
@DEFS@
BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
EXTRA_DIST = udf_example.c udf_example.def $(BUILT_SOURCES) \
BUILT_DIST_SRC = sql_yacc.cc sql_yacc.h
BUILT_SOURCES = $(BUILT_DIST_SRC) lex_hash.h
EXTRA_DIST = udf_example.c udf_example.def $(BUILT_DIST_SRC) \
nt_servc.cc nt_servc.h message.mc CMakeLists.txt \
udf_example.c udf_example.def
CLEANFILES = lex_hash.h sql_yacc.cc sql_yacc.h sql_yacc.output
@ -157,11 +158,10 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
@echo "If it fails, re-run configure with --with-low-memory"
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
# This generates lex_hash.h
# NOTE Built sources should depend on their sources not the tool
# this avoid the rebuild of the built files in a source dist
lex_hash.h: gen_lex_hash.cc lex.h
$(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT)
# FIXME seems like now "lex_hash.h" differs depending on configure
# flags, so can't pregenerate and include in source TAR. Revert to
# dist pregenerated if this changes, so the file doesn't differ.
lex_hash.h: gen_lex_hash$(EXEEXT)
./gen_lex_hash$(EXEEXT) > $@
# the following three should eventually be moved out of this directory

View file

@ -132,11 +132,17 @@ bool Cached_item_decimal::cmp()
{
my_decimal tmp;
my_decimal *ptmp= item->val_decimal(&tmp);
if (null_value != item->null_value || my_decimal_cmp(&value, ptmp))
if (null_value != item->null_value ||
(!item->null_value && my_decimal_cmp(&value, ptmp)))
{
null_value= item->null_value;
my_decimal2decimal(ptmp, &value);
return TRUE;
/* Save only not null values */
if (!null_value)
{
my_decimal2decimal(ptmp, &value);
return TRUE;
}
return FALSE;
}
return FALSE;
}

View file

@ -1122,6 +1122,8 @@ bool Item_func_between::fix_fields(THD *thd, Item **ref)
if (Item_func_opt_neg::fix_fields(thd, ref))
return 1;
thd->lex->current_select->between_count++;
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
if (pred_level && !negated)
return 0;

View file

@ -448,6 +448,7 @@ public:
negated= !negated;
return this;
}
bool subst_argument_checker(byte **arg) { return TRUE; }
};

View file

@ -7129,8 +7129,8 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli,
row_start, &m_cols, row_end, &m_master_reclength,
table->write_set, UPDATE_ROWS_EVENT);
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
DBUG_DUMP("m_after_image", m_after_image, table->s->reclength);
DBUG_DUMP("record[0]", (const char *)table->record[0], table->s->reclength);
DBUG_DUMP("m_after_image", (const char *)m_after_image, table->s->reclength);
/*

View file

@ -150,7 +150,7 @@ MY_LOCALE *my_locale_by_name(const char *name);
Feel free to raise this by the smallest amount you can to get the
"execution_constants" test to pass.
*/
#define STACK_MIN_SIZE 9336 // Abort if less stack during eval.
#define STACK_MIN_SIZE 10788 // Abort if less stack during eval.
#define STACK_MIN_SIZE_FOR_OPEN 1024*80
#define STACK_BUFF_ALLOC 256 // For stack overrun checks
@ -784,6 +784,9 @@ bool quick_rm_table(handlerton *base,const char *db,
const char *table_name, uint flags);
void close_cached_table(THD *thd, TABLE *table);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent);
bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
char *new_table_name, char *new_table_alias,
bool skip_error);
bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
void mysql_parse(THD *thd,char *inBuf,uint length);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
@ -870,7 +873,8 @@ bool mysql_xa_recover(THD *thd);
bool check_simple_select();
int mysql_alter_tablespace(THD* thd, st_alter_tablespace *ts_info);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length,
SORT_FIELD *sortorder);
int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List <Item> &all_fields, ORDER *order);
int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,

View file

@ -9787,6 +9787,7 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick->quick_prefix_select= NULL;
quick->update_key_stat();
quick->adjust_prefix_ranges();
DBUG_RETURN(quick);
}
@ -10016,6 +10017,42 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
}
/*
Opens the ranges if there are more conditions in quick_prefix_select than
the ones used for jumping through the prefixes.
SYNOPSIS
QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges()
NOTES
quick_prefix_select is made over the conditions on the whole key.
It defines a number of ranges of length x.
However when jumping through the prefixes we use only the the first
few most significant keyparts in the range key. However if there
are more keyparts to follow the ones we are using we must make the
condition on the key inclusive (because x < "ab" means
x[0] < 'a' OR (x[0] == 'a' AND x[1] < 'b').
To achive the above we must turn off the NEAR_MIN/NEAR_MAX
*/
void QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges ()
{
if (quick_prefix_select &&
group_prefix_len < quick_prefix_select->max_used_key_length)
{
DYNAMIC_ARRAY *arr;
uint inx;
for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++)
{
QUICK_RANGE *range;
get_dynamic(arr, (gptr)&range, inx);
range->flag &= ~(NEAR_MIN | NEAR_MAX);
}
}
}
/*
Determine the total number and length of the keys that will be used for
index lookup.

View file

@ -295,6 +295,7 @@ protected:
friend class QUICK_SELECT_DESC;
friend class QUICK_INDEX_MERGE_SELECT;
friend class QUICK_ROR_INTERSECT_SELECT;
friend class QUICK_GROUP_MIN_MAX_SELECT;
DYNAMIC_ARRAY ranges; /* ordered array of range ptrs */
QUICK_RANGE **cur_range; /* current element in ranges */
@ -643,6 +644,7 @@ public:
~QUICK_GROUP_MIN_MAX_SELECT();
bool add_range(SEL_ARG *sel_range);
void update_key_stat();
void adjust_prefix_ranges();
bool alloc_buffers();
int init();
int reset();

View file

@ -4362,13 +4362,20 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
const char *field_name=0;
const char *table_name=0;
bool found_unaliased_non_uniq= 0;
/*
true if the item that we search for is a valid name reference
(and not an item that happens to have a name).
*/
bool is_ref_by_name= 0;
uint unaliased_counter;
LINT_INIT(unaliased_counter); // Dependent on found_unaliased
*unaliased= FALSE;
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)
is_ref_by_name= (find->type() == Item::FIELD_ITEM ||
find->type() == Item::REF_ITEM);
if (is_ref_by_name)
{
field_name= ((Item_ident*) find)->field_name;
table_name= ((Item_ident*) find)->table_name;
@ -4480,7 +4487,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
}
}
else if (!table_name && (find->eq(item,0) ||
find->name && item->name &&
is_ref_by_name && find->name && item->name &&
!my_strcasecmp(system_charset_info,
item->name,find->name)))
{
@ -5810,6 +5817,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
thd->mark_used_columns= MARK_COLUMNS_READ;
DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
select_lex->cond_count= 0;
select_lex->between_count= 0;
for (table= tables; table; table= table->next_local)
{

View file

@ -2632,10 +2632,10 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
my_size_t const after_size= pack_row(table, cols, after_row,
after_record);
DBUG_DUMP("before_record", before_record, table->s->reclength);
DBUG_DUMP("after_record", after_record, table->s->reclength);
DBUG_DUMP("before_row", before_row, before_size);
DBUG_DUMP("after_row", after_row, after_size);
DBUG_DUMP("before_record", (const char *)before_record, table->s->reclength);
DBUG_DUMP("after_record", (const char *)after_record, table->s->reclength);
DBUG_DUMP("before_row", (const char *)before_row, before_size);
DBUG_DUMP("after_row", (const char *)after_row, after_size);
Rows_log_event* const ev=
binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,

View file

@ -183,7 +183,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
MYF(MY_FAE | MY_ZEROFILL));
if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
&length)) ||
&length, NULL)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
select, HA_POS_ERROR, 1,
&examined_rows))

View file

@ -1147,7 +1147,7 @@ void st_select_lex::init_query()
initialization is checked for failure.
*/
parent_lex->push_context(&context);
cond_count= with_wild= 0;
cond_count= between_count= with_wild= 0;
conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0;
select_n_having_items= 0;

View file

@ -556,7 +556,8 @@ public:
list during split_sum_func
*/
uint select_n_having_items;
uint cond_count; /* number of arguments of and/or/xor in where/having */
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
uint between_count; /* number of between predicates in where/having/on */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
/*

View file

@ -125,96 +125,143 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list)
}
/*
Rename a single table or a view
SYNPOSIS
do_rename()
thd Thread handle
ren_table A table/view to be renamed
new_db The database to which the table to be moved to
new_table_name The new table/view name
new_table_alias The new table/view alias
skip_error Whether to skip error
DESCRIPTION
Rename a single table or a view.
RETURN
false Ok
true rename failed
*/
bool
do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
char *new_table_alias, bool skip_error)
{
int rc= 1;
char name[FN_REFLEN];
const char *new_alias, *old_alias;
frm_type_enum frm_type;
enum legacy_db_type table_type;
DBUG_ENTER("do_rename");
if (lower_case_table_names == 2)
{
old_alias= ren_table->alias;
new_alias= new_table_alias;
}
else
{
old_alias= ren_table->table_name;
new_alias= new_table_name;
}
build_table_filename(name, sizeof(name),
new_db, new_alias, reg_ext, 0);
if (!access(name,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(1); // This can't be skipped
}
build_table_filename(name, sizeof(name),
ren_table->db, old_alias, reg_ext, 0);
frm_type= mysql_frm_type(thd, name, &table_type);
switch (frm_type)
{
case FRMTYPE_TABLE:
{
if (!(rc= mysql_rename_table(ha_resolve_by_legacy_type(thd,
table_type),
ren_table->db, old_alias,
new_db, new_alias, 0)))
{
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
old_alias,
new_db,
new_alias)))
{
/*
We've succeeded in renaming table's .frm and in updating
corresponding handler data, but have failed to update table's
triggers appropriately. So let us revert operations on .frm
and handler's data and report about failure to rename table.
*/
(void) mysql_rename_table(ha_resolve_by_legacy_type(thd,
table_type),
new_db, new_alias,
ren_table->db, old_alias, 0);
}
}
}
break;
case FRMTYPE_VIEW:
/* change of schema is not allowed */
if (strcmp(ren_table->db, new_db))
my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db,
new_db);
else
rc= mysql_rename_view(thd, new_alias, ren_table);
break;
default:
DBUG_ASSERT(0); // should never happen
case FRMTYPE_ERROR:
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
break;
}
if (rc && !skip_error)
DBUG_RETURN(1);
DBUG_RETURN(0);
}
/*
Rename all tables in list; Return pointer to wrong entry if something goes
wrong. Note that the table_list may be empty!
*/
/*
Rename tables/views in the list
SYNPOSIS
rename_tables()
thd Thread handle
table_list List of tables to rename
skip_error Whether to skip errors
DESCRIPTION
Take a table/view name from and odd list element and rename it to a
the name taken from list element+1. Note that the table_list may be
empty.
RETURN
false Ok
true rename failed
*/
static TABLE_LIST *
rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
TABLE_LIST *ren_table,*new_table;
frm_type_enum frm_type;
enum legacy_db_type table_type;
TABLE_LIST *ren_table,*new_table, *tmp_table;
DBUG_ENTER("rename_tables");
for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
{
int rc= 1;
char name[FN_REFLEN];
const char *new_alias, *old_alias;
new_table= ren_table->next_local;
if (lower_case_table_names == 2)
{
old_alias= ren_table->alias;
new_alias= new_table->alias;
}
else
{
old_alias= ren_table->table_name;
new_alias= new_table->table_name;
}
build_table_filename(name, sizeof(name),
new_table->db, new_alias, reg_ext, 0);
if (!access(name,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(ren_table); // This can't be skipped
}
build_table_filename(name, sizeof(name),
ren_table->db, old_alias, reg_ext, 0);
frm_type= mysql_frm_type(thd, name, &table_type);
switch (frm_type)
{
case FRMTYPE_TABLE:
{
if (table_type == DB_TYPE_UNKNOWN)
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
else
{
if (!(rc= mysql_rename_table(ha_resolve_by_legacy_type(thd,
table_type),
ren_table->db, old_alias,
new_table->db, new_alias, 0)))
{
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
old_alias,
new_table->db,
new_alias)))
{
/*
We've succeeded in renaming table's .frm and in updating
corresponding handler data, but have failed to update table's
triggers appropriately. So let us revert operations on .frm
and handler's data and report about failure to rename table.
*/
(void) mysql_rename_table(ha_resolve_by_legacy_type(thd,
table_type),
new_table->db, new_alias,
ren_table->db, old_alias, 0);
}
}
}
break;
}
case FRMTYPE_VIEW:
/* change of schema is not allowed */
if (strcmp(ren_table->db, new_table->db))
my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db,
new_table->db);
else
rc= mysql_rename_view(thd, new_alias, ren_table);
break;
default:
DBUG_ASSERT(0); // should never happen
case FRMTYPE_ERROR:
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
break;
}
if (rc && !skip_error)
if (do_rename(thd, ren_table, new_table->db, new_table->table_name,
new_table->alias, skip_error))
DBUG_RETURN(ren_table);
}
DBUG_RETURN(0);

View file

@ -35,14 +35,17 @@ const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"index_merge"
};
struct st_sargable_param;
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB *join_tab,
JOIN_TAB *join_tab,
uint tables, COND *conds,
COND_EQUAL *cond_equal,
table_map table_map, SELECT_LEX *select_lex);
table_map table_map, SELECT_LEX *select_lex,
st_sargable_param **sargables);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
@ -1380,12 +1383,13 @@ JOIN::exec()
thd->examined_row_count= 0;
DBUG_VOID_RETURN;
}
/*
don't reset the found rows count if there're no tables
as FOUND_ROWS() may be called.
*/
/*
Don't reset the found rows count if there're no tables as
FOUND_ROWS() may be called. Never reset the examined row count here.
It must be accumulated from all join iterations of all join parts.
*/
if (tables)
thd->limit_found_rows= thd->examined_row_count= 0;
thd->limit_found_rows= 0;
if (zero_result_cause)
{
@ -1415,7 +1419,8 @@ JOIN::exec()
simple_order= simple_group;
skip_sort_order= 0;
}
if (order &&
if (order &&
(order != group_list || !(select_options & SELECT_BIG_RESULT)) &&
(const_tables == tables ||
((simple_order || skip_sort_order) &&
test_if_skip_sort_order(&join_tab[const_tables], order,
@ -1433,6 +1438,12 @@ JOIN::exec()
List<Item> *curr_all_fields= &all_fields;
List<Item> *curr_fields_list= &fields_list;
TABLE *curr_tmp_table= 0;
/*
Initialize examined rows here because the values from all join parts
must be accumulated in examined_row_count. Hence every join
iteration must count from zero.
*/
curr_join->examined_rows= 0;
if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
get_schema_tables_result(curr_join))
@ -1593,6 +1604,7 @@ JOIN::exec()
{
DBUG_VOID_RETURN;
}
sortorder= curr_join->sortorder;
}
thd->proc_info="Copying to group table";
@ -1805,6 +1817,7 @@ JOIN::exec()
(select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR : unit->select_limit_cnt)))
DBUG_VOID_RETURN;
sortorder= curr_join->sortorder;
if (curr_join->const_tables != curr_join->tables &&
!curr_join->join_tab[curr_join->const_tables].table->sort.io_cache)
{
@ -1855,9 +1868,12 @@ JOIN::exec()
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
error= do_select(curr_join, curr_fields_list, NULL, procedure);
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
}
/* Accumulate the counts from all join iterations of all join parts. */
thd->examined_row_count+= curr_join->examined_rows;
DBUG_PRINT("counts", ("thd->examined_row_count: %lu",
(ulong) thd->examined_row_count));
DBUG_VOID_RETURN;
}
@ -2071,6 +2087,19 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */
}
/*
This structure is used to collect info on potentially sargable
predicates in order to check whether they become sargable after
reading const tables.
We form a bitmap of indexes that can be used for sargable predicates.
Only such indexes are involved in range analysis.
*/
typedef struct st_sargable_param
{
Field *field; /* field against which to check sargability */
Item **arg_value; /* values of potential keys for lookups */
uint num_values; /* number of values in the above array */
} SARGABLE_PARAM;
/*
Calculate the best possible join and initialize the join structure
@ -2093,6 +2122,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
KEYUSE *keyuse,*start_keyuse;
table_map outer_join=0;
SARGABLE_PARAM *sargables= 0;
JOIN_TAB *stat_vector[MAX_TABLES+1];
DBUG_ENTER("make_join_statistics");
@ -2230,7 +2260,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (conds || outer_join)
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
conds, join->cond_equal,
~outer_join, join->select_lex))
~outer_join, join->select_lex, &sargables))
DBUG_RETURN(1);
/* Read tables with 0 or 1 rows (system tables) */
@ -2380,6 +2410,26 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
}
} while (join->const_table_map & found_ref && ref_changed);
/*
Update info on indexes that can be used for search lookups as
reading const tables may has added new sargable predicates.
*/
if (const_count && sargables)
{
for( ; sargables->field ; sargables++)
{
Field *field= sargables->field;
JOIN_TAB *stat= field->table->reginfo.join_tab;
key_map possible_keys= field->key_start;
possible_keys.intersect(field->table->keys_in_use_for_query);
bool is_const= 1;
for (uint i=0; i< sargables->num_values; i++)
is_const&= sargables->arg_value[i]->const_item();
if (is_const)
stat[0].const_keys.merge(possible_keys);
}
}
/* Calc how many (possible) matched records in each table */
for (s=stat ; s < stat_end ; s++)
@ -2639,6 +2689,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
eq_func True if we used =, <=> or IS NULL
value Value used for comparison with field
usable_tables Tables which can be used for key optimization
sargables IN/OUT Array of found sargable candidates
NOTES
If we are doing a NOT NULL comparison on a NOT NULL field in a outer join
@ -2650,8 +2701,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
static void
add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
Field *field, bool eq_func, Item **value, uint num_values,
table_map usable_tables)
Field *field, bool eq_func, Item **value, uint num_values,
table_map usable_tables, SARGABLE_PARAM **sargables)
{
uint exists_optimize= 0;
if (!(field->flags & PART_KEY_FLAG))
@ -2710,6 +2761,19 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
}
if (is_const)
stat[0].const_keys.merge(possible_keys);
else if (!eq_func)
{
/*
Save info to be able check whether this predicate can be
considered as sargable for range analisis after reading const tables.
We do not save info about equalities as update_const_equal_items
will take care of updating info on keys from sargable equalities.
*/
(*sargables)--;
(*sargables)->field= field;
(*sargables)->arg_value= value;
(*sargables)->num_values= num_values;
}
/*
We can't always use indexes when comparing a string index to a
number. cmp_type() is checked to allow compare of dates to numbers.
@ -2800,6 +2864,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
value Value used for comparison with field
Is NULL for BETWEEN and IN
usable_tables Tables which can be used for key optimization
sargables IN/OUT Array of found sargable candidates
NOTES
If field items f1 and f2 belong to the same multiple equality and
@ -2813,11 +2878,12 @@ static void
add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
Item_func *cond, Item_field *field_item,
bool eq_func, Item **val,
uint num_values, table_map usable_tables)
uint num_values, table_map usable_tables,
SARGABLE_PARAM **sargables)
{
Field *field= field_item->field;
add_key_field(key_fields, and_level, cond, field,
eq_func, val, num_values, usable_tables);
eq_func, val, num_values, usable_tables, sargables);
Item_equal *item_equal= field_item->item_equal;
if (item_equal)
{
@ -2832,7 +2898,8 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
if (!field->eq(item->field))
{
add_key_field(key_fields, and_level, cond, item->field,
eq_func, val, num_values, usable_tables);
eq_func, val, num_values, usable_tables,
sargables);
}
}
}
@ -2840,7 +2907,8 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
static void
add_key_fields(KEY_FIELD **key_fields,uint *and_level,
COND *cond, table_map usable_tables)
COND *cond, table_map usable_tables,
SARGABLE_PARAM **sargables)
{
if (cond->type() == Item_func::COND_ITEM)
{
@ -2851,20 +2919,20 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
{
Item *item;
while ((item=li++))
add_key_fields(key_fields,and_level,item,usable_tables);
add_key_fields(key_fields,and_level,item,usable_tables,sargables);
for (; org_key_fields != *key_fields ; org_key_fields++)
org_key_fields->level= *and_level;
}
else
{
(*and_level)++;
add_key_fields(key_fields,and_level,li++,usable_tables);
add_key_fields(key_fields,and_level,li++,usable_tables,sargables);
Item *item;
while ((item=li++))
{
KEY_FIELD *start_key_fields= *key_fields;
(*and_level)++;
add_key_fields(key_fields,and_level,item,usable_tables);
add_key_fields(key_fields,and_level,item,usable_tables,sargables);
*key_fields=merge_key_fields(org_key_fields,start_key_fields,
*key_fields,++(*and_level));
}
@ -2895,9 +2963,9 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
cond_func->argument_count() != 2);
add_key_equal_fields(key_fields, *and_level, cond_func,
(Item_field*) (cond_func->key_item()->real_item()),
0, values,
0, values,
cond_func->argument_count()-1,
usable_tables);
usable_tables, sargables);
}
if (cond_func->functype() == Item_func::BETWEEN)
{
@ -2911,7 +2979,8 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
{
field_item= (Item_field *) (cond_func->arguments()[i]->real_item());
add_key_equal_fields(key_fields, *and_level, cond_func,
field_item, 0, values, 1, usable_tables);
field_item, 0, values, 1, usable_tables,
sargables);
}
}
}
@ -2928,7 +2997,8 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
add_key_equal_fields(key_fields, *and_level, cond_func,
(Item_field*) (cond_func->arguments()[0])->real_item(),
equal_func,
cond_func->arguments()+1, 1, usable_tables);
cond_func->arguments()+1, 1, usable_tables,
sargables);
}
if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
cond_func->functype() != Item_func::LIKE_FUNC &&
@ -2937,7 +3007,8 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
add_key_equal_fields(key_fields, *and_level, cond_func,
(Item_field*) (cond_func->arguments()[1])->real_item(),
equal_func,
cond_func->arguments(),1,usable_tables);
cond_func->arguments(),1,usable_tables,
sargables);
}
break;
}
@ -2952,7 +3023,7 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
add_key_equal_fields(key_fields, *and_level, cond_func,
(Item_field*) (cond_func->arguments()[0])->real_item(),
cond_func->functype() == Item_func::ISNULL_FUNC,
&tmp, 1, usable_tables);
&tmp, 1, usable_tables, sargables);
}
break;
case Item_func::OPTIMIZE_EQUAL:
@ -2970,7 +3041,7 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
while ((item= it++))
{
add_key_field(key_fields, *and_level, cond_func, item->field,
TRUE, &const_item, 1, usable_tables);
TRUE, &const_item, 1, usable_tables, sargables);
}
}
else
@ -2990,7 +3061,8 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
if (!field->eq(item->field))
{
add_key_field(key_fields, *and_level, cond_func, field,
TRUE, (Item **) &item, 1, usable_tables);
TRUE, (Item **) &item, 1, usable_tables,
sargables);
}
}
it.rewind();
@ -3141,6 +3213,7 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
nested_join_table IN Nested join pseudo-table to process
end INOUT End of the key field array
and_level INOUT And-level
sargables IN/OUT Array of found sargable candidates
DESCRIPTION
This function populates KEY_FIELD array with entries generated from the
@ -3164,7 +3237,8 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
*/
static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
KEY_FIELD **end, uint *and_level)
KEY_FIELD **end, uint *and_level,
SARGABLE_PARAM **sargables)
{
List_iterator<TABLE_LIST> li(nested_join_table->nested_join->join_list);
table_map tables= 0;
@ -3174,12 +3248,12 @@ static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
while ((table= li++))
{
if (table->nested_join)
add_key_fields_for_nj(table, end, and_level);
add_key_fields_for_nj(table, end, and_level, sargables);
else
if (!table->on_expr)
tables |= table->table->map;
}
add_key_fields(end, and_level, nested_join_table->on_expr, tables);
add_key_fields(end, and_level, nested_join_table->on_expr, tables, sargables);
}
@ -3194,9 +3268,10 @@ static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
tables Number of tables in join
cond WHERE condition (note that the function analyzes
join_tab[i]->on_expr too)
normal_tables tables not inner w.r.t some outer join (ones for which
normal_tables Tables not inner w.r.t some outer join (ones for which
we can make ref access based the WHERE clause)
select_lex current SELECT
sargables OUT Array of found sargable candidates
RETURN
0 - OK
@ -3205,27 +3280,55 @@ static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
static bool
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
uint tables, COND *cond, COND_EQUAL *cond_equal,
table_map normal_tables, SELECT_LEX *select_lex)
uint tables, COND *cond, COND_EQUAL *cond_equal,
table_map normal_tables, SELECT_LEX *select_lex,
SARGABLE_PARAM **sargables)
{
uint and_level,i,found_eq_constant;
KEY_FIELD *key_fields, *end, *field;
uint sz;
uint m= 1;
if (cond_equal && cond_equal->max_members)
m= cond_equal->max_members;
if (!(key_fields=(KEY_FIELD*)
thd->alloc(sizeof(key_fields[0])*
(thd->lex->current_select->cond_count+1)*2*m)))
/*
We use the same piece of memory to store both KEY_FIELD
and SARGABLE_PARAM structure.
KEY_FIELD values are placed at the beginning this memory
while SARGABLE_PARAM values are put at the end.
All predicates that are used to fill arrays of KEY_FIELD
and SARGABLE_PARAM structures have at most 2 arguments
except BETWEEN predicates that have 3 arguments and
IN predicates.
This any predicate if it's not BETWEEN/IN can be used
directly to fill at most 2 array elements, either of KEY_FIELD
or SARGABLE_PARAM type. For a BETWEEN predicate 3 elements
can be filled as this predicate is considered as
saragable with respect to each of its argument.
An IN predicate can require at most 1 element as currently
it is considered as sargable only for its first argument.
Multiple equality can add elements that are filled after
substitution of field arguments by equal fields. There
can be not more than cond_equal->max_members such substitutions.
*/
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
(((thd->lex->current_select->cond_count+1)*2 +
thd->lex->current_select->between_count)*m+1);
if (!(key_fields=(KEY_FIELD*) thd->alloc(sz)))
return TRUE; /* purecov: inspected */
and_level= 0;
field= end= key_fields;
*sargables= (SARGABLE_PARAM *) key_fields +
(sz - sizeof((*sargables)[0].field))/sizeof(SARGABLE_PARAM);
/* set a barrier for the array of SARGABLE_PARAM */
(*sargables)[0].field= 0;
if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
return TRUE;
if (cond)
{
add_key_fields(&end,&and_level,cond,normal_tables);
add_key_fields(&end,&and_level,cond,normal_tables,sargables);
for (; field != end ; field++)
{
add_key_part(keyuse,field);
@ -3248,7 +3351,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
*/
if (*join_tab[i].on_expr_ref)
add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
join_tab[i].table->map);
join_tab[i].table->map,sargables);
}
/* Process ON conditions for the nested joins */
@ -3258,7 +3361,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
while ((table= li++))
{
if (table->nested_join)
add_key_fields_for_nj(table, &end, &and_level);
add_key_fields_for_nj(table, &end, &and_level, sargables);
}
}
@ -5124,9 +5227,28 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
JOIN_TAB *join_tab;
DBUG_ENTER("make_simple_join");
if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
!(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
DBUG_RETURN(TRUE);
/*
Reuse TABLE * and JOIN_TAB if already allocated by a previous call
to this function through JOIN::exec (may happen for sub-queries).
*/
if (!join->table_reexec)
{
if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*))))
DBUG_RETURN(TRUE); /* purecov: inspected */
if (join->tmp_join)
join->tmp_join->table_reexec= join->table_reexec;
}
if (!join->join_tab_reexec)
{
if (!(join->join_tab_reexec=
(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
DBUG_RETURN(TRUE); /* purecov: inspected */
if (join->tmp_join)
join->tmp_join->join_tab_reexec= join->join_tab_reexec;
}
tableptr= join->table_reexec;
join_tab= join->join_tab_reexec;
join->join_tab=join_tab;
join->table=tableptr; tableptr[0]=tmp_table;
join->tables=1;
@ -7514,7 +7636,22 @@ static void update_const_equal_items(COND *cond, JOIN_TAB *tab)
((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
{
Item_equal *item_equal= (Item_equal *) cond;
bool contained_const= item_equal->get_const() != NULL;
item_equal->update_const();
if (!contained_const && item_equal->get_const())
{
/* Update keys for range analysis */
Item_equal_iterator it(*item_equal);
Item_field *item_field;
while ((item_field= it++))
{
Field *field= item_field->field;
JOIN_TAB *stat= field->table->reginfo.join_tab;
key_map possible_keys= field->key_start;
possible_keys.intersect(field->table->keys_in_use_for_query);
stat[0].const_keys.merge(possible_keys);
}
}
}
}
@ -10359,6 +10496,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
*/
join->examined_rows++;
join->thd->row_count++;
DBUG_PRINT("counts", ("join->examined_rows++: %lu",
(ulong) join->examined_rows));
if (found)
{
@ -12220,7 +12359,6 @@ static int
create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit)
{
SORT_FIELD *sortorder;
uint length;
ha_rows examined_rows;
TABLE *table;
@ -12234,11 +12372,18 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
table= tab->table;
select= tab->select;
if (test_if_skip_sort_order(tab,order,select_limit,0))
/*
When there is SQL_BIG_RESULT do not sort using index for GROUP BY,
and thus force sorting on disk.
*/
if ((order != join->group_list ||
!(join->select_options & SELECT_BIG_RESULT)) &&
test_if_skip_sort_order(tab,order,select_limit,0))
DBUG_RETURN(0);
if (!(sortorder=make_unireg_sortorder(order,&length)))
if (!(join->sortorder=
make_unireg_sortorder(order,&length,join->sortorder)))
goto err; /* purecov: inspected */
/* It's not fatal if the following alloc fails */
table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_WME | MY_ZEROFILL));
table->status=0; // May be wrong if quick_select
@ -12283,7 +12428,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
if (table->s->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count
table->sort.found_records=filesort(thd, table,sortorder, length,
table->sort.found_records=filesort(thd, table,join->sortorder, length,
select, filesort_limit, 0,
&examined_rows);
tab->records= table->sort.found_records; // For SQL_CALC_ROWS
@ -12631,7 +12776,8 @@ err:
}
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
SORT_FIELD *sortorder)
{
uint count;
SORT_FIELD *sort,*pos;
@ -12640,7 +12786,9 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
count=0;
for (ORDER *tmp = order; tmp; tmp=tmp->next)
count++;
pos=sort=(SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
if (!sortorder)
sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
pos=sort=sortorder;
if (!pos)
return 0;
@ -13758,7 +13906,19 @@ bool JOIN::alloc_func_list()
disctinct->group_by optimization
*/
if (select_distinct)
{
group_parts+= fields_list.elements;
/*
If the ORDER clause is specified then it's possible that
it also will be optimized, so reserve space for it too
*/
if (order)
{
ORDER *ord;
for (ord= order; ord; ord= ord->next)
group_parts++;
}
}
/* This must use calloc() as rollup_make_fields depends on this */
sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) +
@ -14241,12 +14401,17 @@ bool JOIN::rollup_init()
while ((item= it++))
{
ORDER *group_tmp;
bool found_in_group= 0;
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
{
if (*group_tmp->item == item)
{
item->maybe_null= 1;
found_in_group= 1;
}
}
if (item->type() == Item::FUNC_ITEM)
if (item->type() == Item::FUNC_ITEM && !found_in_group)
{
bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))

View file

@ -321,6 +321,18 @@ public:
bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
/*
storage for caching buffers allocated during query execution.
These buffers allocations need to be cached as the thread memory pool is
cleared only at the end of the execution of the whole query and not caching
allocations that occur in repetition at execution time will result in
excessive memory usage.
*/
SORT_FIELD *sortorder; // make_unireg_sortorder()
TABLE **table_reexec; // make_simple_join()
JOIN_TAB *join_tab_reexec; // make_simple_join()
/* end of allocation caching storage */
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
:fields_list(fields_arg)
@ -346,6 +358,9 @@ public:
examined_rows= 0;
exec_tmp_table1= 0;
exec_tmp_table2= 0;
sortorder= 0;
table_reexec= 0;
join_tab_reexec= 0;
thd= thd_arg;
sum_funcs= sum_funcs2= 0;
procedure= 0;

View file

@ -5152,7 +5152,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
ha_rows copied,deleted;
uint db_create_options, used_fields;
handlerton *old_db_type, *new_db_type;
legacy_db_type table_type;
HA_CREATE_INFO *create_info;
frm_type_enum frm_type;
uint need_copy_table= 0;
bool no_table_reopen= FALSE, varchar= FALSE;
#ifdef WITH_PARTITION_STORAGE_ENGINE
@ -5234,6 +5236,52 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
"/", table_name, reg_ext, NullS);
(void) unpack_filename(new_name_buff, new_name_buff);
if (lower_case_table_names != 2)
my_casedn_str(files_charset_info, new_name_buff);
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
/* Rename a view */
if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
{
/*
Avoid problems with a rename on a table that we have locked or
if the user is trying to to do this in a transcation context
*/
if (thd->locked_tables || thd->active_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
DBUG_RETURN(1);
}
if (wait_if_global_read_lock(thd,0,1))
DBUG_RETURN(1);
VOID(pthread_mutex_lock(&LOCK_open));
if (lock_table_names(thd, table_list))
goto view_err;
error=0;
if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
{
if (mysql_bin_log.is_open())
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
}
unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
view_err:
pthread_mutex_unlock(&LOCK_open);
start_waiting_global_read_lock(thd);
DBUG_RETURN(error);
}
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(TRUE);
table->use_all_columns();
@ -6515,7 +6563,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, 1,
&examined_rows)) ==

View file

@ -327,7 +327,7 @@ int mysql_update(THD *thd,
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
if (!(sortorder=make_unireg_sortorder(order, &length)) ||
if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
(table->sort.found_records= filesort(thd, table, sortorder, length,
select, limit, 1,
&examined_rows))

View file

@ -1421,6 +1421,7 @@ opt_ev_comment: /* empty */ { $$= 0; }
| COMMENT_SYM TEXT_STRING_sys
{
Lex->comment= Lex->event_parse_data->comment= $2;
$$= 1;
}
;

View file

@ -802,7 +802,21 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
count)))
goto err;
for (count= 0; count < interval->count; count++)
interval->type_lengths[count]= strlen(interval->type_names[count]);
{
char *val= (char*) interval->type_names[count];
interval->type_lengths[count]= strlen(val);
/*
Replace all ',' symbols with NAMES_SEP_CHAR.
See the comment in unireg.cc, pack_fields() function
for details.
*/
for (uint cnt= 0 ; cnt < interval->type_lengths[count] ; cnt++)
{
char c= val[cnt];
if (c == ',')
val[cnt]= NAMES_SEP_CHAR;
}
}
interval->type_lengths[count]= 0;
}
}
@ -2773,12 +2787,13 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
this expression will not be moved to WHERE condition (i.e. will
be clean correctly for PS/SP)
*/
tbl->on_expr= and_conds(tbl->on_expr, where);
tbl->on_expr= and_conds(tbl->on_expr,
where->copy_andor_structure(thd));
break;
}
}
if (tbl == 0)
*conds= and_conds(*conds, where);
*conds= and_conds(*conds, where->copy_andor_structure(thd));
if (arena)
thd->restore_active_arena(arena, &backup);
where_processed= TRUE;

View file

@ -793,6 +793,21 @@ static bool pack_fields(File file, List<create_field> &create_fields,
tmp.append(NAMES_SEP_CHAR);
for (const char **pos=field->interval->type_names ; *pos ; pos++)
{
char *val= (char*) *pos;
uint str_len= strlen(val);
/*
Note, hack: in old frm NAMES_SEP_CHAR is used to separate
names in the interval (ENUM/SET). To allow names to contain
NAMES_SEP_CHAR, we replace it with a comma before writing frm.
Backward conversion is done during frm file opening,
See table.cc, openfrm() function
*/
for (uint cnt= 0 ; cnt < str_len ; cnt++)
{
char c= val[cnt];
if (c == NAMES_SEP_CHAR)
val[cnt]= ',';
}
tmp.append(*pos);
tmp.append(NAMES_SEP_CHAR);
}

View file

@ -2,3 +2,4 @@ MYSQL_STORAGE_ENGINE(federated,,[Federated Storage Engine],
[Connects to tables on remote MySQL servers], [max,max-no-ndb])
MYSQL_PLUGIN_STATIC(federated, [libfederated.a])
MYSQL_PLUGIN_DYNAMIC(federated, [ha_federated.la])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federated.cc])

View file

@ -3,4 +3,5 @@ MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine],
MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap])
MYSQL_PLUGIN_STATIC(heap, [libheap.a])
MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(heap, [ha_heap.cc])

View file

@ -68,4 +68,5 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
storage/innobase/handler/Makefile
storage/innobase/usr/Makefile)
])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])

View file

@ -16,6 +16,31 @@
/* Describe, check and repair of MyISAM tables */
/*
About checksum calculation.
There are two types of checksums. Table checksum and row checksum.
Row checksum is an additional byte at the end of dynamic length
records. It must be calculated if the table is configured for them.
Otherwise they must not be used. The variable
MYISAM_SHARE::calc_checksum determines if row checksums are used.
MI_INFO::checksum is used as temporary storage during row handling.
For parallel repair we must assure that only one thread can use this
variable. There is no problem on the write side as this is done by one
thread only. But when checking a record after read this could go
wrong. But since all threads read through a common read buffer, it is
sufficient if only one thread checks it.
Table checksum is an eight byte value in the header of the index file.
It can be calculated even if row checksums are not used. The variable
MI_CHECK::glob_crc is calculated over all records.
MI_SORT_PARAM::calc_checksum determines if this should be done. This
variable is not part of MI_CHECK because it must be set per thread for
parallel repair. The global glob_crc must be changed by one thread
only. And it is sufficient to calculate the checksum once only.
*/
#include "ftdefs.h"
#include <m_ctype.h>
#include <stdarg.h>
@ -41,8 +66,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
ha_checksum *key_checksum, uint level);
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
static ha_checksum calc_checksum(ha_rows count);
static int writekeys(MI_CHECK *param, MI_INFO *info,byte *buff,
my_off_t filepos);
static int writekeys(MI_SORT_PARAM *sort_param);
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
my_off_t pagepos, File new_file);
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
@ -1102,7 +1126,8 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
goto err;
start_recpos=pos;
splits++;
VOID(_mi_pack_get_block_info(info,&block_info, -1, start_recpos));
VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
&info->rec_buff, -1, start_recpos));
pos=block_info.filepos+block_info.rec_len;
if (block_info.rec_len < (uint) info->s->min_pack_length ||
block_info.rec_len > (uint) info->s->max_pack_length)
@ -1116,7 +1141,8 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
if (_mi_read_cache(&param->read_cache,(byte*) info->rec_buff,
block_info.filepos, block_info.rec_len, READING_NEXT))
goto err;
if (_mi_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len))
if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
info->rec_buff, block_info.rec_len))
{
mi_check_print_error(param,"Found wrong record at %s",
llstr(start_recpos,llbuff));
@ -1400,7 +1426,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
info->state->empty=0;
param->glob_crc=0;
if (param->testflag & T_CALC_CHECKSUM)
param->calc_checksum=1;
sort_param.calc_checksum= 1;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
@ -1429,7 +1455,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
/* Re-create all keys, which are set in key_map. */
while (!(error=sort_get_next_record(&sort_param)))
{
if (writekeys(param,info,(byte*)sort_param.record,sort_param.filepos))
if (writekeys(&sort_param))
{
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
goto err;
@ -1574,11 +1600,13 @@ err:
/* Uppate keyfile when doing repair */
static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
my_off_t filepos)
static int writekeys(MI_SORT_PARAM *sort_param)
{
register uint i;
uchar *key;
uchar *key;
MI_INFO *info= sort_param->sort_info->info;
byte *buff= sort_param->record;
my_off_t filepos= sort_param->filepos;
DBUG_ENTER("writekeys");
key=info->lastkey+info->s->base.max_key_length;
@ -1632,8 +1660,8 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff,
}
}
/* Remove checksum that was added to glob_crc in sort_get_next_record */
if (param->calc_checksum)
param->glob_crc-= info->checksum;
if (sort_param->calc_checksum)
sort_param->sort_info->param->glob_crc-= info->checksum;
DBUG_PRINT("error",("errno: %d",my_errno));
DBUG_RETURN(-1);
} /* writekeys */
@ -2140,7 +2168,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
del=info->state->del;
param->glob_crc=0;
if (param->testflag & T_CALC_CHECKSUM)
param->calc_checksum=1;
sort_param.calc_checksum= 1;
rec_per_key_part= param->rec_per_key_part;
for (sort_param.key=0 ; sort_param.key < share->base.keys ;
@ -2226,7 +2254,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
param->retry_repair=1;
goto err;
}
param->calc_checksum=0; /* No need to calc glob_crc */
/* No need to calculate checksum again. */
sort_param.calc_checksum= 0;
free_root(&sort_param.wordroot, MYF(0));
/* Set for next loop */
@ -2390,6 +2419,28 @@ err:
Each key is handled by a separate thread.
TODO: make a number of threads a parameter
In parallel repair we use one thread per index. There are two modes:
Quick
Only the indexes are rebuilt. All threads share a read buffer.
Every thread that needs fresh data in the buffer enters the shared
cache lock. The last thread joining the lock reads the buffer from
the data file and wakes all other threads.
Non-quick
The data file is rebuilt and all indexes are rebuilt to point to
the new record positions. One thread is the master thread. It
reads from the old data file and writes to the new data file. It
also creates one of the indexes. The other threads read from a
buffer which is filled by the master. If they need fresh data,
they enter the shared cache lock. If the masters write buffer is
full, it flushes it to the new data file and enters the shared
cache lock too. When all threads joined in the lock, the master
copies its write buffer to the read buffer for the other threads
and wakes them.
RESULT
0 ok
<>0 Error
@ -2412,6 +2463,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
ulong *rec_per_key_part;
HA_KEYSEG *keyseg;
char llbuff[22];
IO_CACHE new_data_cache; /* For non-quick repair. */
IO_CACHE_SHARE io_share;
SORT_INFO sort_info;
ulonglong key_map=share->state.key_map;
@ -2433,19 +2485,55 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|=T_CALC_CHECKSUM;
/*
Quick repair (not touching data file, rebuilding indexes):
{
Read cache is (MI_CHECK *param)->read_cache using info->dfile.
}
Non-quick repair (rebuilding data file and indexes):
{
Master thread:
Read cache is (MI_CHECK *param)->read_cache using info->dfile.
Write cache is (MI_INFO *info)->rec_cache using new_file.
Slave threads:
Read cache is new_data_cache synced to master rec_cache.
The final assignment of the filedescriptor for rec_cache is done
after the cache creation.
Don't check file size on new_data_cache, as the resulting file size
is not known yet.
As rec_cache and new_data_cache are synced, write_buffer_length is
used for the read cache 'new_data_cache'. Both start at the same
position 'new_header_length'.
}
*/
DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
bzero((char*)&sort_info,sizeof(sort_info));
/* Initialize pthread structures before goto err. */
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&sort_info.cond, 0);
if (!(sort_info.key_block=
alloc_key_blocks(param,
(uint) param->sort_key_blocks,
share->base.max_key_block_length))
|| init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) ||
(! rep_quick &&
init_io_cache(&info->rec_cache,info->dfile,
(uint) param->write_buffer_length,
WRITE_CACHE,new_header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw)))
alloc_key_blocks(param, (uint) param->sort_key_blocks,
share->base.max_key_block_length)) ||
init_io_cache(&param->read_cache, info->dfile,
(uint) param->read_buffer_length,
READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)) ||
(!rep_quick &&
(init_io_cache(&info->rec_cache, info->dfile,
(uint) param->write_buffer_length,
WRITE_CACHE, new_header_length, 1,
MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw) ||
init_io_cache(&new_data_cache, -1,
(uint) param->write_buffer_length,
READ_CACHE, new_header_length, 1,
MYF(MY_WME | MY_DONT_CHECK_FILESIZE)))))
goto err;
sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks;
info->opt_flag|=WRITE_CACHE_USED;
@ -2536,8 +2624,6 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
del=info->state->del;
param->glob_crc=0;
if (param->testflag & T_CALC_CHECKSUM)
param->calc_checksum=1;
if (!(sort_param=(MI_SORT_PARAM *)
my_malloc((uint) share->base.keys *
@ -2587,6 +2673,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].sort_info=&sort_info;
sort_param[i].master=0;
sort_param[i].fix_datafile=0;
sort_param[i].calc_checksum= 0;
sort_param[i].filepos=new_header_length;
sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
@ -2624,19 +2711,45 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_info.total_keys=i;
sort_param[0].master= 1;
sort_param[0].fix_datafile= (my_bool)(! rep_quick);
sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM);
sort_info.got_error=0;
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&sort_info.cond, 0);
pthread_mutex_lock(&sort_info.mutex);
init_io_cache_share(&param->read_cache, &io_share, i);
/*
Initialize the I/O cache share for use with the read caches and, in
case of non-quick repair, the write cache. When all threads join on
the cache lock, the writer copies the write cache contents to the
read caches.
*/
if (i > 1)
{
if (rep_quick)
init_io_cache_share(&param->read_cache, &io_share, NULL, i);
else
init_io_cache_share(&new_data_cache, &io_share, &info->rec_cache, i);
}
else
io_share.total_threads= 0; /* share not used */
(void) pthread_attr_init(&thr_attr);
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
for (i=0 ; i < sort_info.total_keys ; i++)
{
sort_param[i].read_cache=param->read_cache;
/*
Copy the properly initialized IO_CACHE structure so that every
thread has its own copy. In quick mode param->read_cache is shared
for use by all threads. In non-quick mode all threads but the
first copy the shared new_data_cache, which is synchronized to the
write cache of the first thread. The first thread copies
param->read_cache, which is not shared.
*/
sort_param[i].read_cache= ((rep_quick || !i) ? param->read_cache :
new_data_cache);
DBUG_PRINT("io_cache_share", ("thread: %u read_cache: 0x%lx",
i, (long) &sort_param[i].read_cache));
/*
two approaches: the same amount of memory for each thread
or the memory for the same number of keys for each thread...
@ -2654,7 +2767,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
(void *) (sort_param+i)))
{
mi_check_print_error(param,"Cannot start a repair thread");
remove_io_thread(&param->read_cache);
/* Cleanup: Detach from the share. Avoid others to be blocked. */
if (io_share.total_threads)
remove_io_thread(&sort_param[i].read_cache);
DBUG_PRINT("error", ("Cannot start a repair thread"));
sort_info.got_error=1;
}
else
@ -2676,6 +2792,11 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
if (sort_param[0].fix_datafile)
{
/*
Append some nuls to the end of a memory mapped file. Destroy the
write cache. The master thread did already detach from the share
by remove_io_thread() in sort.c:thr_find_all_keys().
*/
if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache))
goto err;
if (param->testflag & T_SAFE_REPAIR)
@ -2691,8 +2812,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param->filepos;
/* Only whole records */
share->state.version=(ulong) time((time_t*) 0);
/*
Exchange the data file descriptor of the table, so that we use the
new file from now on.
*/
my_close(info->dfile,MYF(0));
info->dfile=new_file;
share->data_file_type=sort_info.new_data_file_type;
share->pack.header_length=(ulong) new_header_length;
}
@ -2747,7 +2874,20 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
err:
got_error|= flush_blocks(param, share->key_cache, share->kfile);
/*
Destroy the write cache. The master thread did already detach from
the share by remove_io_thread() or it was not yet started (if the
error happend before creating the thread).
*/
VOID(end_io_cache(&info->rec_cache));
/*
Destroy the new data cache in case of non-quick repair. All slave
threads did either detach from the share by remove_io_thread()
already or they were not yet started (if the error happend before
creating the threads).
*/
if (!rep_quick)
VOID(end_io_cache(&new_data_cache));
if (!got_error)
{
/* Replace the actual file with the temporary file */
@ -2879,12 +3019,41 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
} /* sort_ft_key_read */
/* Read next record from file using parameters in sort_info */
/* Return -1 if end of file, 0 if ok and > 0 if error */
/*
Read next record from file using parameters in sort_info.
SYNOPSIS
sort_get_next_record()
sort_param Information about and for the sort process
NOTE
Dynamic Records With Non-Quick Parallel Repair
For non-quick parallel repair we use a synchronized read/write
cache. This means that one thread is the master who fixes the data
file by reading each record from the old data file and writing it
to the new data file. By doing this the records in the new data
file are written contiguously. Whenever the write buffer is full,
it is copied to the read buffer. The slaves read from the read
buffer, which is not associated with a file. Thus read_cache.file
is -1. When using _mi_read_cache(), the slaves must always set
flag to READING_NEXT so that the function never tries to read from
file. This is safe because the records are contiguous. There is no
need to read outside the cache. This condition is evaluated in the
variable 'parallel_flag' for quick reference. read_cache.file must
be >= 0 in every other case.
RETURN
-1 end of file
0 ok
> 0 error
*/
static int sort_get_next_record(MI_SORT_PARAM *sort_param)
{
int searching;
int parallel_flag;
uint found_record,b_type,left_length;
my_off_t pos;
byte *to;
@ -2922,7 +3091,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
sort_param->max_pos=(sort_param->pos+=share->base.pack_reclength);
if (*sort_param->record)
{
if (param->calc_checksum)
if (sort_param->calc_checksum)
param->glob_crc+= (info->checksum=
mi_static_checksum(info,sort_param->record));
DBUG_RETURN(0);
@ -2937,6 +3106,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
LINT_INIT(to);
pos=sort_param->pos;
searching=(sort_param->fix_datafile && (param->testflag & T_EXTEND));
parallel_flag= (sort_param->read_cache.file < 0) ? READING_NEXT : 0;
for (;;)
{
found_record=block_info.second_read= 0;
@ -2967,7 +3137,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
(byte*) block_info.header,pos,
MI_BLOCK_INFO_HEADER_LENGTH,
(! found_record ? READING_NEXT : 0) |
READING_HEADER))
parallel_flag | READING_HEADER))
{
if (found_record)
{
@ -3144,9 +3314,31 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
llstr(sort_param->start_recpos,llbuff));
goto try_next;
}
if (_mi_read_cache(&sort_param->read_cache,to,block_info.filepos,
block_info.data_len,
(found_record == 1 ? READING_NEXT : 0)))
/*
Copy information that is already read. Avoid accessing data
below the cache start. This could happen if the header
streched over the end of the previous buffer contents.
*/
{
uint header_len= (uint) (block_info.filepos - pos);
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
if (prefetch_len > block_info.data_len)
prefetch_len= block_info.data_len;
if (prefetch_len)
{
memcpy(to, block_info.header + header_len, prefetch_len);
block_info.filepos+= prefetch_len;
block_info.data_len-= prefetch_len;
left_length-= prefetch_len;
to+= prefetch_len;
}
}
if (block_info.data_len &&
_mi_read_cache(&sort_param->read_cache,to,block_info.filepos,
block_info.data_len,
(found_record == 1 ? READING_NEXT : 0) |
parallel_flag))
{
mi_check_print_info(param,
"Read error for block at: %s (error: %d); Skipped",
@ -3176,13 +3368,14 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
{
if (sort_param->read_cache.error < 0)
DBUG_RETURN(1);
if (info->s->calc_checksum)
info->checksum=mi_checksum(info,sort_param->record);
if (sort_param->calc_checksum)
info->checksum= mi_checksum(info, sort_param->record);
if ((param->testflag & (T_EXTEND | T_REP)) || searching)
{
if (_mi_rec_check(info, sort_param->record, sort_param->rec_buff,
sort_param->find_length,
(param->testflag & T_QUICK) &&
sort_param->calc_checksum &&
test(info->s->calc_checksum)))
{
mi_check_print_info(param,"Found wrong packed record at %s",
@ -3190,7 +3383,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
goto try_next;
}
}
if (param->calc_checksum)
if (sort_param->calc_checksum)
param->glob_crc+= info->checksum;
DBUG_RETURN(0);
}
@ -3217,7 +3410,8 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
DBUG_RETURN(1); /* Something wrong with data */
}
sort_param->start_recpos=sort_param->pos;
if (_mi_pack_get_block_info(info,&block_info,-1,sort_param->pos))
if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
&sort_param->rec_buff, -1, sort_param->pos))
DBUG_RETURN(-1);
if (!block_info.rec_len &&
sort_param->pos + MEMMAP_EXTRA_MARGIN ==
@ -3241,15 +3435,14 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
llstr(sort_param->pos,llbuff));
continue;
}
if (_mi_pack_rec_unpack(info,sort_param->record,sort_param->rec_buff,
block_info.rec_len))
if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
sort_param->rec_buff, block_info.rec_len))
{
if (! searching)
mi_check_print_info(param,"Found wrong record at %s",
llstr(sort_param->pos,llbuff));
continue;
}
info->checksum=mi_checksum(info,sort_param->record);
if (!sort_param->fix_datafile)
{
sort_param->filepos=sort_param->pos;
@ -3259,8 +3452,9 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
sort_param->max_pos=(sort_param->pos=block_info.filepos+
block_info.rec_len);
info->packed_length=block_info.rec_len;
if (param->calc_checksum)
param->glob_crc+= info->checksum;
if (sort_param->calc_checksum)
param->glob_crc+= (info->checksum=
mi_checksum(info, sort_param->record));
DBUG_RETURN(0);
}
}
@ -3268,7 +3462,20 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
}
/* Write record to new file */
/*
Write record to new file.
SYNOPSIS
sort_write_record()
sort_param Sort parameters.
NOTE
This is only called by a master thread if parallel repair is used.
RETURN
0 OK
1 Error
*/
int sort_write_record(MI_SORT_PARAM *sort_param)
{
@ -3317,6 +3524,7 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
}
from=sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
}
/* We can use info->checksum here as only one thread calls this. */
info->checksum=mi_checksum(info,sort_param->record);
reclength=_mi_rec_pack(info,from,sort_param->record);
flag=0;
@ -3726,7 +3934,7 @@ static int sort_delete_record(MI_SORT_PARAM *sort_param)
DBUG_RETURN(1);
}
}
if (param->calc_checksum)
if (sort_param->calc_checksum)
param->glob_crc-=(*info->s->calc_checksum)(info, sort_param->record);
}
error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);

View file

@ -219,7 +219,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
(my_disable_locking && share->state.open_count))))
{
DBUG_PRINT("error",("Table is marked as crashed"));
DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u "
"changed: %u open_count: %u !locking: %d",
open_flags, share->state.changed,
share->state.open_count, my_disable_locking));
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
goto err;

View file

@ -103,7 +103,8 @@ static uint fill_and_get_bits(MI_BIT_BUFF *bit_buff,uint count);
static void fill_buffer(MI_BIT_BUFF *bit_buff);
static uint max_bit(uint value);
#ifdef HAVE_MMAP
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff,
MI_BLOCK_INFO *info, byte **rec_buff_p,
uchar *header);
#endif
@ -449,13 +450,15 @@ int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, byte *buf)
DBUG_RETURN(-1); /* _search() didn't find record */
file=info->dfile;
if (_mi_pack_get_block_info(info, &block_info, file, filepos))
if (_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
&info->rec_buff, file, filepos))
goto err;
if (my_read(file,(byte*) info->rec_buff + block_info.offset ,
block_info.rec_len - block_info.offset, MYF(MY_NABP)))
goto panic;
info->update|= HA_STATE_AKTIV;
DBUG_RETURN(_mi_pack_rec_unpack(info,buf,info->rec_buff,block_info.rec_len));
DBUG_RETURN(_mi_pack_rec_unpack(info, &info->bit_buff, buf,
info->rec_buff, block_info.rec_len));
panic:
my_errno=HA_ERR_WRONG_IN_RECORD;
err:
@ -464,8 +467,8 @@ err:
int _mi_pack_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
ulong reclength)
int _mi_pack_rec_unpack(register MI_INFO *info, MI_BIT_BUFF *bit_buff,
register byte *to, byte *from, ulong reclength)
{
byte *end_field;
reg3 MI_COLUMNDEF *end;
@ -473,18 +476,18 @@ int _mi_pack_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
MYISAM_SHARE *share=info->s;
DBUG_ENTER("_mi_pack_rec_unpack");
init_bit_buffer(&info->bit_buff, (uchar*) from,reclength);
init_bit_buffer(bit_buff, (uchar*) from, reclength);
for (current_field=share->rec, end=current_field+share->base.fields ;
current_field < end ;
current_field++,to=end_field)
{
end_field=to+current_field->length;
(*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to,
(*current_field->unpack)(current_field, bit_buff, (uchar*) to,
(uchar*) end_field);
}
if (! info->bit_buff.error &&
info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end)
if (!bit_buff->error &&
bit_buff->pos - bit_buff->bits / 8 == bit_buff->end)
DBUG_RETURN(0);
info->update&= ~HA_STATE_AKTIV;
DBUG_RETURN(my_errno=HA_ERR_WRONG_IN_RECORD);
@ -1015,13 +1018,16 @@ int _mi_read_rnd_pack_record(MI_INFO *info, byte *buf,
if (info->opt_flag & READ_CACHE_USED)
{
if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
share->pack.ref_length, skip_deleted_blocks))
if (_mi_read_cache(&info->rec_cache, (byte*) block_info.header,
filepos, share->pack.ref_length,
skip_deleted_blocks ? READING_NEXT : 0))
goto err;
b_type=_mi_pack_get_block_info(info,&block_info,-1, filepos);
b_type=_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
&info->rec_buff, -1, filepos);
}
else
b_type=_mi_pack_get_block_info(info,&block_info,info->dfile,filepos);
b_type=_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
&info->rec_buff, info->dfile, filepos);
if (b_type)
goto err; /* Error code is already set */
#ifndef DBUG_OFF
@ -1034,9 +1040,9 @@ int _mi_read_rnd_pack_record(MI_INFO *info, byte *buf,
if (info->opt_flag & READ_CACHE_USED)
{
if (_mi_read_cache(&info->rec_cache,(byte*) info->rec_buff,
block_info.filepos, block_info.rec_len,
skip_deleted_blocks))
if (_mi_read_cache(&info->rec_cache, (byte*) info->rec_buff,
block_info.filepos, block_info.rec_len,
skip_deleted_blocks ? READING_NEXT : 0))
goto err;
}
else
@ -1051,8 +1057,8 @@ int _mi_read_rnd_pack_record(MI_INFO *info, byte *buf,
info->nextpos=block_info.filepos+block_info.rec_len;
info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
DBUG_RETURN (_mi_pack_rec_unpack(info,buf,info->rec_buff,
block_info.rec_len));
DBUG_RETURN (_mi_pack_rec_unpack(info, &info->bit_buff, buf,
info->rec_buff, block_info.rec_len));
err:
DBUG_RETURN(my_errno);
}
@ -1060,8 +1066,9 @@ int _mi_read_rnd_pack_record(MI_INFO *info, byte *buf,
/* Read and process header from a huff-record-file */
uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file,
my_off_t filepos)
uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff,
MI_BLOCK_INFO *info, byte **rec_buff_p,
File file, my_off_t filepos)
{
uchar *header=info->header;
uint head_length,ref_length;
@ -1086,17 +1093,17 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file,
head_length+= read_pack_length((uint) myisam->s->pack.version,
header + head_length, &info->blob_len);
if (!(mi_alloc_rec_buff(myisam,info->rec_len + info->blob_len,
&myisam->rec_buff)))
rec_buff_p)))
return BLOCK_FATAL_ERROR; /* not enough memory */
myisam->bit_buff.blob_pos=(uchar*) myisam->rec_buff+info->rec_len;
myisam->bit_buff.blob_end= myisam->bit_buff.blob_pos+info->blob_len;
bit_buff->blob_pos= (uchar*) *rec_buff_p + info->rec_len;
bit_buff->blob_end= bit_buff->blob_pos + info->blob_len;
myisam->blob_length=info->blob_len;
}
info->filepos=filepos+head_length;
if (file > 0)
{
info->offset=min(info->rec_len, ref_length - head_length);
memcpy(myisam->rec_buff, header+head_length, info->offset);
memcpy(*rec_buff_p, header + head_length, info->offset);
}
return 0;
}
@ -1214,7 +1221,8 @@ void _mi_unmap_file(MI_INFO *info)
}
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff,
MI_BLOCK_INFO *info, byte **rec_buff_p,
uchar *header)
{
header+= read_pack_length((uint) myisam->s->pack.version, header,
@ -1225,10 +1233,10 @@ static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
&info->blob_len);
/* mi_alloc_rec_buff sets my_errno on error */
if (!(mi_alloc_rec_buff(myisam, info->blob_len,
&myisam->rec_buff)))
rec_buff_p)))
return 0; /* not enough memory */
myisam->bit_buff.blob_pos=(uchar*) myisam->rec_buff;
myisam->bit_buff.blob_end= (uchar*) myisam->rec_buff + info->blob_len;
bit_buff->blob_pos= (uchar*) *rec_buff_p;
bit_buff->blob_end= (uchar*) *rec_buff_p + info->blob_len;
}
return header;
}
@ -1244,11 +1252,13 @@ static int _mi_read_mempack_record(MI_INFO *info, my_off_t filepos, byte *buf)
if (filepos == HA_OFFSET_ERROR)
DBUG_RETURN(-1); /* _search() didn't find record */
if (!(pos= (byte*) _mi_mempack_get_block_info(info,&block_info,
if (!(pos= (byte*) _mi_mempack_get_block_info(info, &info->bit_buff,
&block_info, &info->rec_buff,
(uchar*) share->file_map+
filepos)))
DBUG_RETURN(-1);
DBUG_RETURN(_mi_pack_rec_unpack(info, buf, pos, block_info.rec_len));
DBUG_RETURN(_mi_pack_rec_unpack(info, &info->bit_buff, buf,
pos, block_info.rec_len));
}
@ -1268,7 +1278,8 @@ static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf,
my_errno=HA_ERR_END_OF_FILE;
goto err;
}
if (!(pos= (byte*) _mi_mempack_get_block_info(info,&block_info,
if (!(pos= (byte*) _mi_mempack_get_block_info(info, &info->bit_buff,
&block_info, &info->rec_buff,
(uchar*)
(start=share->file_map+
filepos))))
@ -1285,7 +1296,8 @@ static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf,
info->nextpos=filepos+(uint) (pos-start)+block_info.rec_len;
info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
DBUG_RETURN (_mi_pack_rec_unpack(info,buf,pos, block_info.rec_len));
DBUG_RETURN (_mi_pack_rec_unpack(info, &info->bit_buff, buf,
pos, block_info.rec_len));
err:
DBUG_RETURN(my_errno);
}

View file

@ -71,6 +71,21 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
uchar * key_buff;
uint start_key_len;
/*
The problem is that the optimizer doesn't support
RTree keys properly at the moment.
Hope this will be fixed some day.
But now NULL in the min_key means that we
didn't make the task for the RTree key
and expect BTree functionality from it.
As it's not able to handle such request
we return the error.
*/
if (!min_key)
{
res= HA_POS_ERROR;
break;
}
key_buff= info->lastkey+info->s->base.max_key_length;
start_key_len= _mi_pack_key(info,inx, key_buff,
(uchar*) min_key->key, min_key->length,

View file

@ -76,6 +76,7 @@ typedef struct st_mi_state_info
ulong sec_index_changed; /* Updated when new sec_index */
ulong sec_index_used; /* which extra index are in use */
ulonglong key_map; /* Which keys are in use */
ha_checksum checksum; /* Table checksum */
ulong version; /* timestamp of create */
time_t create_time; /* Time when created database */
time_t recover_time; /* Time for last recover */
@ -177,6 +178,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */
int (*delete_record)(struct st_myisam_info*);
int (*read_rnd)(struct st_myisam_info*, byte*, my_off_t, my_bool);
int (*compare_record)(struct st_myisam_info*, const byte *);
/* Function to use for a row checksum. */
ha_checksum (*calc_checksum)(struct st_myisam_info*, const byte *);
int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *,
const byte *record, my_off_t pos);
@ -262,7 +264,7 @@ struct st_myisam_info {
my_off_t last_keypage; /* Last key page read */
my_off_t last_search_keypage; /* Last keypage when searching */
my_off_t dupp_key_pos;
ha_checksum checksum;
ha_checksum checksum; /* Temp storage for row checksum */
/* QQ: the folloing two xxx_length fields should be removed,
as they are not compatible with parallel repair */
ulong packed_length,blob_length; /* Length of found, packed record */
@ -314,8 +316,9 @@ typedef struct st_mi_sort_param
pthread_t thr;
IO_CACHE read_cache, tempfile, tempfile_for_exceptions;
DYNAMIC_ARRAY buffpek;
/*
MI_BIT_BUFF bit_buff; /* For parallel repair of packrec. */
/*
The next two are used to collect statistics, see update_key_parts for
description.
*/
@ -326,6 +329,7 @@ typedef struct st_mi_sort_param
uint key, key_length,real_key_length,sortbuff_size;
uint maxbuffers, keys, find_length, sort_keys_length;
my_bool fix_datafile, master;
my_bool calc_checksum; /* calculate table checksum */
MI_KEYDEF *keyinfo;
HA_KEYSEG *seg;
SORT_INFO *sort_info;
@ -379,8 +383,15 @@ typedef struct st_mi_sort_param
#define mi_putint(x,y,nod) { uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y);\
mi_int2store(x,boh); }
#define mi_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
#define mi_mark_crashed(x) (x)->s->state.changed|=STATE_CRASHED
#define mi_mark_crashed_on_repair(x) { (x)->s->state.changed|=STATE_CRASHED|STATE_CRASHED_ON_REPAIR ; (x)->update|= HA_STATE_CHANGED; }
#define mi_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \
DBUG_PRINT("error", ("Marked table crashed")); \
}while(0)
#define mi_mark_crashed_on_repair(x) do{(x)->s->state.changed|= \
STATE_CRASHED|STATE_CRASHED_ON_REPAIR; \
(x)->update|= HA_STATE_CHANGED; \
DBUG_PRINT("error", \
("Marked table crashed")); \
}while(0)
#define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED)
#define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR)
#define mi_print_error(SHARE, ERRNO) \
@ -620,8 +631,8 @@ extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const uchar *key,
extern my_bool _mi_read_pack_info(MI_INFO *info,pbool fix_keys);
extern int _mi_read_pack_record(MI_INFO *info,my_off_t filepos,byte *buf);
extern int _mi_read_rnd_pack_record(MI_INFO*, byte *,my_off_t, my_bool);
extern int _mi_pack_rec_unpack(MI_INFO *info,byte *to,byte *from,
ulong reclength);
extern int _mi_pack_rec_unpack(MI_INFO *info, MI_BIT_BUFF *bit_buff,
byte *to, byte *from, ulong reclength);
extern ulonglong mi_safe_mul(ulonglong a,ulonglong b);
extern int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
const byte *oldrec, const byte *newrec, my_off_t pos);
@ -686,7 +697,9 @@ extern "C" {
extern uint _mi_get_block_info(MI_BLOCK_INFO *,File, my_off_t);
extern uint _mi_rec_pack(MI_INFO *info,byte *to,const byte *from);
extern uint _mi_pack_get_block_info(MI_INFO *, MI_BLOCK_INFO *, File, my_off_t);
extern uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff,
MI_BLOCK_INFO *info, byte **rec_buff_p,
File file, my_off_t filepos);
extern void _my_store_blob_length(byte *pos,uint pack_length,uint length);
extern void _myisam_log(enum myisam_log_commands command,MI_INFO *info,
const byte *buffert,uint length);

View file

@ -1965,7 +1965,7 @@ static char *bindigits(ulonglong value, uint bits)
DBUG_ASSERT(idx < sizeof(digits));
while (idx)
*(ptr++)= '0' + ((value >> (--idx)) & 1);
*(ptr++)= '0' + ((char) (value >> (--idx)) & (char) 1);
*ptr= '\0';
return digits;
}
@ -1995,7 +1995,7 @@ static char *hexdigits(ulonglong value)
DBUG_ASSERT(idx < sizeof(digits));
while (idx)
{
if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9')
if ((*(ptr++)= '0' + ((char) (value >> (4 * (--idx))) & (char) 0xf)) > '9')
*(ptr - 1)+= 'a' - '9' - 1;
}
*ptr= '\0';
@ -2284,7 +2284,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
errors++;
break;
}
idx+= code & 1;
idx+= (uint) code & 1;
if (idx >= length)
{
VOID(fflush(stdout));

View file

@ -3,4 +3,5 @@ MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine],
MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam])
MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a])
MYSQL_PLUGIN_MANDATORY(myisam) dnl Default
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisam, [ha_myisam.cc])

View file

@ -148,7 +148,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
skr=maxbuffer;
if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
(sort_length+sizeof(char*))) <= 1)
(sort_length+sizeof(char*))) <= 1 ||
keys < (uint) maxbuffer)
{
mi_check_print_error(info->sort_info->param,
"sort_buffer_size is to small");
@ -309,7 +310,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
pthread_handler_t thr_find_all_keys(void *arg)
{
MI_SORT_PARAM *info= (MI_SORT_PARAM*) arg;
MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
int error;
uint memavl,old_memavl,keys,sort_length;
uint idx, maxbuffer;
@ -321,32 +322,34 @@ pthread_handler_t thr_find_all_keys(void *arg)
if (my_thread_init())
goto err;
if (info->sort_info->got_error)
DBUG_ENTER("thr_find_all_keys");
DBUG_PRINT("enter", ("master: %d", sort_param->master));
if (sort_param->sort_info->got_error)
goto err;
if (info->keyinfo->flag && HA_VAR_LENGTH_KEY)
if (sort_param->keyinfo->flag && HA_VAR_LENGTH_KEY)
{
info->write_keys=write_keys_varlen;
info->read_to_buffer=read_to_buffer_varlen;
info->write_key=write_merge_key_varlen;
sort_param->write_keys= write_keys_varlen;
sort_param->read_to_buffer= read_to_buffer_varlen;
sort_param->write_key= write_merge_key_varlen;
}
else
{
info->write_keys=write_keys;
info->read_to_buffer=read_to_buffer;
info->write_key=write_merge_key;
sort_param->write_keys= write_keys;
sort_param->read_to_buffer= read_to_buffer;
sort_param->write_key= write_merge_key;
}
my_b_clear(&info->tempfile);
my_b_clear(&info->tempfile_for_exceptions);
bzero((char*) &info->buffpek,sizeof(info->buffpek));
bzero((char*) &info->unique, sizeof(info->unique));
my_b_clear(&sort_param->tempfile);
my_b_clear(&sort_param->tempfile_for_exceptions);
bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
sort_keys= (uchar **) NULL;
memavl=max(info->sortbuff_size, MIN_SORT_MEMORY);
idx= info->sort_info->max_records;
sort_length= info->key_length;
maxbuffer= 1;
memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY);
idx= sort_param->sort_info->max_records;
sort_length= sort_param->key_length;
maxbuffer= 1;
while (memavl >= MIN_SORT_MEMORY)
{
@ -361,20 +364,22 @@ pthread_handler_t thr_find_all_keys(void *arg)
skr=maxbuffer;
if (memavl < sizeof(BUFFPEK)*maxbuffer ||
(keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
(sort_length+sizeof(char*))) <= 1)
(sort_length+sizeof(char*))) <= 1 ||
keys < (uint) maxbuffer)
{
mi_check_print_error(info->sort_info->param,
mi_check_print_error(sort_param->sort_info->param,
"sort_buffer_size is to small");
goto err;
}
}
while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+
((info->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
if ((sort_keys= (uchar**)
my_malloc(keys*(sort_length+sizeof(char*))+
((sort_param->keyinfo->flag & HA_FULLTEXT) ?
HA_FT_MAXBYTELEN : 0), MYF(0))))
{
if (my_init_dynamic_array(&info->buffpek, sizeof(BUFFPEK),
if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
maxbuffer, maxbuffer/2))
{
my_free((gptr) sort_keys,MYF(0));
@ -389,70 +394,88 @@ pthread_handler_t thr_find_all_keys(void *arg)
}
if (memavl < MIN_SORT_MEMORY)
{
mi_check_print_error(info->sort_info->param,"Sort buffer to small"); /* purecov: tested */
mi_check_print_error(sort_param->sort_info->param, "Sort buffer too small");
goto err; /* purecov: tested */
}
if (info->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %d keys\n",info->key+1,keys);
info->sort_keys=sort_keys;
if (sort_param->sort_info->param->testflag & T_VERBOSE)
printf("Key %d - Allocating buffer for %d keys\n",
sort_param->key + 1, keys);
sort_param->sort_keys= sort_keys;
idx=error=0;
sort_keys[0]=(uchar*) (sort_keys+keys);
while (!(error=info->sort_info->got_error) &&
!(error=(*info->key_read)(info,sort_keys[idx])))
DBUG_PRINT("info", ("reading keys"));
while (!(error= sort_param->sort_info->got_error) &&
!(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
{
if (info->real_key_length > info->key_length)
if (sort_param->real_key_length > sort_param->key_length)
{
if (write_key(info,sort_keys[idx], &info->tempfile_for_exceptions))
if (write_key(sort_param, sort_keys[idx],
&sort_param->tempfile_for_exceptions))
goto err;
continue;
}
if (++idx == keys)
{
if (info->write_keys(info,sort_keys,idx-1,
(BUFFPEK *)alloc_dynamic(&info->buffpek),
&info->tempfile))
if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
sort_keys[0]=(uchar*) (sort_keys+keys);
memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length);
memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
idx=1;
}
sort_keys[idx]=sort_keys[idx-1]+info->key_length;
sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
}
if (error > 0)
goto err;
if (info->buffpek.elements)
if (sort_param->buffpek.elements)
{
if (info->write_keys(info,sort_keys, idx,
(BUFFPEK *) alloc_dynamic(&info->buffpek), &info->tempfile))
if (sort_param->write_keys(sort_param, sort_keys, idx,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
info->keys=(info->buffpek.elements-1)*(keys-1)+idx;
sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
}
else
info->keys=idx;
sort_param->keys= idx;
info->sort_keys_length=keys;
sort_param->sort_keys_length= keys;
goto ok;
err:
info->sort_info->got_error=1; /* no need to protect this with a mutex */
DBUG_PRINT("error", ("got some error"));
sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
if (sort_keys)
my_free((gptr) sort_keys,MYF(0));
info->sort_keys=0;
delete_dynamic(& info->buffpek);
close_cached_file(&info->tempfile);
close_cached_file(&info->tempfile_for_exceptions);
sort_param->sort_keys= 0;
delete_dynamic(& sort_param->buffpek);
close_cached_file(&sort_param->tempfile);
close_cached_file(&sort_param->tempfile_for_exceptions);
ok:
free_root(&info->wordroot, MYF(0));
remove_io_thread(&info->read_cache);
pthread_mutex_lock(&info->sort_info->mutex);
info->sort_info->threads_running--;
pthread_cond_signal(&info->sort_info->cond);
pthread_mutex_unlock(&info->sort_info->mutex);
free_root(&sort_param->wordroot, MYF(0));
/*
Detach from the share if the writer is involved. Avoid others to
be blocked. This includes a flush of the write buffer. This will
also indicate EOF to the readers.
*/
if (sort_param->sort_info->info->rec_cache.share)
remove_io_thread(&sort_param->sort_info->info->rec_cache);
/* Readers detach from the share if any. Avoid others to be blocked. */
if (sort_param->read_cache.share)
remove_io_thread(&sort_param->read_cache);
pthread_mutex_lock(&sort_param->sort_info->mutex);
if (!--sort_param->sort_info->threads_running)
pthread_cond_signal(&sort_param->sort_info->cond);
pthread_mutex_unlock(&sort_param->sort_info->mutex);
DBUG_PRINT("exit", ("======== ending thread ========"));
my_thread_end();
return NULL;
}
@ -470,6 +493,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
MYISAM_SHARE *share=info->s;
MI_SORT_PARAM *sinfo;
byte *mergebuf=0;
DBUG_ENTER("thr_write_keys");
LINT_INIT(length);
for (i= 0, sinfo= sort_param ;
@ -479,6 +503,8 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
if (!sinfo->sort_keys)
{
got_error=1;
my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff),
MYF(MY_ALLOW_ZERO_PTR));
continue;
}
if (!got_error)
@ -606,7 +632,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
}
}
my_free((gptr) mergebuf,MYF(MY_ALLOW_ZERO_PTR));
return got_error;
DBUG_RETURN(got_error);
}
#endif /* THREAD */

View file

@ -3,3 +3,4 @@ MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine],
MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg])
MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg.a])
MYSQL_PLUGIN_MANDATORY(myisammrg)
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisammrg, [ha_myisammrg.cc])

View file

@ -75,7 +75,7 @@ Dbtup::dump_disk_alloc(Dbtup::Disk_alloc_info & alloc)
for(Uint32 i = 0; i<MAX_FREE_LIST; i++)
{
printf(" %d : ", i);
Ptr<Page> ptr;
PagePtr ptr;
ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
LocalDLList<Page> list(*pool, alloc.m_dirty_pages[i]);
for(list.first(ptr); !ptr.isNull(); list.next(ptr))
@ -262,7 +262,7 @@ Dbtup::update_extent_pos(Disk_alloc_info& alloc,
}
void
Dbtup::restart_setup_page(Disk_alloc_info& alloc, Ptr<Page> pagePtr)
Dbtup::restart_setup_page(Disk_alloc_info& alloc, PagePtr pagePtr)
{
/**
* Link to extent, clear uncommitted_used_space
@ -344,12 +344,15 @@ Dbtup::disk_page_prealloc(Signal* signal,
if (!alloc.m_dirty_pages[i].isEmpty())
{
ptrI= alloc.m_dirty_pages[i].firstItem;
Ptr<GlobalPage> page;
m_global_page_pool.getPtr(page, ptrI);
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, ptrI);
disk_page_prealloc_dirty_page(alloc, *(PagePtr*)&page, i, sz);
key->m_page_no= ((Page*)page.p)->m_page_no;
key->m_file_no= ((Page*)page.p)->m_file_no;
PagePtr tmp;
tmp.i = gpage.i;
tmp.p = reinterpret_cast<Page*>(gpage.p);
disk_page_prealloc_dirty_page(alloc, tmp, i, sz);
key->m_page_no= tmp.p->m_page_no;
key->m_file_no= tmp.p->m_file_no;
if (DBG_DISK)
ndbout << " found dirty page " << *key << endl;
return 0; // Page in memory
@ -547,7 +550,7 @@ Dbtup::disk_page_prealloc(Signal* signal,
void
Dbtup::disk_page_prealloc_dirty_page(Disk_alloc_info & alloc,
Ptr<Page> pagePtr,
PagePtr pagePtr,
Uint32 old_idx, Uint32 sz)
{
ddassert(pagePtr.p->list_index == old_idx);
@ -638,7 +641,9 @@ Dbtup::disk_page_prealloc_callback(Signal* signal,
fragPtr.i= req.p->m_frag_ptr_i;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
Ptr<Page> pagePtr = *(Ptr<Page>*)&gpage;
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
if (unlikely(pagePtr.p->m_restart_seq != globalData.m_restart_seq))
{
@ -666,7 +671,9 @@ Dbtup::disk_page_prealloc_initial_callback(Signal*signal,
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, page_id);
Ptr<Page> pagePtr = *(Ptr<Page>*)&gpage;
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
Ptr<Fragrecord> fragPtr;
fragPtr.i= req.p->m_frag_ptr_i;
@ -705,7 +712,7 @@ void
Dbtup::disk_page_prealloc_callback_common(Signal* signal,
Ptr<Page_request> req,
Ptr<Fragrecord> fragPtr,
Ptr<Page> pagePtr)
PagePtr pagePtr)
{
/**
* 1) remove page request from Disk_alloc_info.m_page_requests
@ -736,7 +743,7 @@ Dbtup::disk_page_prealloc_callback_common(Signal* signal,
*/
ArrayPool<Page> *cheat_pool= (ArrayPool<Page>*)&m_global_page_pool;
LocalDLList<Page> list(* cheat_pool, alloc.m_dirty_pages[new_idx]);
list.add(*(Ptr<Page>*)&pagePtr);
list.add(pagePtr);
pagePtr.p->uncommitted_used_space = real_used;
pagePtr.p->list_index = new_idx;
@ -765,7 +772,7 @@ Dbtup::disk_page_prealloc_callback_common(Signal* signal,
}
void
Dbtup::disk_page_set_dirty(Ptr<Page> pagePtr)
Dbtup::disk_page_set_dirty(PagePtr pagePtr)
{
Uint32 idx = pagePtr.p->list_index;
if ((idx & 0x8000) == 0)
@ -833,7 +840,9 @@ Dbtup::disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count)
{
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, page_id);
PagePtr pagePtr= *(PagePtr*)&gpage;
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
Uint32 type = pagePtr.p->m_page_header.m_page_type;
if (unlikely((type != File_formats::PT_Tup_fixsize_page &&
@ -1028,10 +1037,13 @@ Dbtup::disk_page_abort_prealloc(Signal *signal, Fragrecord* fragPtrP,
case -1:
break;
default:
Ptr<GlobalPage> page;
m_global_page_pool.getPtr(page, (Uint32)res);
disk_page_abort_prealloc_callback_1(signal, fragPtrP, *(PagePtr*)&page,
sz);
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, (Uint32)res);
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
disk_page_abort_prealloc_callback_1(signal, fragPtrP, pagePtr, sz);
}
}
@ -1044,8 +1056,10 @@ Dbtup::disk_page_abort_prealloc_callback(Signal* signal,
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, page_id);
PagePtr pagePtr= *(PagePtr*)&gpage;
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
Ptr<Tablerec> tabPtr;
tabPtr.i= pagePtr.p->m_table_id;
ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
@ -1308,7 +1322,9 @@ Dbtup::disk_restart_undo_callback(Signal* signal,
jamEntry();
Ptr<GlobalPage> gpage;
m_global_page_pool.getPtr(gpage, page_id);
Ptr<Page> pagePtr = *(Ptr<Page>*)&gpage;
PagePtr pagePtr;
pagePtr.i = gpage.i;
pagePtr.p = reinterpret_cast<Page*>(gpage.p);
Apply_undo* undo = &f_undo;

View file

@ -1039,22 +1039,19 @@ int Dbtup::handleUpdateReq(Signal* signal,
tup_version= (tup_version + 1) & ZTUP_VERSION_MASK;
operPtrP->tupVersion= tup_version;
int retValue;
if (!req_struct->interpreted_exec) {
jam();
retValue= updateAttributes(req_struct,
&cinBuffer[0],
req_struct->attrinfo_len);
int retValue = updateAttributes(req_struct,
&cinBuffer[0],
req_struct->attrinfo_len);
if (unlikely(retValue == -1))
goto error;
} else {
jam();
if (unlikely(interpreterStartLab(signal, req_struct) == -1))
return -1;
}
if (retValue == -1) {
goto error;
}
if (regTabPtr->need_shrink())
{
shrink_tuple(req_struct, sizes+2, regTabPtr, disk);
@ -1073,7 +1070,7 @@ int Dbtup::handleUpdateReq(Signal* signal,
jam();
setChecksum(req_struct->m_tuple_ptr, regTabPtr);
}
return retValue;
return 0;
error:
tupkeyErrorLab(signal);

View file

@ -305,7 +305,11 @@ inline
bool
RecordPool<T, P>::seize(Ptr<T> & ptr)
{
return m_pool.seize(*(Ptr<void>*)&ptr);
Ptr<void> tmp;
bool ret = m_pool.seize(tmp);
ptr.i = tmp.i;
ptr.p = static_cast<T*>(tmp.p);
return ret;
}
template <typename T, typename P>

View file

@ -366,7 +366,29 @@ NdbTransaction::execute(ExecType aTypeOfExec,
* operations, making postExecute impossible
*/
if (abortOption == AO_IgnoreError)
{
if (theCompletedFirstOp != NULL)
{
if (tCompletedFirstOp != NULL)
{
tCompletedLastOp->next(theCompletedFirstOp);
theCompletedFirstOp = tCompletedFirstOp;
}
}
else
{
theCompletedFirstOp = tCompletedFirstOp;
theCompletedLastOp = tCompletedLastOp;
}
if (tPrepOp != NULL && tRestOp != NULL) {
if (theFirstOpInList == NULL)
theFirstOpInList = tRestOp;
else
theLastOpInList->next(tRestOp);
theLastOpInList = tLastOp;
}
DBUG_RETURN(-1);
}
}
#ifdef ndb_api_crash_on_complex_blob_abort

View file

@ -33,7 +33,7 @@ typedef struct charset_info_st
uint strxfrm_multiply;
uint mbminlen;
uint mbmaxlen;
char max_sort_char; /* For LIKE optimization */
uint16 max_sort_char; /* For LIKE optimization */
MY_CHARSET_HANDLER *cset;
MY_COLLATION_HANDLER *coll;
@ -134,7 +134,15 @@ Misc fields
mbmaxlen - maximum multibyte sequence length.
1 for 8bit charsets. Can be also 2 or 3.
max_sort_char - for LIKE range
in case of 8bit character sets - native code
of maximum character (max_str pad byte);
in case of UTF8 and UCS2 - Unicode code of the maximum
possible character (usually U+FFFF). This code is
converted to multibyte representation (usually 0xEFBFBF)
and then used as a pad sequence for max_str.
in case of other multibyte character sets -
max_str pad byte (usually 0xFF).
MY_CHARSET_HANDLER
==================

View file

@ -474,15 +474,35 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
/*
Write max key: create a buffer with multibyte
representation of the max_sort_char character,
and copy it into max_str in a loop.
Fill the given buffer with 'maximum character' for given charset
SYNOPSIS
pad_max_char()
cs Character set
str Start of buffer to fill
end End of buffer to fill
DESCRIPTION
Write max key:
- for non-Unicode character sets:
just set to 255.
- for Unicode character set (utf-8):
create a buffer with multibyte representation of the max_sort_char
character, and copy it into max_str in a loop.
*/
static void pad_max_char(CHARSET_INFO *cs, char *str, char *end)
{
char buf[10];
char buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
(uchar*) buf + sizeof(buf));
char buflen;
if (!(cs->state & MY_CS_UNICODE))
{
bfill(str, end - str, 255);
return;
}
buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
(uchar*) buf + sizeof(buf));
DBUG_ASSERT(buflen > 0);
do
{
@ -943,7 +963,7 @@ MY_COLLATION_HANDLER my_collation_mb_bin_handler =
my_strnncollsp_mb_bin,
my_strnxfrm_mb_bin,
my_strnxfrmlen_simple,
my_like_range_simple,
my_like_range_mb,
my_wildcmp_mb_bin,
my_strcasecmp_mb_bin,
my_instr_mb,

View file

@ -2615,7 +2615,7 @@ CHARSET_INFO my_charset_utf8_bin=
1, /* mbminlen */
3, /* mbmaxlen */
0, /* min_sort_char */
255, /* max_sort_char */
0xFFFF, /* max_sort_char */
' ', /* pad char */
0, /* escape_with_backslash_is_dangerous */
&my_charset_utf8_handler,

View file

@ -327,7 +327,7 @@ then
cp -fp mysql-debug-%{mysql_version}/config.log "$MYSQL_DEBUGCONFLOG_DEST"
fi
(cd mysql-debug-%{mysql_version} ; \
(cd mysql-debug-%{mysql_version}/mysql-test ; \
./mysql-test-run.pl --comment=debug --skip-rpl --skip-ndbcluster --force ; \
true)
@ -357,12 +357,13 @@ then
cp -fp mysql-release-%{mysql_version}/config.log "$MYSQL_CONFLOG_DEST"
fi
(cd mysql-release-%{mysql_version} ; \
./mysql-test-run.pl --comment=normal --force ; \
./mysql-test-run.pl --comment=ps --ps-protocol --force ; \
./mysql-test-run.pl --comment=normal+rowrepl --mysqld=--binlog-format=row --force ; \
./mysql-test-run.pl --comment=ps+rowrepl --ps-protocol --mysqld=--binlog-format=row --force ; \
true)
cd mysql-release-%{mysql_version}/mysql-test
./mysql-test-run.pl --comment=normal --force --skip-ndbcluster --timer || true
./mysql-test-run.pl --comment=ps --ps-protocol --force --skip-ndbcluster --timer || true
./mysql-test-run.pl --comment=normal+rowrepl --mysqld=--binlog-format=row --force --skip-ndbcluster --timer || true
./mysql-test-run.pl --comment=ps+rowrepl+NDB --ps-protocol --mysqld=--binlog-format=row --force --timer || true
./mysql-test-run.pl --comment=NDB --with-ndbcluster-only --force --timer || true
cd ../..
##############################################################################
@ -522,7 +523,6 @@ fi
%doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisampack.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_explain_log.1*
%doc %attr(644, root, man) %{_mandir}/man8/mysqld.8*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*

View file

@ -140,11 +140,19 @@ static signal_entry install_signal[]= {
{ SIGABRT, handle_core_signal },
{ SIGFPE, handle_core_signal },
{ SIGSEGV, handle_core_signal },
{ SIGBUS, handle_core_signal },
{ SIGXCPU, handle_core_signal },
{ SIGXFSZ, handle_core_signal },
{ SIGSYS, handle_core_signal },
{ SIGTRAP, handle_core_signal }
{ SIGBUS, handle_core_signal }
#ifdef SIGXCPU
, { SIGXCPU, handle_core_signal }
#endif
#ifdef SIGXCPU
, { SIGXFSZ, handle_core_signal }
#endif
#ifdef SIGXCPU
, { SIGSYS, handle_core_signal }
#endif
#ifdef SIGXCPU
, { SIGTRAP, handle_core_signal }
#endif
};
void