Merge mysql.com:/nfsdisk1/lars/bkroot/mysql-4.1-rpl
into mysql.com:/nfsdisk1/lars/MERGE/mysql-4.1-merge sql/item_func.cc: Auto merged
This commit is contained in:
commit
1322c4aaef
@ -167,8 +167,7 @@ check_cpu () {
|
||||
touch __test.c
|
||||
|
||||
while [ "$cpu_arg" ] ; do
|
||||
# FIXME: echo -n isn't portable - see contortions autoconf goes through
|
||||
echo -n testing $cpu_arg "... " >&2
|
||||
printf "testing $cpu_arg ... " >&2
|
||||
|
||||
# compile check
|
||||
check_cpu_cflags=`eval echo $check_cpu_args`
|
||||
|
@ -2589,6 +2589,8 @@ static char *primary_key_fields(const char *table_name)
|
||||
char show_keys_buff[15 + 64 * 2 + 3];
|
||||
uint result_length = 0;
|
||||
char *result = 0;
|
||||
char buff[NAME_LEN * 2 + 3];
|
||||
char *quoted_field;
|
||||
|
||||
my_snprintf(show_keys_buff, sizeof(show_keys_buff),
|
||||
"SHOW KEYS FROM %s", table_name);
|
||||
@ -2612,8 +2614,10 @@ static char *primary_key_fields(const char *table_name)
|
||||
{
|
||||
/* Key is unique */
|
||||
do
|
||||
result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */
|
||||
while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1);
|
||||
{
|
||||
quoted_field= quote_name(row[4], buff, 0);
|
||||
result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */
|
||||
} while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1);
|
||||
}
|
||||
|
||||
/* Build the ORDER BY clause result */
|
||||
@ -2627,9 +2631,13 @@ static char *primary_key_fields(const char *table_name)
|
||||
}
|
||||
mysql_data_seek(res, 0);
|
||||
row = mysql_fetch_row(res);
|
||||
end = strmov(result, row[4]);
|
||||
while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1)
|
||||
end = strxmov(end, ",", row[4], NullS);
|
||||
quoted_field= quote_name(row[4], buff, 0);
|
||||
end= strmov(result, quoted_field);
|
||||
while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1)
|
||||
{
|
||||
quoted_field= quote_name(row[4], buff, 0);
|
||||
end= strxmov(end, ",", quoted_field, NullS);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
@ -2990,10 +2990,14 @@ AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware")
|
||||
export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR
|
||||
ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'"
|
||||
|
||||
if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
|
||||
if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no"
|
||||
then
|
||||
AC_DEFINE([THREAD], [1],
|
||||
[Define if you want to have threaded code. This may be undef on client code])
|
||||
fi
|
||||
|
||||
if test "$with_server" != "no"
|
||||
then
|
||||
# Avoid _PROGRAMS names
|
||||
THREAD_LPROGRAMS="test_thr_alarm\$(EXEEXT) test_thr_lock\$(EXEEXT)"
|
||||
AC_SUBST(THREAD_LPROGRAMS)
|
||||
|
@ -76,7 +76,7 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
||||
and my_default_record_cache_size we get about 1/128 unused memory.
|
||||
*/
|
||||
*alloc_length=sizeof(HP_PTRS)*i+block->records_in_block* block->recbuffer;
|
||||
if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(0))))
|
||||
if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(MY_WME))))
|
||||
return 1;
|
||||
|
||||
if (i == 0)
|
||||
|
@ -68,11 +68,17 @@ int heap_write(HP_INFO *info, const byte *record)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
|
||||
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
|
||||
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
|
||||
info->errkey= keydef - share->keydef;
|
||||
if (keydef->algorithm == HA_KEY_ALG_BTREE)
|
||||
/*
|
||||
We don't need to delete non-inserted key from rb-tree. Also, if
|
||||
we got ENOMEM, the key wasn't inserted, so don't try to delete it
|
||||
either. Otherwise for HASH index on HA_ERR_FOUND_DUPP_KEY the key
|
||||
was inserted and we have to delete it.
|
||||
*/
|
||||
if (keydef->algorithm == HA_KEY_ALG_BTREE || my_errno == ENOMEM)
|
||||
{
|
||||
/* we don't need to delete non-inserted key from rb-tree */
|
||||
keydef--;
|
||||
}
|
||||
while (keydef >= share->keydef)
|
||||
|
@ -84,6 +84,42 @@
|
||||
#define NETWARE_SET_SCREEN_MODE(A)
|
||||
#endif
|
||||
|
||||
/*
|
||||
The macros below are used to allow build of Universal/fat binaries of
|
||||
MySQL and MySQL applications under darwin.
|
||||
*/
|
||||
#ifdef TARGET_FAT_BINARY
|
||||
# undef SIZEOF_CHARP
|
||||
# undef SIZEOF_INT
|
||||
# undef SIZEOF_LONG
|
||||
# undef SIZEOF_LONG_LONG
|
||||
# undef SIZEOF_OFF_T
|
||||
# undef SIZEOF_SHORT
|
||||
|
||||
#if defined(__i386__)
|
||||
# undef WORDS_BIGENDIAN
|
||||
# define SIZEOF_CHARP 4
|
||||
# define SIZEOF_INT 4
|
||||
# define SIZEOF_LONG 4
|
||||
# define SIZEOF_LONG_LONG 8
|
||||
# define SIZEOF_OFF_T 8
|
||||
# define SIZEOF_SHORT 2
|
||||
|
||||
#elif defined(__ppc__)
|
||||
# define WORDS_BIGENDIAN
|
||||
# define SIZEOF_CHARP 4
|
||||
# define SIZEOF_INT 4
|
||||
# define SIZEOF_LONG 4
|
||||
# define SIZEOF_LONG_LONG 8
|
||||
# define SIZEOF_OFF_T 8
|
||||
# define SIZEOF_SHORT 2
|
||||
|
||||
#else
|
||||
# error Building FAT binary for an unknown architecture.
|
||||
#endif
|
||||
#endif /* TARGET_FAT_BINARY */
|
||||
|
||||
|
||||
/*
|
||||
The macros below are borrowed from include/linux/compiler.h in the
|
||||
Linux kernel. Use them to indicate the likelyhood of the truthfulness
|
||||
|
@ -18,6 +18,9 @@ typedef struct hash_cell_struct hash_cell_t;
|
||||
|
||||
typedef void* hash_node_t;
|
||||
|
||||
/* Fix Bug #13859: symbol collision between imap/mysql */
|
||||
#define hash_create hash0_create
|
||||
|
||||
/*****************************************************************
|
||||
Creates a hash table with >= n array cells. The actual number
|
||||
of cells is chosen to be a prime number slightly bigger than n. */
|
||||
|
@ -124,12 +124,34 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`date_format("2004-01-19 10:10:10", "%Y-%m-%d")` binary(10) default NULL
|
||||
`date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) character set utf8 default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
select * from t1;
|
||||
date_format("2004-01-19 10:10:10", "%Y-%m-%d")
|
||||
2004-01-19
|
||||
drop table t1;
|
||||
set names utf8;
|
||||
set LC_TIME_NAMES='fr_FR';
|
||||
create table t1 (s1 char(20) character set latin1);
|
||||
insert into t1 values (date_format('2004-02-02','%M'));
|
||||
select hex(s1) from t1;
|
||||
hex(s1)
|
||||
66E97672696572
|
||||
drop table t1;
|
||||
create table t1 (s1 char(20) character set koi8r);
|
||||
set LC_TIME_NAMES='ru_RU';
|
||||
insert into t1 values (date_format('2004-02-02','%M'));
|
||||
insert into t1 values (date_format('2004-02-02','%b'));
|
||||
insert into t1 values (date_format('2004-02-02','%W'));
|
||||
insert into t1 values (date_format('2004-02-02','%a'));
|
||||
select hex(s1), s1 from t1;
|
||||
hex(s1) s1
|
||||
E6C5D7D2C1CCD1 Февраля
|
||||
E6C5D7 Фев
|
||||
F0CFCEC5C4C5CCD8CEC9CB Понедельник
|
||||
F0CEC4 Пнд
|
||||
drop table t1;
|
||||
set LC_TIME_NAMES='en_US';
|
||||
set names koi8r;
|
||||
create table t1 (s1 char(1) character set utf8);
|
||||
insert into t1 values (_koi8r'ÁÂ');
|
||||
|
@ -1584,4 +1584,66 @@ CREATE TABLE `t1` (
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
drop table t1;
|
||||
CREATE TABLE `t1` (
|
||||
`a b` INT,
|
||||
`c"d` INT,
|
||||
`e``f` INT,
|
||||
PRIMARY KEY (`a b`, `c"d`, `e``f`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (0815, 4711, 2006);
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
DROP TABLE IF EXISTS "t1";
|
||||
CREATE TABLE "t1" (
|
||||
"a b" int(11) NOT NULL default '0',
|
||||
"c""d" int(11) NOT NULL default '0',
|
||||
"e`f" int(11) NOT NULL default '0',
|
||||
PRIMARY KEY ("a b","c""d","e`f")
|
||||
);
|
||||
|
||||
LOCK TABLES "t1" WRITE;
|
||||
/*!40000 ALTER TABLE "t1" DISABLE KEYS */;
|
||||
INSERT INTO "t1" VALUES (815,4711,2006);
|
||||
/*!40000 ALTER TABLE "t1" ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
DROP TABLE IF EXISTS `t1`;
|
||||
CREATE TABLE `t1` (
|
||||
`a b` int(11) NOT NULL default '0',
|
||||
`c"d` int(11) NOT NULL default '0',
|
||||
`e``f` int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (`a b`,`c"d`,`e``f`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
LOCK TABLES `t1` WRITE;
|
||||
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
|
||||
INSERT INTO `t1` VALUES (815,4711,2006);
|
||||
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
DROP TABLE `t1`;
|
||||
End of 4.1 tests
|
||||
|
@ -1035,4 +1035,71 @@ EXECUTE stmt USING @a;
|
||||
0 0
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
CREATE TABLE t1 (i INT);
|
||||
PREPARE st_19182
|
||||
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||
EXECUTE st_19182;
|
||||
DESC t2;
|
||||
Field Type Null Key Default Extra
|
||||
j int(11) YES MUL NULL
|
||||
i int(11) YES MUL NULL
|
||||
DROP TABLE t2;
|
||||
EXECUTE st_19182;
|
||||
DESC t2;
|
||||
Field Type Null Key Default Extra
|
||||
j int(11) YES MUL NULL
|
||||
i int(11) YES MUL NULL
|
||||
DEALLOCATE PREPARE st_19182;
|
||||
DROP TABLE t2, t1;
|
||||
drop database if exists mysqltest;
|
||||
drop table if exists t1, t2;
|
||||
create database mysqltest character set utf8;
|
||||
prepare stmt1 from "create table mysqltest.t1 (c char(10))";
|
||||
prepare stmt2 from "create table mysqltest.t2 select 'test'";
|
||||
execute stmt1;
|
||||
execute stmt2;
|
||||
show create table mysqltest.t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c` char(10) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8
|
||||
show create table mysqltest.t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`test` char(4) character set latin1 NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8
|
||||
drop table mysqltest.t1;
|
||||
drop table mysqltest.t2;
|
||||
alter database mysqltest character set latin1;
|
||||
execute stmt1;
|
||||
execute stmt2;
|
||||
show create table mysqltest.t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c` char(10) character set utf8 default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
show create table mysqltest.t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`test` char(4) NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop database mysqltest;
|
||||
deallocate prepare stmt1;
|
||||
deallocate prepare stmt2;
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c` char(10) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c` char(10) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
End of 4.1 tests.
|
||||
|
16
mysql-test/r/rpl_locale.result
Normal file
16
mysql-test/r/rpl_locale.result
Normal file
@ -0,0 +1,16 @@
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
create table t1 (s1 char(10));
|
||||
set lc_time_names= 'de_DE';
|
||||
insert into t1 values (date_format('2001-01-01','%W'));
|
||||
select * from t1;
|
||||
s1
|
||||
Montag
|
||||
select * from t1;
|
||||
s1
|
||||
Montag
|
||||
drop table t1;
|
@ -499,6 +499,63 @@ set names latin1;
|
||||
select @@have_innodb;
|
||||
@@have_innodb
|
||||
#
|
||||
*** Various tests with LC_TIME_NAMES
|
||||
*** LC_TIME_NAMES: testing case insensitivity
|
||||
set @@lc_time_names='ru_ru';
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
ru_RU
|
||||
*** LC_TIME_NAMES: testing with a user variable
|
||||
set @lc='JA_JP';
|
||||
set @@lc_time_names=@lc;
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
ja_JP
|
||||
*** LC_TIME_NAMES: testing with string expressions
|
||||
set lc_time_names=concat('de','_','DE');
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
de_DE
|
||||
set lc_time_names=concat('de','+','DE');
|
||||
ERROR HY000: Unknown locale: 'de+DE'
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
de_DE
|
||||
LC_TIME_NAMES: testing with numeric expressions
|
||||
set @@lc_time_names=1+2;
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
sv_SE
|
||||
set @@lc_time_names=1/0;
|
||||
ERROR 42000: Incorrect argument type to variable 'lc_time_names'
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
sv_SE
|
||||
set lc_time_names=en_US;
|
||||
LC_TIME_NAMES: testing NULL and a negative number:
|
||||
set lc_time_names=NULL;
|
||||
ERROR 42000: Variable 'lc_time_names' can't be set to the value of 'NULL'
|
||||
set lc_time_names=-1;
|
||||
ERROR HY000: Unknown locale: '-1'
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
en_US
|
||||
LC_TIME_NAMES: testing locale with the last ID:
|
||||
set lc_time_names=108;
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
zh_HK
|
||||
LC_TIME_NAMES: testing a number beyond the valid ID range:
|
||||
set lc_time_names=109;
|
||||
ERROR HY000: Unknown locale: '109'
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
zh_HK
|
||||
LC_TIME_NAMES: testing that 0 is en_US:
|
||||
set lc_time_names=0;
|
||||
select @@lc_time_names;
|
||||
@@lc_time_names
|
||||
en_US
|
||||
set @test = @@query_prealloc_size;
|
||||
set @@query_prealloc_size = @test;
|
||||
select @@query_prealloc_size = @test;
|
||||
|
@ -51,5 +51,6 @@ unlock tables;
|
||||
connection con1;
|
||||
reap;
|
||||
drop table t5;
|
||||
--system rm $MYSQLTEST_VARDIR/tmp/t?.*
|
||||
|
||||
# End of 4.1 tests
|
||||
|
@ -93,6 +93,26 @@ show create table t1;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#22646 LC_TIME_NAMES: Assignment to non-UTF8 target fails
|
||||
#
|
||||
set names utf8;
|
||||
set LC_TIME_NAMES='fr_FR';
|
||||
create table t1 (s1 char(20) character set latin1);
|
||||
insert into t1 values (date_format('2004-02-02','%M'));
|
||||
select hex(s1) from t1;
|
||||
drop table t1;
|
||||
create table t1 (s1 char(20) character set koi8r);
|
||||
set LC_TIME_NAMES='ru_RU';
|
||||
insert into t1 values (date_format('2004-02-02','%M'));
|
||||
insert into t1 values (date_format('2004-02-02','%b'));
|
||||
insert into t1 values (date_format('2004-02-02','%W'));
|
||||
insert into t1 values (date_format('2004-02-02','%a'));
|
||||
select hex(s1), s1 from t1;
|
||||
drop table t1;
|
||||
set LC_TIME_NAMES='en_US';
|
||||
|
||||
|
||||
#
|
||||
# Bug #2366 Wrong utf8 behaviour when data is truncated
|
||||
#
|
||||
|
@ -702,4 +702,19 @@ create table t1 (a int);
|
||||
--exec $MYSQL_DUMP --skip-comments --force test t1 --where='xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 2>&1
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#13926: --order-by-primary fails if PKEY contains quote character
|
||||
#
|
||||
CREATE TABLE `t1` (
|
||||
`a b` INT,
|
||||
`c"d` INT,
|
||||
`e``f` INT,
|
||||
PRIMARY KEY (`a b`, `c"d`, `e``f`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (0815, 4711, 2006);
|
||||
|
||||
--exec $MYSQL_DUMP --skip-comments --compatible=ansi --order-by-primary test t1
|
||||
--exec $MYSQL_DUMP --skip-comments --order-by-primary test t1
|
||||
DROP TABLE `t1`;
|
||||
|
||||
--echo End of 4.1 tests
|
||||
|
@ -1068,5 +1068,82 @@ EXECUTE stmt USING @a;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#19182: CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work
|
||||
# from stored procedure.
|
||||
#
|
||||
# The cause of a bug was that cached LEX::create_list was modified,
|
||||
# and then together with LEX::key_list was reset.
|
||||
#
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (i INT);
|
||||
|
||||
PREPARE st_19182
|
||||
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||
|
||||
EXECUTE st_19182;
|
||||
DESC t2;
|
||||
|
||||
DROP TABLE t2;
|
||||
|
||||
# Check that on second execution we don't loose 'j' column and the keys
|
||||
# on 'i' and 'j' columns.
|
||||
EXECUTE st_19182;
|
||||
DESC t2;
|
||||
|
||||
DEALLOCATE PREPARE st_19182;
|
||||
DROP TABLE t2, t1;
|
||||
|
||||
#
|
||||
# Bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
|
||||
#
|
||||
# Code which implemented CREATE/ALTER TABLE and CREATE DATABASE
|
||||
# statement modified HA_CREATE_INFO structure in LEX, making these
|
||||
# statements PS/SP-unsafe (their re-execution might have resulted
|
||||
# in incorrect results).
|
||||
#
|
||||
--disable_warnings
|
||||
drop database if exists mysqltest;
|
||||
drop table if exists t1, t2;
|
||||
--enable_warnings
|
||||
# CREATE TABLE and CREATE TABLE ... SELECT
|
||||
create database mysqltest character set utf8;
|
||||
prepare stmt1 from "create table mysqltest.t1 (c char(10))";
|
||||
prepare stmt2 from "create table mysqltest.t2 select 'test'";
|
||||
execute stmt1;
|
||||
execute stmt2;
|
||||
show create table mysqltest.t1;
|
||||
show create table mysqltest.t2;
|
||||
drop table mysqltest.t1;
|
||||
drop table mysqltest.t2;
|
||||
alter database mysqltest character set latin1;
|
||||
execute stmt1;
|
||||
execute stmt2;
|
||||
show create table mysqltest.t1;
|
||||
show create table mysqltest.t2;
|
||||
drop database mysqltest;
|
||||
deallocate prepare stmt1;
|
||||
deallocate prepare stmt2;
|
||||
#
|
||||
# CREATE TABLE with DATA DIRECTORY option
|
||||
#
|
||||
# Protect ourselves from data left in tmp/ by a previos possibly failed
|
||||
# test
|
||||
--system rm -f $MYSQLTEST_VARDIR/tmp/t1.*
|
||||
--disable_query_log
|
||||
eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'";
|
||||
--enable_query_log
|
||||
execute stmt;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
#
|
||||
--echo End of 4.1 tests.
|
||||
|
22
mysql-test/t/rpl_locale.test
Normal file
22
mysql-test/t/rpl_locale.test
Normal file
@ -0,0 +1,22 @@
|
||||
# Replication of locale variables
|
||||
|
||||
source include/master-slave.inc;
|
||||
|
||||
#
|
||||
# Bug#22645 LC_TIME_NAMES: Statement not replicated
|
||||
#
|
||||
connection master;
|
||||
create table t1 (s1 char(10));
|
||||
set lc_time_names= 'de_DE';
|
||||
insert into t1 values (date_format('2001-01-01','%W'));
|
||||
select * from t1;
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
select * from t1;
|
||||
connection master;
|
||||
drop table t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
|
@ -396,6 +396,50 @@ set names latin1;
|
||||
--replace_column 1 #
|
||||
select @@have_innodb;
|
||||
|
||||
#
|
||||
# Tests for lc_time_names
|
||||
# Note, when adding new locales, please fix ID accordingly:
|
||||
# - to test the last ID (currently 108)
|
||||
# - and the next after the last (currently 109)
|
||||
#
|
||||
--echo *** Various tests with LC_TIME_NAMES
|
||||
--echo *** LC_TIME_NAMES: testing case insensitivity
|
||||
set @@lc_time_names='ru_ru';
|
||||
select @@lc_time_names;
|
||||
--echo *** LC_TIME_NAMES: testing with a user variable
|
||||
set @lc='JA_JP';
|
||||
set @@lc_time_names=@lc;
|
||||
select @@lc_time_names;
|
||||
--echo *** LC_TIME_NAMES: testing with string expressions
|
||||
set lc_time_names=concat('de','_','DE');
|
||||
select @@lc_time_names;
|
||||
--error 1105
|
||||
set lc_time_names=concat('de','+','DE');
|
||||
select @@lc_time_names;
|
||||
--echo LC_TIME_NAMES: testing with numeric expressions
|
||||
set @@lc_time_names=1+2;
|
||||
select @@lc_time_names;
|
||||
--error 1232
|
||||
set @@lc_time_names=1/0;
|
||||
select @@lc_time_names;
|
||||
set lc_time_names=en_US;
|
||||
--echo LC_TIME_NAMES: testing NULL and a negative number:
|
||||
--error 1231
|
||||
set lc_time_names=NULL;
|
||||
--error 1105
|
||||
set lc_time_names=-1;
|
||||
select @@lc_time_names;
|
||||
--echo LC_TIME_NAMES: testing locale with the last ID:
|
||||
set lc_time_names=108;
|
||||
select @@lc_time_names;
|
||||
--echo LC_TIME_NAMES: testing a number beyond the valid ID range:
|
||||
--error 1105
|
||||
set lc_time_names=109;
|
||||
select @@lc_time_names;
|
||||
--echo LC_TIME_NAMES: testing that 0 is en_US:
|
||||
set lc_time_names=0;
|
||||
select @@lc_time_names;
|
||||
|
||||
#
|
||||
# Bug #13334: query_prealloc_size default less than minimum
|
||||
#
|
||||
|
@ -322,7 +322,7 @@ BASE=$BASE2
|
||||
#
|
||||
|
||||
if [ x"@GXX@" = x"yes" ] ; then
|
||||
gcclib=`@CC@ --print-libgcc-file`
|
||||
gcclib=`@CC@ @CFLAGS@ --print-libgcc-file`
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Warning: Couldn't find libgcc.a!"
|
||||
else
|
||||
|
@ -22,6 +22,16 @@ command=".mysql.$$"
|
||||
trap "interrupt" 2
|
||||
|
||||
rootpass=""
|
||||
echo_n=
|
||||
echo_c=
|
||||
|
||||
set_echo_compat() {
|
||||
case `echo "testing\c"`,`echo -n testing` in
|
||||
*c*,-n*) echo_n= echo_c= ;;
|
||||
*c*,*) echo_n=-n echo_c= ;;
|
||||
*) echo_n= echo_c='\c' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
prepare() {
|
||||
touch $config $command
|
||||
@ -45,7 +55,7 @@ get_root_password() {
|
||||
status=1
|
||||
while [ $status -eq 1 ]; do
|
||||
stty -echo
|
||||
echo -n "Enter current password for root (enter for none): "
|
||||
echo $echo_n "Enter current password for root (enter for none): $echo_c"
|
||||
read password
|
||||
echo
|
||||
stty echo
|
||||
@ -65,10 +75,10 @@ get_root_password() {
|
||||
|
||||
set_root_password() {
|
||||
stty -echo
|
||||
echo -n "New password: "
|
||||
echo $echo_n "New password: $echo_c"
|
||||
read password1
|
||||
echo
|
||||
echo -n "Re-enter new password: "
|
||||
echo $echo_n "Re-enter new password: $echo_c"
|
||||
read password2
|
||||
echo
|
||||
stty echo
|
||||
@ -173,6 +183,7 @@ cleanup() {
|
||||
# The actual script starts here
|
||||
|
||||
prepare
|
||||
set_echo_compat
|
||||
|
||||
echo
|
||||
echo
|
||||
@ -201,11 +212,11 @@ echo "root user without the proper authorisation."
|
||||
echo
|
||||
|
||||
if [ $hadpass -eq 0 ]; then
|
||||
echo -n "Set root password? [Y/n] "
|
||||
echo $echo_n "Set root password? [Y/n] $echo_c"
|
||||
else
|
||||
echo "You already have a root password set, so you can safely answer 'n'."
|
||||
echo
|
||||
echo -n "Change the root password? [Y/n] "
|
||||
echo $echo_n "Change the root password? [Y/n] $echo_c"
|
||||
fi
|
||||
|
||||
read reply
|
||||
@ -232,7 +243,7 @@ echo "go a bit smoother. You should remove them before moving into a"
|
||||
echo "production environment."
|
||||
echo
|
||||
|
||||
echo -n "Remove anonymous users? [Y/n] "
|
||||
echo $echo_n "Remove anonymous users? [Y/n] $echo_c"
|
||||
|
||||
read reply
|
||||
if [ "$reply" = "n" ]; then
|
||||
@ -251,7 +262,7 @@ echo "Normally, root should only be allowed to connect from 'localhost'. This"
|
||||
echo "ensures that someone cannot guess at the root password from the network."
|
||||
echo
|
||||
|
||||
echo -n "Disallow root login remotely? [Y/n] "
|
||||
echo $echo_n "Disallow root login remotely? [Y/n] $echo_c"
|
||||
read reply
|
||||
if [ "$reply" = "n" ]; then
|
||||
echo " ... skipping."
|
||||
@ -270,7 +281,7 @@ echo "access. This is also intended only for testing, and should be removed"
|
||||
echo "before moving into a production environment."
|
||||
echo
|
||||
|
||||
echo -n "Remove test database and access to it? [Y/n] "
|
||||
echo $echo_n "Remove test database and access to it? [Y/n] $echo_c"
|
||||
read reply
|
||||
if [ "$reply" = "n" ]; then
|
||||
echo " ... skipping."
|
||||
@ -288,7 +299,7 @@ echo "Reloading the privilege tables will ensure that all changes made so far"
|
||||
echo "will take effect immediately."
|
||||
echo
|
||||
|
||||
echo -n "Reload privilege tables now? [Y/n] "
|
||||
echo $echo_n "Reload privilege tables now? [Y/n] $echo_c"
|
||||
read reply
|
||||
if [ "$reply" = "n" ]; then
|
||||
echo " ... skipping."
|
||||
|
@ -2473,8 +2473,9 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length,
|
||||
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
||||
if (entry->value == pos)
|
||||
entry->value=0;
|
||||
if (!(entry->value=(char*) my_realloc(entry->value, length,
|
||||
MYF(MY_ALLOW_ZERO_PTR))))
|
||||
entry->value= (char*) my_realloc(entry->value, length,
|
||||
MYF(MY_ALLOW_ZERO_PTR | MY_WME));
|
||||
if (!entry->value)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -595,16 +595,10 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
|
||||
uint weekday;
|
||||
ulong length;
|
||||
const char *ptr, *end;
|
||||
MY_LOCALE *locale;
|
||||
THD *thd= current_thd;
|
||||
char buf[128];
|
||||
String tmp(buf, sizeof(buf), thd->variables.character_set_results);
|
||||
uint errors= 0;
|
||||
MY_LOCALE *locale= thd->variables.lc_time_names;
|
||||
|
||||
tmp.length(0);
|
||||
str->length(0);
|
||||
str->set_charset(&my_charset_bin);
|
||||
locale = thd->variables.lc_time_names;
|
||||
|
||||
if (l_time->neg)
|
||||
str->append("-", 1);
|
||||
@ -618,41 +612,37 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
|
||||
{
|
||||
switch (*++ptr) {
|
||||
case 'M':
|
||||
if (!l_time->month)
|
||||
return 1;
|
||||
tmp.copy(locale->month_names->type_names[l_time->month-1],
|
||||
strlen(locale->month_names->type_names[l_time->month-1]),
|
||||
system_charset_info, tmp.charset(), &errors);
|
||||
str->append(tmp.ptr(), tmp.length());
|
||||
break;
|
||||
if (!l_time->month)
|
||||
return 1;
|
||||
str->append(locale->month_names->type_names[l_time->month-1],
|
||||
strlen(locale->month_names->type_names[l_time->month-1]),
|
||||
system_charset_info);
|
||||
break;
|
||||
case 'b':
|
||||
if (!l_time->month)
|
||||
return 1;
|
||||
tmp.copy(locale->ab_month_names->type_names[l_time->month-1],
|
||||
strlen(locale->ab_month_names->type_names[l_time->month-1]),
|
||||
system_charset_info, tmp.charset(), &errors);
|
||||
str->append(tmp.ptr(), tmp.length());
|
||||
break;
|
||||
if (!l_time->month)
|
||||
return 1;
|
||||
str->append(locale->ab_month_names->type_names[l_time->month-1],
|
||||
strlen(locale->ab_month_names->type_names[l_time->month-1]),
|
||||
system_charset_info);
|
||||
break;
|
||||
case 'W':
|
||||
if (type == MYSQL_TIMESTAMP_TIME)
|
||||
return 1;
|
||||
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
|
||||
l_time->day),0);
|
||||
tmp.copy(locale->day_names->type_names[weekday],
|
||||
strlen(locale->day_names->type_names[weekday]),
|
||||
system_charset_info, tmp.charset(), &errors);
|
||||
str->append(tmp.ptr(), tmp.length());
|
||||
break;
|
||||
if (type == MYSQL_TIMESTAMP_TIME)
|
||||
return 1;
|
||||
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
|
||||
l_time->day),0);
|
||||
str->append(locale->day_names->type_names[weekday],
|
||||
strlen(locale->day_names->type_names[weekday]),
|
||||
system_charset_info);
|
||||
break;
|
||||
case 'a':
|
||||
if (type == MYSQL_TIMESTAMP_TIME)
|
||||
return 1;
|
||||
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
|
||||
l_time->day),0);
|
||||
tmp.copy(locale->ab_day_names->type_names[weekday],
|
||||
strlen(locale->ab_day_names->type_names[weekday]),
|
||||
system_charset_info, tmp.charset(), &errors);
|
||||
str->append(tmp.ptr(), tmp.length());
|
||||
break;
|
||||
if (type == MYSQL_TIMESTAMP_TIME)
|
||||
return 1;
|
||||
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
|
||||
l_time->day),0);
|
||||
str->append(locale->ab_day_names->type_names[weekday],
|
||||
strlen(locale->ab_day_names->type_names[weekday]),
|
||||
system_charset_info);
|
||||
break;
|
||||
case 'D':
|
||||
if (type == MYSQL_TIMESTAMP_TIME)
|
||||
return 1;
|
||||
@ -1638,8 +1628,9 @@ longlong Item_func_sec_to_time::val_int()
|
||||
|
||||
void Item_func_date_format::fix_length_and_dec()
|
||||
{
|
||||
THD* thd= current_thd;
|
||||
decimals=0;
|
||||
collation.set(&my_charset_bin);
|
||||
collation.set(thd->variables.collation_connection);
|
||||
if (args[1]->type() == STRING_ITEM)
|
||||
{ // Optimize the normal case
|
||||
fixed_length=1;
|
||||
@ -1653,17 +1644,14 @@ void Item_func_date_format::fix_length_and_dec()
|
||||
args[1]->collation.set(
|
||||
get_charset_by_csname(args[1]->collation.collation->csname,
|
||||
MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
|
||||
/*
|
||||
The result is a binary string (no reason to use collation->mbmaxlen
|
||||
This is becasue make_date_time() only returns binary strings
|
||||
*/
|
||||
max_length= format_length(((Item_string*) args[1])->const_string());
|
||||
max_length= format_length(((Item_string*) args[1])->const_string()) *
|
||||
collation.collation->mbmaxlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_length=0;
|
||||
/* The result is a binary string (no reason to use collation->mbmaxlen */
|
||||
max_length=min(args[1]->max_length,MAX_BLOB_WIDTH) * 10;
|
||||
max_length= min(args[1]->max_length,MAX_BLOB_WIDTH) * 10 *
|
||||
collation.collation->mbmaxlen;
|
||||
set_if_smaller(max_length,MAX_BLOB_WIDTH);
|
||||
}
|
||||
maybe_null=1; // If wrong date
|
||||
@ -1783,6 +1771,7 @@ String *Item_func_date_format::val_str(String *str)
|
||||
date_time_format.format.length= format->length();
|
||||
|
||||
/* Create the result string */
|
||||
str->set_charset(collation.collation);
|
||||
if (!make_date_time(&date_time_format, &l_time,
|
||||
is_time_format ? MYSQL_TIMESTAMP_TIME :
|
||||
MYSQL_TIMESTAMP_DATE,
|
||||
|
15
sql/log.cc
15
sql/log.cc
@ -1350,6 +1350,21 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
Use the same ONE_SHOT trick for making replication of lc_time_names.
|
||||
*/
|
||||
if (thd->variables.lc_time_names->number) // Not en_US
|
||||
{
|
||||
char buf[32];
|
||||
uint length= my_snprintf(buf, sizeof(buf),
|
||||
"SET ONE_SHOT LC_TIME_NAMES=%u",
|
||||
(uint) thd->variables.lc_time_names->number);
|
||||
Query_log_event e(thd, buf, length, 0, FALSE);
|
||||
e.set_log_pos(this);
|
||||
e.error_code= 0; // This statement cannot fail (see [1]).
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (thd->last_insert_id_used)
|
||||
|
@ -71,6 +71,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
||||
|
||||
typedef struct my_locale_st
|
||||
{
|
||||
uint number;
|
||||
const char *name;
|
||||
const char *description;
|
||||
const bool is_ascii;
|
||||
@ -84,6 +85,7 @@ extern MY_LOCALE my_locale_en_US;
|
||||
extern MY_LOCALE *my_locales[];
|
||||
|
||||
MY_LOCALE *my_locale_by_name(const char *name);
|
||||
MY_LOCALE *my_locale_by_number(uint number);
|
||||
|
||||
/***************************************************************************
|
||||
Configuration parameters
|
||||
@ -563,25 +565,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
uint &key_count, int select_field_count);
|
||||
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
List<create_field> &fields, List<Key> &keys,
|
||||
Alter_info *alter_info,
|
||||
bool tmp_table, uint select_field_count);
|
||||
|
||||
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
const char *db, const char *name,
|
||||
List<create_field> *extra_fields,
|
||||
List<Key> *keys,
|
||||
Alter_info *alter_info,
|
||||
List<Item> *items,
|
||||
MYSQL_LOCK **lock);
|
||||
int mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
List<create_field> &fields,
|
||||
List<Key> &keys,
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
bool ignore,
|
||||
ALTER_INFO *alter_info, bool do_send_ok=1);
|
||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
||||
bool ignore);
|
||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
|
||||
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_ident *src_table);
|
||||
@ -590,9 +589,6 @@ bool mysql_rename_table(enum db_type base,
|
||||
const char * old_name,
|
||||
const char *new_db,
|
||||
const char * new_name);
|
||||
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
|
||||
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
|
||||
ALTER_INFO *alter_info);
|
||||
int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
TABLE_LIST *update_table_list,
|
||||
Item **conds, uint order_num, ORDER *order);
|
||||
@ -679,7 +675,8 @@ int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
|
||||
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
|
||||
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
|
||||
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
|
||||
int mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
|
||||
int mysqld_show_create_db(THD *thd, char *dbname,
|
||||
const HA_CREATE_INFO *create);
|
||||
|
||||
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
|
||||
int mysqld_show_status(THD *thd);
|
||||
|
@ -2570,19 +2570,38 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
|
||||
|
||||
bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
|
||||
{
|
||||
char *locale_str =var->value->str_value.c_ptr();
|
||||
MY_LOCALE *locale_match= my_locale_by_name(locale_str);
|
||||
MY_LOCALE *locale_match;
|
||||
|
||||
if(locale_match == NULL)
|
||||
if (var->value->result_type() == INT_RESULT)
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), locale_str);
|
||||
return 1;
|
||||
if (!(locale_match= my_locale_by_number((uint) var->value->val_int())))
|
||||
{
|
||||
char buf[20];
|
||||
int10_to_str((int) var->value->val_int(), buf, -10);
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), buf);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
else // STRING_RESULT
|
||||
{
|
||||
var->save_result.locale_value= locale_match;
|
||||
return 0;
|
||||
char buff[6];
|
||||
String str(buff, sizeof(buff), &my_charset_latin1), *res;
|
||||
if (!(res=var->value->val_str(&str)))
|
||||
{
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
|
||||
return 1;
|
||||
}
|
||||
const char *locale_str= res->c_ptr();
|
||||
if (!(locale_match= my_locale_by_name(locale_str)))
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_ERROR,
|
||||
"Unknown locale: '%s'", MYF(0), locale_str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
var->save_result.locale_value= locale_match;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -764,12 +764,16 @@ class sys_var_thd_lc_time_names :public sys_var_thd
|
||||
public:
|
||||
sys_var_thd_lc_time_names(const char *name_arg):
|
||||
sys_var_thd(name_arg)
|
||||
{}
|
||||
{
|
||||
#if MYSQL_VERSION_ID < 50000
|
||||
no_support_one_shot= 0;
|
||||
#endif
|
||||
}
|
||||
bool check(THD *thd, set_var *var);
|
||||
SHOW_TYPE type() { return SHOW_CHAR; }
|
||||
bool check_update_type(Item_result type)
|
||||
{
|
||||
return type != STRING_RESULT; /* Only accept strings */
|
||||
return ((type != STRING_RESULT) && (type != INT_RESULT));
|
||||
}
|
||||
bool check_default(enum_var_type type) { return 0; }
|
||||
bool update(THD *thd, set_var *var);
|
||||
|
@ -1293,20 +1293,21 @@ class select_create: public select_insert {
|
||||
ORDER *group;
|
||||
const char *db;
|
||||
const char *name;
|
||||
List<create_field> *extra_fields;
|
||||
List<Key> *keys;
|
||||
HA_CREATE_INFO *create_info;
|
||||
Alter_info *alter_info;
|
||||
MYSQL_LOCK *lock;
|
||||
Field **field;
|
||||
public:
|
||||
select_create(const char *db_name, const char *table_name,
|
||||
HA_CREATE_INFO *create_info_par,
|
||||
List<create_field> &fields_par,
|
||||
List<Key> &keys_par,
|
||||
List<Item> &select_fields,enum_duplicates duplic, bool ignore)
|
||||
:select_insert (NULL, &select_fields, duplic, ignore), db(db_name),
|
||||
name(table_name), extra_fields(&fields_par),keys(&keys_par),
|
||||
create_info(create_info_par), lock(0)
|
||||
HA_CREATE_INFO *create_info_arg,
|
||||
Alter_info *alter_info_arg,
|
||||
List<Item> &select_fields,
|
||||
enum_duplicates duplic, bool ignore)
|
||||
:select_insert(NULL, &select_fields, duplic, ignore),
|
||||
db(db_name), name(table_name),
|
||||
create_info(create_info_arg),
|
||||
alter_info(alter_info_arg),
|
||||
lock(0)
|
||||
{}
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
void store_values(List<Item> &values);
|
||||
|
@ -1805,7 +1805,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
|
||||
unit= u;
|
||||
table= create_table_from_items(thd, create_info, db, name,
|
||||
extra_fields, keys, &values, &lock);
|
||||
alter_info, &values, &lock);
|
||||
if (!table)
|
||||
DBUG_RETURN(-1); // abort() deletes table
|
||||
|
||||
|
@ -1015,6 +1015,18 @@ int yylex(void *arg, void *yythd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
||||
:drop_list(rhs.drop_list, mem_root),
|
||||
alter_list(rhs.alter_list, mem_root),
|
||||
key_list(rhs.key_list, mem_root),
|
||||
create_list(rhs.create_list, mem_root),
|
||||
flags(rhs.flags),
|
||||
keys_onoff(rhs.keys_onoff),
|
||||
tablespace_op(rhs.tablespace_op),
|
||||
is_simple(rhs.is_simple)
|
||||
{}
|
||||
|
||||
/*
|
||||
st_select_lex structures initialisations
|
||||
*/
|
||||
|
@ -571,19 +571,61 @@ typedef class st_select_lex SELECT_LEX;
|
||||
#define ALTER_ORDER 64
|
||||
#define ALTER_OPTIONS 128
|
||||
|
||||
typedef struct st_alter_info
|
||||
/**
|
||||
@brief Parsing data for CREATE or ALTER TABLE.
|
||||
|
||||
This structure contains a list of columns or indexes to be created,
|
||||
altered or dropped.
|
||||
*/
|
||||
|
||||
class Alter_info
|
||||
{
|
||||
public:
|
||||
List<Alter_drop> drop_list;
|
||||
List<Alter_column> alter_list;
|
||||
List<Key> key_list;
|
||||
List<create_field> create_list;
|
||||
uint flags;
|
||||
enum enum_enable_or_disable keys_onoff;
|
||||
enum tablespace_op_type tablespace_op;
|
||||
bool is_simple;
|
||||
|
||||
st_alter_info(){clear();}
|
||||
void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
|
||||
void reset(){drop_list.empty();alter_list.empty();clear();}
|
||||
} ALTER_INFO;
|
||||
Alter_info() :
|
||||
flags(0),
|
||||
keys_onoff(LEAVE_AS_IS),
|
||||
tablespace_op(NO_TABLESPACE_OP),
|
||||
is_simple(1)
|
||||
{}
|
||||
void reset()
|
||||
{
|
||||
drop_list.empty();
|
||||
alter_list.empty();
|
||||
key_list.empty();
|
||||
create_list.empty();
|
||||
flags= 0;
|
||||
keys_onoff= LEAVE_AS_IS;
|
||||
tablespace_op= NO_TABLESPACE_OP;
|
||||
is_simple= 1;
|
||||
}
|
||||
/**
|
||||
Construct a copy of this object to be used for mysql_alter_table
|
||||
and mysql_create_table. Historically, these two functions modify
|
||||
their Alter_info arguments. This behaviour breaks re-execution of
|
||||
prepared statements and stored procedures and is compensated by
|
||||
always supplying a copy of Alter_info to these functions.
|
||||
The constructed copy still shares key Key, Alter_drop, create_field
|
||||
and Alter_column elements of the lists - these structures are not
|
||||
modified and thus are not copied.
|
||||
|
||||
@note You need to use check thd->is_fatal_error for out
|
||||
of memory condition after calling this function.
|
||||
*/
|
||||
Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root);
|
||||
private:
|
||||
Alter_info &operator=(const Alter_info &rhs); // not implemented
|
||||
Alter_info(const Alter_info &rhs); // not implemented
|
||||
};
|
||||
|
||||
|
||||
/* The state of the lex parsing. This is saved in the THD struct */
|
||||
|
||||
@ -620,8 +662,6 @@ typedef struct st_lex
|
||||
List<String> interval_list;
|
||||
List<LEX_USER> users_list;
|
||||
List<LEX_COLUMN> columns;
|
||||
List<Key> key_list;
|
||||
List<create_field> create_list;
|
||||
List<Item> *insert_list,field_list,value_list,update_list;
|
||||
List<List_item> many_values;
|
||||
List<set_var_base> var_list;
|
||||
@ -654,7 +694,7 @@ typedef struct st_lex
|
||||
bool derived_tables;
|
||||
bool safe_to_cache_query;
|
||||
bool subqueries, ignore;
|
||||
ALTER_INFO alter_info;
|
||||
Alter_info alter_info;
|
||||
/* Prepared statements SQL syntax:*/
|
||||
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
||||
/*
|
||||
|
@ -66,21 +66,24 @@ public:
|
||||
pointer.
|
||||
*/
|
||||
|
||||
class list_node :public Sql_alloc
|
||||
|
||||
/**
|
||||
list_node - a node of a single-linked list.
|
||||
@note We never call a destructor for instances of this class.
|
||||
*/
|
||||
|
||||
struct list_node :public Sql_alloc
|
||||
{
|
||||
public:
|
||||
list_node *next;
|
||||
void *info;
|
||||
list_node(void *info_par,list_node *next_par)
|
||||
:next(next_par),info(info_par)
|
||||
{}
|
||||
{}
|
||||
list_node() /* For end_of_list */
|
||||
{
|
||||
info=0;
|
||||
next= this;
|
||||
}
|
||||
friend class base_list;
|
||||
friend class base_list_iterator;
|
||||
{
|
||||
info= 0;
|
||||
next= this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -96,11 +99,56 @@ public:
|
||||
|
||||
inline void empty() { elements=0; first= &end_of_list; last=&first;}
|
||||
inline base_list() { empty(); }
|
||||
/**
|
||||
This is a shallow copy constructor that implicitly passes the ownership
|
||||
from the source list to the new instance. The old instance is not
|
||||
updated, so both objects end up sharing the same nodes. If one of
|
||||
the instances then adds or removes a node, the other becomes out of
|
||||
sync ('last' pointer), while still operational. Some old code uses and
|
||||
relies on this behaviour. This logic is quite tricky: please do not use
|
||||
it in any new code.
|
||||
*/
|
||||
inline base_list(const base_list &tmp) :Sql_alloc()
|
||||
{
|
||||
elements=tmp.elements;
|
||||
first=tmp.first;
|
||||
last=tmp.last;
|
||||
elements= tmp.elements;
|
||||
first= tmp.first;
|
||||
last= elements ? tmp.last : &first;
|
||||
}
|
||||
/**
|
||||
Construct a deep copy of the argument in memory root mem_root.
|
||||
The elements themselves are copied by pointer.
|
||||
*/
|
||||
inline base_list(const base_list &rhs, MEM_ROOT *mem_root)
|
||||
{
|
||||
if (rhs.elements)
|
||||
{
|
||||
/*
|
||||
It's okay to allocate an array of nodes at once: we never
|
||||
call a destructor for list_node objects anyway.
|
||||
*/
|
||||
first= (list_node*) alloc_root(mem_root,
|
||||
sizeof(list_node) * rhs.elements);
|
||||
if (first)
|
||||
{
|
||||
elements= rhs.elements;
|
||||
list_node *dst= first;
|
||||
list_node *src= rhs.first;
|
||||
for (; dst < first + elements - 1; dst++, src= src->next)
|
||||
{
|
||||
dst->info= src->info;
|
||||
dst->next= dst + 1;
|
||||
}
|
||||
/* Copy the last node */
|
||||
dst->info= src->info;
|
||||
dst->next= &end_of_list;
|
||||
/* Setup 'last' member */
|
||||
last= &dst->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
elements= 0;
|
||||
first= &end_of_list;
|
||||
last= &first;
|
||||
}
|
||||
inline base_list(bool error) { }
|
||||
inline bool push_back(void *info)
|
||||
@ -327,6 +375,8 @@ template <class T> class List :public base_list
|
||||
public:
|
||||
inline List() :base_list() {}
|
||||
inline List(const List<T> &tmp) :base_list(tmp) {}
|
||||
inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
|
||||
base_list(tmp, mem_root) {}
|
||||
inline bool push_back(T *a) { return base_list::push_back(a); }
|
||||
inline bool push_front(T *a) { return base_list::push_front(a); }
|
||||
inline T* head() {return (T*) base_list::head(); }
|
||||
|
1245
sql/sql_locale.cc
1245
sql/sql_locale.cc
File diff suppressed because it is too large
Load Diff
212
sql/sql_parse.cc
212
sql/sql_parse.cc
@ -1958,6 +1958,7 @@ static void reset_one_shot_variables(THD *thd)
|
||||
thd->update_charset();
|
||||
thd->variables.time_zone=
|
||||
global_system_variables.time_zone;
|
||||
thd->variables.lc_time_names= &my_locale_en_US;
|
||||
thd->one_shot_set= 0;
|
||||
}
|
||||
|
||||
@ -2478,19 +2479,36 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
/* Skip first table, which is the table we are creating */
|
||||
TABLE_LIST *create_table, *create_table_local;
|
||||
/*
|
||||
Code below (especially in mysql_create_table() and select_create
|
||||
methods) may modify HA_CREATE_INFO structure in LEX, so we have to
|
||||
use a copy of this structure to make execution prepared statement-
|
||||
safe. A shallow copy is enough as this code won't modify any memory
|
||||
referenced from this structure.
|
||||
*/
|
||||
HA_CREATE_INFO create_info(lex->create_info);
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
|
||||
if (thd->is_fatal_error)
|
||||
{
|
||||
/* out of memory when creating a copy of alter_info */
|
||||
res= 1;
|
||||
goto unsent_create_error;
|
||||
}
|
||||
tables= lex->unlink_first_table(tables, &create_table,
|
||||
&create_table_local);
|
||||
|
||||
if ((res= create_table_precheck(thd, tables, create_table)))
|
||||
goto unsent_create_error;
|
||||
|
||||
create_info.alias= create_table->alias;
|
||||
#ifndef HAVE_READLINK
|
||||
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
|
||||
create_info.data_file_name= create_info.index_file_name= NULL;
|
||||
#else
|
||||
/* Fix names if symlinked tables */
|
||||
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
|
||||
if (append_file_to_dir(thd, &create_info.data_file_name,
|
||||
create_table->real_name) ||
|
||||
append_file_to_dir(thd,&lex->create_info.index_file_name,
|
||||
append_file_to_dir(thd, &create_info.index_file_name,
|
||||
create_table->real_name))
|
||||
{
|
||||
res=-1;
|
||||
@ -2501,14 +2519,14 @@ mysql_execute_command(THD *thd)
|
||||
If we are using SET CHARSET without DEFAULT, add an implicite
|
||||
DEFAULT to not confuse old users. (This may change).
|
||||
*/
|
||||
if ((lex->create_info.used_fields &
|
||||
if ((create_info.used_fields &
|
||||
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
|
||||
HA_CREATE_USED_CHARSET)
|
||||
{
|
||||
lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
||||
lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
lex->create_info.default_table_charset= lex->create_info.table_charset;
|
||||
lex->create_info.table_charset= 0;
|
||||
create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
||||
create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||
create_info.default_table_charset= create_info.table_charset;
|
||||
create_info.table_charset= 0;
|
||||
}
|
||||
/*
|
||||
The create-select command will open and read-lock the select table
|
||||
@ -2542,11 +2560,14 @@ mysql_execute_command(THD *thd)
|
||||
if (!(res=open_and_lock_tables(thd,tables)))
|
||||
{
|
||||
res= -1; // If error
|
||||
/*
|
||||
select_create is currently not re-execution friendly and
|
||||
needs to be created for every execution of a PS/SP.
|
||||
*/
|
||||
if ((result=new select_create(create_table->db,
|
||||
create_table->real_name,
|
||||
&lex->create_info,
|
||||
lex->create_list,
|
||||
lex->key_list,
|
||||
&create_info,
|
||||
&alter_info,
|
||||
select_lex->item_list, lex->duplicates,
|
||||
lex->ignore)))
|
||||
{
|
||||
@ -2558,22 +2579,18 @@ mysql_execute_command(THD *thd)
|
||||
res=handle_select(thd, lex, result);
|
||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
||||
}
|
||||
//reset for PS
|
||||
lex->create_list.empty();
|
||||
lex->key_list.empty();
|
||||
}
|
||||
}
|
||||
else // regular create
|
||||
{
|
||||
if (lex->name)
|
||||
res= mysql_create_like_table(thd, create_table, &lex->create_info,
|
||||
res= mysql_create_like_table(thd, create_table, &create_info,
|
||||
(Table_ident *)lex->name);
|
||||
else
|
||||
{
|
||||
res= mysql_create_table(thd,create_table->db,
|
||||
create_table->real_name, &lex->create_info,
|
||||
lex->create_list,
|
||||
lex->key_list,0,0);
|
||||
res= mysql_create_table(thd, create_table->db,
|
||||
create_table->real_name, &create_info,
|
||||
&alter_info, 0, 0);
|
||||
}
|
||||
if (!res)
|
||||
send_ok(thd);
|
||||
@ -2591,15 +2608,49 @@ unsent_create_error:
|
||||
break;
|
||||
}
|
||||
case SQLCOM_CREATE_INDEX:
|
||||
/* Fall through */
|
||||
case SQLCOM_DROP_INDEX:
|
||||
/*
|
||||
CREATE INDEX and DROP INDEX are implemented by calling ALTER
|
||||
TABLE with proper arguments. This isn't very fast but it
|
||||
should work for most cases.
|
||||
|
||||
In the future ALTER TABLE will notice that only added
|
||||
indexes and create these one by one for the existing table
|
||||
without having to do a full rebuild.
|
||||
|
||||
One should normally create all indexes with CREATE TABLE or
|
||||
ALTER TABLE.
|
||||
*/
|
||||
{
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
HA_CREATE_INFO create_info;
|
||||
|
||||
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info*/
|
||||
goto error;
|
||||
|
||||
if (check_one_table_access(thd, INDEX_ACL, tables))
|
||||
goto error; /* purecov: inspected */
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
if (end_active_trans(thd))
|
||||
res= -1;
|
||||
else
|
||||
res = mysql_create_index(thd, tables, lex->key_list);
|
||||
break;
|
||||
goto error;
|
||||
/*
|
||||
Currently CREATE INDEX or DROP INDEX cause a full table rebuild
|
||||
and thus classify as slow administrative statements just like
|
||||
ALTER TABLE.
|
||||
*/
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
|
||||
bzero((char*) &create_info, sizeof(create_info));
|
||||
create_info.db_type= DB_TYPE_DEFAULT;
|
||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
|
||||
res= mysql_alter_table(thd, tables->db, tables->real_name,
|
||||
&create_info, tables, &alter_info,
|
||||
0, (ORDER*)0, DUP_ERROR, 0);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_REPLICATION
|
||||
case SQLCOM_SLAVE_START:
|
||||
{
|
||||
@ -2642,6 +2693,17 @@ unsent_create_error:
|
||||
#else
|
||||
{
|
||||
ulong priv=0;
|
||||
/*
|
||||
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
|
||||
so we have to use a copy of this structure to make execution
|
||||
prepared statement- safe. A shallow copy is enough as no memory
|
||||
referenced from this structure will be modified.
|
||||
*/
|
||||
HA_CREATE_INFO create_info(lex->create_info);
|
||||
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||
|
||||
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
|
||||
goto error;
|
||||
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
|
||||
{
|
||||
net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
|
||||
@ -2655,7 +2717,7 @@ unsent_create_error:
|
||||
default database if the new name is not explicitly qualified
|
||||
by a database. (Bug #11493)
|
||||
*/
|
||||
if (lex->alter_info.flags & ALTER_RENAME)
|
||||
if (alter_info.flags & ALTER_RENAME)
|
||||
{
|
||||
if (! thd->db)
|
||||
{
|
||||
@ -2671,7 +2733,7 @@ unsent_create_error:
|
||||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
|
||||
check_merge_table_access(thd, tables->db,
|
||||
(TABLE_LIST *)
|
||||
lex->create_info.merge_list.first))
|
||||
create_info.merge_list.first))
|
||||
goto error; /* purecov: inspected */
|
||||
if (grant_option)
|
||||
{
|
||||
@ -2690,26 +2752,26 @@ unsent_create_error:
|
||||
}
|
||||
}
|
||||
/* Don't yet allow changing of symlinks with ALTER TABLE */
|
||||
if (lex->create_info.data_file_name)
|
||||
if (create_info.data_file_name)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||
"DATA DIRECTORY option ignored");
|
||||
if (lex->create_info.index_file_name)
|
||||
if (create_info.index_file_name)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||
"INDEX DIRECTORY option ignored");
|
||||
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
|
||||
create_info.data_file_name= create_info.index_file_name= NULL;
|
||||
/* ALTER TABLE ends previous transaction */
|
||||
if (end_active_trans(thd))
|
||||
res= -1;
|
||||
else
|
||||
{
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||
&lex->create_info,
|
||||
tables, lex->create_list,
|
||||
lex->key_list,
|
||||
select_lex->order_list.elements,
|
||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||
&create_info,
|
||||
tables,
|
||||
&alter_info,
|
||||
select_lex->order_list.elements,
|
||||
(ORDER *) select_lex->order_list.first,
|
||||
lex->duplicates, lex->ignore, &lex->alter_info);
|
||||
lex->duplicates, lex->ignore);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2846,7 +2908,7 @@ unsent_create_error:
|
||||
goto error; /* purecov: inspected */
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
||||
mysql_recreate_table(thd, tables, 1) :
|
||||
mysql_recreate_table(thd, tables) :
|
||||
mysql_optimize_table(thd, tables, &lex->check_opt);
|
||||
/* ! we write after unlocking the table */
|
||||
if (!res && !lex->no_write_to_binlog)
|
||||
@ -3123,14 +3185,6 @@ unsent_create_error:
|
||||
res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
|
||||
}
|
||||
break;
|
||||
case SQLCOM_DROP_INDEX:
|
||||
if (check_one_table_access(thd, INDEX_ACL, tables))
|
||||
goto error; /* purecov: inspected */
|
||||
if (end_active_trans(thd))
|
||||
res= -1;
|
||||
else
|
||||
res = mysql_drop_index(thd, tables, &lex->alter_info);
|
||||
break;
|
||||
case SQLCOM_SHOW_DATABASES:
|
||||
#if defined(DONT_ALLOW_SHOW_COMMANDS)
|
||||
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
||||
@ -3363,6 +3417,12 @@ purposes internal to the MySQL server", MYF(0));
|
||||
break;
|
||||
case SQLCOM_CREATE_DB:
|
||||
{
|
||||
/*
|
||||
As mysql_create_db() may modify HA_CREATE_INFO structure passed to
|
||||
it, we need to use a copy of LEX::create_info to make execution
|
||||
prepared statement- safe.
|
||||
*/
|
||||
HA_CREATE_INFO create_info(lex->create_info);
|
||||
if (end_active_trans(thd))
|
||||
{
|
||||
res= -1;
|
||||
@ -3393,7 +3453,7 @@ purposes internal to the MySQL server", MYF(0));
|
||||
if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
|
||||
break;
|
||||
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
|
||||
&lex->create_info, 0);
|
||||
&create_info, 0);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_DROP_DB:
|
||||
@ -4443,15 +4503,17 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
||||
if (type_modifier & PRI_KEY_FLAG)
|
||||
{
|
||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||
lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
|
||||
0, lex->col_list));
|
||||
lex->alter_info.key_list.push_back(new Key(Key::PRIMARY, NullS,
|
||||
HA_KEY_ALG_UNDEF, 0,
|
||||
lex->col_list));
|
||||
lex->col_list.empty();
|
||||
}
|
||||
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
||||
{
|
||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||
lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
|
||||
lex->col_list));
|
||||
lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
|
||||
HA_KEY_ALG_UNDEF, 0,
|
||||
lex->col_list));
|
||||
lex->col_list.empty();
|
||||
}
|
||||
|
||||
@ -4778,7 +4840,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
||||
new_field->sql_type,
|
||||
new_field->length);
|
||||
new_field->char_length= new_field->length;
|
||||
lex->create_list.push_back(new_field);
|
||||
lex->alter_info.create_list.push_back(new_field);
|
||||
lex->last_field=new_field;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -5458,57 +5520,6 @@ Item * all_any_subquery_creator(Item *left_expr,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
|
||||
the proper arguments. This isn't very fast but it should work for most
|
||||
cases.
|
||||
|
||||
In the future ALTER TABLE will notice that only added indexes
|
||||
and create these one by one for the existing table without having to do
|
||||
a full rebuild.
|
||||
|
||||
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
|
||||
*/
|
||||
|
||||
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
|
||||
{
|
||||
List<create_field> fields;
|
||||
ALTER_INFO alter_info;
|
||||
alter_info.flags= ALTER_ADD_INDEX;
|
||||
alter_info.is_simple= 0;
|
||||
HA_CREATE_INFO create_info;
|
||||
DBUG_ENTER("mysql_create_index");
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
|
||||
&create_info, table_list,
|
||||
fields, keys, 0, (ORDER*)0,
|
||||
DUP_ERROR, 0, &alter_info));
|
||||
}
|
||||
|
||||
|
||||
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
|
||||
{
|
||||
List<create_field> fields;
|
||||
List<Key> keys;
|
||||
HA_CREATE_INFO create_info;
|
||||
DBUG_ENTER("mysql_drop_index");
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
alter_info->clear();
|
||||
alter_info->flags= ALTER_DROP_INDEX;
|
||||
alter_info->is_simple= 0;
|
||||
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
|
||||
&create_info, table_list,
|
||||
fields, keys, 0, (ORDER*)0,
|
||||
DUP_ERROR, 0, alter_info));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Multi update query pre-check
|
||||
|
||||
@ -5791,7 +5802,6 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||
CREATE_TMP_ACL : CREATE_ACL);
|
||||
lex->create_info.alias= create_table->alias;
|
||||
if (check_access(thd, want_priv, create_table->db,
|
||||
&create_table->grant.privilege, 0, 0) ||
|
||||
check_merge_table_access(thd, create_table->db,
|
||||
|
@ -845,7 +845,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
||||
}
|
||||
|
||||
int mysqld_show_create_db(THD *thd, char *dbname,
|
||||
HA_CREATE_INFO *create_info)
|
||||
const HA_CREATE_INFO *create_info)
|
||||
{
|
||||
int length;
|
||||
char path[FN_REFLEN];
|
||||
|
375
sql/sql_table.cc
375
sql/sql_table.cc
@ -456,8 +456,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
||||
mysql_prepare_table()
|
||||
thd Thread object
|
||||
create_info Create information (like MAX_ROWS)
|
||||
fields List of fields to create
|
||||
keys List of keys to create
|
||||
alter_info List of columns and indexes to create
|
||||
|
||||
DESCRIPTION
|
||||
Prepares the table and key structures for table creation.
|
||||
@ -468,8 +467,8 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
||||
*/
|
||||
|
||||
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
List<create_field> &fields,
|
||||
List<Key> &keys, bool tmp_table, uint &db_options,
|
||||
Alter_info *alter_info,
|
||||
bool tmp_table, uint &db_options,
|
||||
handler *file, KEY *&key_info_buffer,
|
||||
uint *key_count, int select_field_count)
|
||||
{
|
||||
@ -482,10 +481,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
int timestamps= 0, timestamps_with_niladic= 0;
|
||||
int field_no,dup_no;
|
||||
int select_field_pos,auto_increment=0;
|
||||
List_iterator<create_field> it(alter_info->create_list);
|
||||
List_iterator<create_field> it2(alter_info->create_list);
|
||||
DBUG_ENTER("mysql_prepare_table");
|
||||
|
||||
List_iterator<create_field> it(fields),it2(fields);
|
||||
select_field_pos=fields.elements - select_field_count;
|
||||
select_field_pos= alter_info->create_list.elements - select_field_count;
|
||||
null_fields=blob_columns=0;
|
||||
|
||||
for (field_no=0; (sql_field=it++) ; field_no++)
|
||||
@ -883,7 +883,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
|
||||
/* Create keys */
|
||||
|
||||
List_iterator<Key> key_iterator(keys), key_iterator2(keys);
|
||||
List_iterator<Key> key_iterator(alter_info->key_list);
|
||||
List_iterator<Key> key_iterator2(alter_info->key_list);
|
||||
uint key_parts=0, fk_key_count=0;
|
||||
bool primary_key=0,unique_key=0;
|
||||
Key *key, *key2;
|
||||
@ -1333,23 +1334,27 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
|
||||
SYNOPSIS
|
||||
mysql_create_table()
|
||||
thd Thread object
|
||||
db Database
|
||||
table_name Table name
|
||||
create_info Create information (like MAX_ROWS)
|
||||
fields List of fields to create
|
||||
keys List of keys to create
|
||||
tmp_table Set to 1 if this is an internal temporary table
|
||||
(From ALTER TABLE)
|
||||
thd Thread object
|
||||
db Database
|
||||
table_name Table name
|
||||
create_info [in/out] Create information (like MAX_ROWS)
|
||||
alter_info [in/out] List of columns and indexes to create
|
||||
tmp_table Set to 1 if this is an internal temporary table
|
||||
(From ALTER TABLE)
|
||||
|
||||
DESCRIPTION
|
||||
If one creates a temporary table, this is automaticly opened
|
||||
If one creates a temporary table, this is automatically opened
|
||||
|
||||
no_log is needed for the case of CREATE ... SELECT,
|
||||
as the logging will be done later in sql_insert.cc
|
||||
select_field_count is also used for CREATE ... SELECT,
|
||||
and must be zero for standard create of table.
|
||||
|
||||
Note that structures passed as 'create_info' and 'alter_info' parameters
|
||||
may be modified by this function. It is responsibility of the caller to
|
||||
make a copy of create_info in order to provide correct execution in
|
||||
prepared statements/stored routines.
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
-1 error
|
||||
@ -1357,8 +1362,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
|
||||
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
List<create_field> &fields,
|
||||
List<Key> &keys,bool tmp_table,
|
||||
Alter_info *alter_info,
|
||||
bool tmp_table,
|
||||
uint select_field_count)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
@ -1371,7 +1376,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
DBUG_ENTER("mysql_create_table");
|
||||
|
||||
/* Check for duplicate fields and check type of table to create */
|
||||
if (!fields.elements)
|
||||
if (!alter_info->create_list.elements)
|
||||
{
|
||||
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
|
||||
DBUG_RETURN(-1);
|
||||
@ -1423,10 +1428,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
create_info->default_table_charset= db_info.default_table_charset;
|
||||
}
|
||||
|
||||
if (mysql_prepare_table(thd, create_info, fields,
|
||||
keys, tmp_table, db_options, file,
|
||||
key_info_buffer, &key_count,
|
||||
select_field_count))
|
||||
if (mysql_prepare_table(thd, create_info, alter_info, tmp_table,
|
||||
db_options, file,
|
||||
key_info_buffer, &key_count,
|
||||
select_field_count))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/* Check if table exists */
|
||||
@ -1503,8 +1508,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
create_info->table_options=db_options;
|
||||
|
||||
if (rea_create_table(thd, path, db, table_name,
|
||||
create_info, fields, key_count,
|
||||
key_info_buffer))
|
||||
create_info, alter_info->create_list,
|
||||
key_count, key_info_buffer))
|
||||
goto end;
|
||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||
{
|
||||
@ -1592,8 +1597,7 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
|
||||
|
||||
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
const char *db, const char *name,
|
||||
List<create_field> *extra_fields,
|
||||
List<Key> *keys,
|
||||
Alter_info *alter_info,
|
||||
List<Item> *items,
|
||||
MYSQL_LOCK **lock)
|
||||
{
|
||||
@ -1627,7 +1631,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
((Item_field *)item)->field :
|
||||
(Field*) 0))))
|
||||
DBUG_RETURN(0);
|
||||
extra_fields->push_back(cr_field);
|
||||
alter_info->create_list.push_back(cr_field);
|
||||
}
|
||||
/* create and lock table */
|
||||
/* QQ: create and open should be done atomic ! */
|
||||
@ -1641,8 +1645,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
open_table().
|
||||
*/
|
||||
tmp_disable_binlog(thd);
|
||||
if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
|
||||
*keys,0,select_field_count))
|
||||
if (!mysql_create_table(thd, db, name, create_info, alter_info,
|
||||
0, select_field_count))
|
||||
{
|
||||
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
|
||||
quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
|
||||
@ -2146,6 +2150,7 @@ send_result_message:
|
||||
|
||||
case HA_ADMIN_TRY_ALTER:
|
||||
{
|
||||
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||
/*
|
||||
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
||||
"try with alter", so here we close the table, do an ALTER TABLE,
|
||||
@ -2155,7 +2160,9 @@ send_result_message:
|
||||
TABLE_LIST *save_next= table->next;
|
||||
table->next= 0;
|
||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||
result_code= mysql_recreate_table(thd, table, 0);
|
||||
thd->net.no_send_ok= TRUE;
|
||||
result_code= mysql_recreate_table(thd, table);
|
||||
thd->net.no_send_ok= save_no_send_ok;
|
||||
reenable_binlog(thd);
|
||||
close_thread_tables(thd);
|
||||
if (!result_code) // recreation went ok
|
||||
@ -2635,206 +2642,6 @@ err:
|
||||
}
|
||||
|
||||
|
||||
#ifdef NOT_USED
|
||||
/*
|
||||
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
|
||||
the proper arguments. This isn't very fast but it should work for most
|
||||
cases.
|
||||
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
|
||||
*/
|
||||
|
||||
int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
|
||||
{
|
||||
List<create_field> fields;
|
||||
List<Alter_drop> drop;
|
||||
List<Alter_column> alter;
|
||||
HA_CREATE_INFO create_info;
|
||||
int rc;
|
||||
uint idx;
|
||||
uint db_options;
|
||||
uint key_count;
|
||||
TABLE *table;
|
||||
Field **f_ptr;
|
||||
KEY *key_info_buffer;
|
||||
char path[FN_REFLEN+1];
|
||||
DBUG_ENTER("mysql_create_index");
|
||||
|
||||
/*
|
||||
Try to use online generation of index.
|
||||
This requires that all indexes can be created online.
|
||||
Otherwise, the old alter table procedure is executed.
|
||||
|
||||
Open the table to have access to the correct table handler.
|
||||
*/
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
The add_index method takes an array of KEY structs for the new indexes.
|
||||
Preparing a new table structure generates this array.
|
||||
It needs a list with all fields of the table, which does not need to
|
||||
be correct in every respect. The field names are important.
|
||||
*/
|
||||
for (f_ptr= table->field; *f_ptr; f_ptr++)
|
||||
{
|
||||
create_field *c_fld= new create_field(*f_ptr, *f_ptr);
|
||||
c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
|
||||
fields.push_back(c_fld);
|
||||
}
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
db_options= 0;
|
||||
if (mysql_prepare_table(thd, &create_info, fields,
|
||||
keys, /*tmp_table*/ 0, db_options, table->file,
|
||||
key_info_buffer, key_count,
|
||||
/*select_field_count*/ 0))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
Check if all keys can be generated with the add_index method.
|
||||
If anyone cannot, then take the old way.
|
||||
*/
|
||||
for (idx=0; idx< key_count; idx++)
|
||||
{
|
||||
DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
|
||||
if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
|
||||
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
|
||||
break ;
|
||||
}
|
||||
if ((idx < key_count)|| !key_count)
|
||||
{
|
||||
/* Re-initialize the create_info, which was changed by prepare table. */
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
/* Cleanup the fields list. We do not want to create existing fields. */
|
||||
fields.delete_elements();
|
||||
if (real_alter_table(thd, table_list->db, table_list->real_name,
|
||||
&create_info, table_list, table,
|
||||
fields, keys, drop, alter, 0, (ORDER*)0,
|
||||
ALTER_ADD_INDEX, DUP_ERROR))
|
||||
/* Don't need to free((gptr) key_info_buffer);*/
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (table->file->add_index(table, key_info_buffer, key_count)||
|
||||
build_table_path(path, sizeof(path), table_list->db,
|
||||
(lower_case_table_names == 2) ?
|
||||
table_list->alias : table_list->real_name,
|
||||
reg_ext) == 0 ||
|
||||
mysql_create_frm(thd, path, &create_info,
|
||||
fields, key_count, key_info_buffer, table->file))
|
||||
/* don't need to free((gptr) key_info_buffer);*/
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
/* don't need to free((gptr) key_info_buffer);*/
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
|
||||
List<Alter_drop> &drop)
|
||||
{
|
||||
List<create_field> fields;
|
||||
List<Key> keys;
|
||||
List<Alter_column> alter;
|
||||
HA_CREATE_INFO create_info;
|
||||
uint idx;
|
||||
uint db_options;
|
||||
uint key_count;
|
||||
uint *key_numbers;
|
||||
TABLE *table;
|
||||
Field **f_ptr;
|
||||
KEY *key_info;
|
||||
KEY *key_info_buffer;
|
||||
char path[FN_REFLEN];
|
||||
DBUG_ENTER("mysql_drop_index");
|
||||
|
||||
/*
|
||||
Try to use online generation of index.
|
||||
This requires that all indexes can be created online.
|
||||
Otherwise, the old alter table procedure is executed.
|
||||
|
||||
Open the table to have access to the correct table handler.
|
||||
*/
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
The drop_index method takes an array of key numbers.
|
||||
It cannot get more entries than keys in the table.
|
||||
*/
|
||||
key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
|
||||
key_count= 0;
|
||||
|
||||
/*
|
||||
Get the number of each key and check if it can be created online.
|
||||
*/
|
||||
List_iterator<Alter_drop> drop_it(drop);
|
||||
Alter_drop *drop_key;
|
||||
while ((drop_key= drop_it++))
|
||||
{
|
||||
/* Find the key in the table. */
|
||||
key_info=table->key_info;
|
||||
for (idx=0; idx< table->keys; idx++, key_info++)
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
|
||||
break;
|
||||
}
|
||||
if (idx>= table->keys)
|
||||
{
|
||||
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
|
||||
/*don't need to free((gptr) key_numbers);*/
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
/*
|
||||
Check if the key can be generated with the add_index method.
|
||||
If anyone cannot, then take the old way.
|
||||
*/
|
||||
DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
|
||||
if (!(table->file->index_ddl_flags(table->key_info+idx)&
|
||||
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
|
||||
break ;
|
||||
key_numbers[key_count++]= idx;
|
||||
}
|
||||
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
|
||||
if ((drop_key)|| (drop.elements<= 0))
|
||||
{
|
||||
if (real_alter_table(thd, table_list->db, table_list->real_name,
|
||||
&create_info, table_list, table,
|
||||
fields, keys, drop, alter, 0, (ORDER*)0,
|
||||
ALTER_DROP_INDEX, DUP_ERROR))
|
||||
/*don't need to free((gptr) key_numbers);*/
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
db_options= 0;
|
||||
if (table->file->drop_index(table, key_numbers, key_count)||
|
||||
mysql_prepare_table(thd, &create_info, fields,
|
||||
keys, /*tmp_table*/ 0, db_options, table->file,
|
||||
key_info_buffer, key_count,
|
||||
/*select_field_count*/ 0)||
|
||||
build_table_path(path, sizeof(path), table_list->db,
|
||||
(lower_case_table_names == 2) ?
|
||||
table_list->alias : table_list->real_name,
|
||||
reg_ext) == 0 ||
|
||||
mysql_create_frm(thd, path, &create_info,
|
||||
fields, key_count, key_info_buffer, table->file))
|
||||
/*don't need to free((gptr) key_numbers);*/
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/*don't need to free((gptr) key_numbers);*/
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif /* NOT_USED */
|
||||
|
||||
|
||||
/*
|
||||
@ -2887,15 +2694,21 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
|
||||
|
||||
/*
|
||||
Alter table
|
||||
|
||||
|
||||
NOTE
|
||||
The structures passed as 'create_info' and 'alter_info' parameters may
|
||||
be modified by this function. It is responsibility of the caller to make
|
||||
a copy of create_info in order to provide correct execution in prepared
|
||||
statements/stored routines.
|
||||
*/
|
||||
|
||||
int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
List<create_field> &fields, List<Key> &keys,
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order,
|
||||
enum enum_duplicates handle_duplicates, bool ignore,
|
||||
ALTER_INFO *alter_info, bool do_send_ok)
|
||||
enum enum_duplicates handle_duplicates, bool ignore)
|
||||
{
|
||||
TABLE *table,*new_table;
|
||||
int error;
|
||||
@ -3064,8 +2877,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if (do_send_ok)
|
||||
send_ok(thd);
|
||||
send_ok(thd);
|
||||
}
|
||||
else if (error > 0)
|
||||
{
|
||||
@ -3091,10 +2903,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
|
||||
restore_record(table,default_values); // Empty record for DEFAULT
|
||||
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
||||
List_iterator<create_field> def_it(fields);
|
||||
List_iterator<create_field> def_it(alter_info->create_list);
|
||||
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
||||
List<create_field> create_list; // Add new fields here
|
||||
List<Key> key_list; // Add new keys here
|
||||
Alter_info new_info; // Add new columns and indexes here
|
||||
create_field *def;
|
||||
|
||||
/*
|
||||
@ -3140,13 +2951,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
def->field=field;
|
||||
if (!def->after)
|
||||
{
|
||||
create_list.push_back(def);
|
||||
new_info.create_list.push_back(def);
|
||||
def_it.remove();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Use old field value
|
||||
create_list.push_back(def=new create_field(field,field));
|
||||
new_info.create_list.push_back(def= new create_field(field, field));
|
||||
alter_it.rewind(); // Change default if ALTER
|
||||
Alter_column *alter;
|
||||
while ((alter=alter_it++))
|
||||
@ -3167,7 +2978,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
}
|
||||
}
|
||||
def_it.rewind();
|
||||
List_iterator<create_field> find_it(create_list);
|
||||
List_iterator<create_field> find_it(new_info.create_list);
|
||||
while ((def=def_it++)) // Add new columns
|
||||
{
|
||||
if (def->change && ! def->field)
|
||||
@ -3176,9 +2987,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (!def->after)
|
||||
create_list.push_back(def);
|
||||
new_info.create_list.push_back(def);
|
||||
else if (def->after == first_keyword)
|
||||
create_list.push_front(def);
|
||||
new_info.create_list.push_front(def);
|
||||
else
|
||||
{
|
||||
create_field *find;
|
||||
@ -3202,7 +3013,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
table_name);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (!create_list.elements)
|
||||
if (!new_info.create_list.elements)
|
||||
{
|
||||
my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
|
||||
DBUG_RETURN(-1);
|
||||
@ -3213,8 +3024,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
for which some fields exists.
|
||||
*/
|
||||
|
||||
List_iterator<Key> key_it(keys);
|
||||
List_iterator<create_field> field_it(create_list);
|
||||
List_iterator<Key> key_it(alter_info->key_list);
|
||||
List_iterator<create_field> field_it(new_info.create_list);
|
||||
List<key_part_spec> key_parts;
|
||||
|
||||
KEY *key_info=table->key_info;
|
||||
@ -3272,24 +3083,37 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
key_part_length));
|
||||
}
|
||||
if (key_parts.elements)
|
||||
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
|
||||
(key_info->flags & HA_NOSAME ?
|
||||
(!my_strcasecmp(system_charset_info,
|
||||
key_name, primary_key_name) ?
|
||||
Key::PRIMARY : Key::UNIQUE) :
|
||||
(key_info->flags & HA_FULLTEXT ?
|
||||
Key::FULLTEXT : Key::MULTIPLE)),
|
||||
key_name,
|
||||
key_info->algorithm,
|
||||
test(key_info->flags & HA_GENERATED_KEY),
|
||||
key_parts));
|
||||
{
|
||||
Key *key;
|
||||
enum Key::Keytype key_type;
|
||||
|
||||
if (key_info->flags & HA_SPATIAL)
|
||||
key_type= Key::SPATIAL;
|
||||
else if (key_info->flags & HA_NOSAME)
|
||||
{
|
||||
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
|
||||
key_type= Key::PRIMARY;
|
||||
else
|
||||
key_type= Key::UNIQUE;
|
||||
}
|
||||
else if (key_info->flags & HA_FULLTEXT)
|
||||
key_type= Key::FULLTEXT;
|
||||
else
|
||||
key_type= Key::MULTIPLE;
|
||||
|
||||
key= new Key(key_type, key_name,
|
||||
key_info->algorithm,
|
||||
test(key_info->flags & HA_GENERATED_KEY),
|
||||
key_parts);
|
||||
new_info.key_list.push_back(key);
|
||||
}
|
||||
}
|
||||
{
|
||||
Key *key;
|
||||
while ((key=key_it++)) // Add new keys
|
||||
{
|
||||
if (key->type != Key::FOREIGN_KEY)
|
||||
key_list.push_back(key);
|
||||
new_info.key_list.push_back(key);
|
||||
if (key->name &&
|
||||
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
|
||||
{
|
||||
@ -3393,7 +3217,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
/* We don't log the statement, it will be logged later. */
|
||||
tmp_disable_binlog(thd);
|
||||
error= mysql_create_table(thd, new_db, tmp_name,
|
||||
create_info,create_list,key_list,1,0);
|
||||
create_info, &new_info, 1, 0);
|
||||
reenable_binlog(thd);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
@ -3422,10 +3246,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
next_insert_id=thd->next_insert_id; // Remember for loggin
|
||||
copied=deleted=0;
|
||||
if (!new_table->is_view)
|
||||
error=copy_data_between_tables(table,new_table,create_list,
|
||||
handle_duplicates, ignore,
|
||||
order_num, order, &copied, &deleted,
|
||||
alter_info->keys_onoff);
|
||||
error= copy_data_between_tables(table, new_table, new_info.create_list,
|
||||
handle_duplicates, ignore,
|
||||
order_num, order, &copied, &deleted,
|
||||
alter_info->keys_onoff);
|
||||
/*
|
||||
No need to have call to alter_table_manage_keys() in the else because
|
||||
in 4.1 we always copy data, except for views. In 5.0 it could happen
|
||||
@ -3637,8 +3461,7 @@ end_temporary:
|
||||
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
|
||||
(ulong) (copied + deleted), (ulong) deleted,
|
||||
(ulong) thd->cuted_fields);
|
||||
if (do_send_ok)
|
||||
send_ok(thd,copied+deleted,0L,tmp_name);
|
||||
send_ok(thd, copied + deleted, 0L, tmp_name);
|
||||
thd->some_tables_deleted=0;
|
||||
DBUG_RETURN(0);
|
||||
|
||||
@ -3828,30 +3651,26 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
mysql_recreate_table()
|
||||
thd Thread handler
|
||||
tables Tables to recreate
|
||||
do_send_ok If we should send_ok() or leave it to caller
|
||||
|
||||
RETURN
|
||||
Like mysql_alter_table().
|
||||
*/
|
||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
||||
bool do_send_ok)
|
||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
|
||||
{
|
||||
DBUG_ENTER("mysql_recreate_table");
|
||||
LEX *lex= thd->lex;
|
||||
HA_CREATE_INFO create_info;
|
||||
lex->create_list.empty();
|
||||
lex->key_list.empty();
|
||||
lex->col_list.empty();
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.is_simple= 0; // Force full recreate
|
||||
Alter_info alter_info;
|
||||
|
||||
DBUG_ENTER("mysql_recreate_table");
|
||||
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.row_type=ROW_TYPE_DEFAULT;
|
||||
create_info.default_table_charset=default_charset_info;
|
||||
alter_info.is_simple= 0; // Force full recreate
|
||||
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
|
||||
table_list, lex->create_list,
|
||||
lex->key_list, 0, (ORDER *) 0,
|
||||
DUP_ERROR, 0, &lex->alter_info, do_send_ok));
|
||||
table_list, &alter_info,
|
||||
0, (ORDER *) 0, DUP_ERROR, 0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1021,8 +1021,7 @@ create:
|
||||
TL_READ_NO_INSERT:
|
||||
TL_READ)))
|
||||
YYABORT;
|
||||
lex->create_list.empty();
|
||||
lex->key_list.empty();
|
||||
lex->alter_info.reset();
|
||||
lex->col_list.empty();
|
||||
lex->change=NullS;
|
||||
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
||||
@ -1040,16 +1039,18 @@ create:
|
||||
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
|
||||
TL_OPTION_UPDATING))
|
||||
YYABORT;
|
||||
lex->create_list.empty();
|
||||
lex->key_list.empty();
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.is_simple= 0;
|
||||
lex->alter_info.flags= ALTER_ADD_INDEX;
|
||||
lex->col_list.empty();
|
||||
lex->change=NullS;
|
||||
}
|
||||
'(' key_list ')'
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
Key *key= new Key($2, $4.str, $5, 0, lex->col_list);
|
||||
|
||||
lex->key_list.push_back(new Key($2,$4.str, $5, 0, lex->col_list));
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
lex->col_list.empty();
|
||||
}
|
||||
| CREATE DATABASE opt_if_not_exists ident
|
||||
@ -1305,29 +1306,34 @@ key_def:
|
||||
key_type opt_ident key_alg '(' key_list ')'
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list));
|
||||
Key *key= new Key($1, $2, $3, 0, lex->col_list);
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
|
||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||
}
|
||||
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
const char *key_name= $3 ? $3:$1;
|
||||
lex->key_list.push_back(new Key($2, key_name, $4, 0,
|
||||
lex->col_list));
|
||||
Key *key= new Key($2, key_name, $4, 0, lex->col_list);
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||
}
|
||||
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->key_list.push_back(new foreign_key($4 ? $4:$1, lex->col_list,
|
||||
$8,
|
||||
lex->ref_list,
|
||||
lex->fk_delete_opt,
|
||||
lex->fk_update_opt,
|
||||
lex->fk_match_option));
|
||||
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
|
||||
HA_KEY_ALG_UNDEF, 1,
|
||||
lex->col_list));
|
||||
const char *key_name= $4 ? $4 : $1;
|
||||
Key *key= new foreign_key(key_name, lex->col_list,
|
||||
$8,
|
||||
lex->ref_list,
|
||||
lex->fk_delete_opt,
|
||||
lex->fk_update_opt,
|
||||
lex->fk_match_option);
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
key= new Key(Key::MULTIPLE, key_name,
|
||||
HA_KEY_ALG_UNDEF, 1,
|
||||
lex->col_list);
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||
}
|
||||
| constraint opt_check_constraint
|
||||
@ -1850,8 +1856,6 @@ alter:
|
||||
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
|
||||
TL_OPTION_UPDATING))
|
||||
YYABORT;
|
||||
lex->create_list.empty();
|
||||
lex->key_list.empty();
|
||||
lex->col_list.empty();
|
||||
lex->select_lex.init_order();
|
||||
lex->select_lex.db=lex->name=0;
|
||||
@ -1859,9 +1863,7 @@ alter:
|
||||
lex->create_info.db_type= DB_TYPE_DEFAULT;
|
||||
lex->create_info.default_table_charset= NULL;
|
||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.is_simple= 1;
|
||||
lex->alter_info.flags= 0;
|
||||
lex->alter_info.reset();
|
||||
}
|
||||
alter_list
|
||||
{}
|
||||
@ -4030,7 +4032,9 @@ drop:
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command= SQLCOM_DROP_INDEX;
|
||||
lex->alter_info.drop_list.empty();
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.is_simple= 0;
|
||||
lex->alter_info.flags= ALTER_DROP_INDEX;
|
||||
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
||||
$3.str));
|
||||
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
|
||||
|
@ -340,7 +340,7 @@ install -m 644 libmysqld/libmysqld.a $RBR%{_libdir}/mysql/
|
||||
# Include libgcc.a in the devel subpackage (BUG 4921)
|
||||
if expr "$CC" : ".*gcc.*" > /dev/null ;
|
||||
then
|
||||
libgcc=`$CC --print-libgcc-file`
|
||||
libgcc=`$CC $CFLAGS --print-libgcc-file`
|
||||
if [ -f $libgcc ]
|
||||
then
|
||||
%define have_libgcc 1
|
||||
@ -726,6 +726,11 @@ fi
|
||||
# itself - note that they must be ordered by date (important when
|
||||
# merging BK trees)
|
||||
%changelog
|
||||
* Fri Jan 05 2007 Kent Boortz <kent@mysql.com>
|
||||
|
||||
- Add CFLAGS to gcc call with --print-libgcc-file, to make sure the
|
||||
correct "libgcc.a" path is returned for the 32/64 bit architecture.
|
||||
|
||||
* Thu Dec 14 2006 Joerg Bruehe <joerg@mysql.com>
|
||||
|
||||
- Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql"
|
||||
|
Loading…
x
Reference in New Issue
Block a user