Merge bk-internal.mysql.com:/home/bk/mysql-5.1

into  bodhi.local:/opt/local/work/mysql-5.1-runtime-merge
This commit is contained in:
kostja@bodhi.local 2006-07-28 18:02:38 +04:00
commit 4bd7acec3f
43 changed files with 2548 additions and 161 deletions

View file

@ -1,4 +1,6 @@
*-t
*.Plo
*.Po
*.a
*.bb
*.bbg
@ -12,6 +14,7 @@
*.gcov
*.idb
*.la
*.lai
*.lib
*.lo
*.map
@ -23,6 +26,7 @@
*.res
*.sbr
*.so
*.so.*
*.spec
*/*_pure_*warnings
*/.pure
@ -283,6 +287,7 @@ build_tags.sh
client/#mysql.cc#
client/*.ds?
client/*.vcproj
client/.libs -prune
client/completion_hash.cpp
client/decimal.c
client/insert_test
@ -578,6 +583,7 @@ libmysqld/sql_insert.cc
libmysqld/sql_lex.cc
libmysqld/sql_list.cc
libmysqld/sql_load.cc
libmysqld/sql_locale.cc
libmysqld/sql_manager.cc
libmysqld/sql_map.cc
libmysqld/sql_olap.cc
@ -1755,6 +1761,7 @@ test1/*
test_xml
tests/*.ds?
tests/*.vcproj
tests/.libs -prune
tests/client_test
tests/connect_test
tests/mysql_client_test
@ -1762,6 +1769,7 @@ thr_insert_test/*
thr_test/*
thread_test
tmp/*
tools/.libs -prune
tools/my_vsnprintf.c
tools/mysqlmanager
tools/mysqlmngd

View file

@ -61,8 +61,9 @@ ADD_LIBRARY(mysqldemb emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_update.cc ../sql/sql_view.cc
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../vio/vio.c
../vio/viosocket.c ../vio/viossl.c ../vio/viosslfactories.c
../sql/partition_info.cc ../sql/sql_locale.cc
../vio/vio.c ../vio/viosocket.c ../vio/viossl.c
../vio/viosslfactories.c
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h)

View file

@ -56,7 +56,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
key.cc lock.cc log.cc log_event.cc sql_state.c \
protocol.cc net_serv.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
sql_load.cc discover.cc \
sql_load.cc discover.cc sql_locale.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \

View file

@ -12,3 +12,20 @@ about:text CREATE TABLE `about:text` (
PRIMARY KEY (`_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table `about:text`;
use test;
drop table if exists t1;
create table t1(a int) engine=myisam;
insert into t1 values(1);
"We get an error because the table is in the definition cache"
create table t1(a int, b int);
ERROR 42S01: Table 't1' already exists
"Flush the cache and recreate the table anew to be able to drop it"
flush tables;
show open tables like "t%";
Database Table In_use Name_locked
create table t1(a int, b int, c int);
"Try to select from the table. This should not crash the server"
select count(a) from t1;
count(a)
0
drop table t1;

View file

@ -498,6 +498,22 @@ f1 f2
Warnings:
Warning 1292 Truncated incorrect date value: '2003-04-05 g'
Warning 1292 Truncated incorrect datetime value: '2003-04-05 10:11:12.101010234567'
set names latin1;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
date_format('2004-01-01','%W (%a), %e %M (%b) %Y')
Thursday (Thu), 1 January (Jan) 2004
set lc_time_names=ru_RU;
set names koi8r;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
date_format('2004-01-01','%W (%a), %e %M (%b) %Y')
þÅÔ×ÅÒÇ (þÔ×), 1 ñÎ×ÁÒÑ (ñÎ×) 2004
set lc_time_names=de_DE;
set names latin1;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
date_format('2004-01-01','%W (%a), %e %M (%b) %Y')
Donnerstag (Do), 1 Januar (Jan) 2004
set names latin1;
set lc_time_names=en_US;
create table t1 (f1 datetime);
insert into t1 (f1) values ("2005-01-01");
insert into t1 (f1) values ("2005-02-01");

View file

@ -1603,22 +1603,6 @@ fld_cid fld_name fld_parentid fld_delt
5 Torkel 0 0
DROP TABLE federated.t1;
DROP TABLE federated.bug_17377_table;
create table t1 (id int not null auto_increment primary key, val int);
create table t1
(id int not null auto_increment primary key, val int) engine=federated
connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
insert into t1 values (1,0),(2,0);
update t1 set val = NULL where id = 1;
select * from t1;
id val
1 NULL
2 0
select * from t1;
id val
1 NULL
2 0
drop table t1;
drop table t1;
drop table if exists federated.t1;
create table federated.t1 (a int, b int, c int);
drop table if exists federated.t1;
@ -1733,6 +1717,23 @@ id c1 c2
9 abc ppc
drop table federated.t1, federated.t2;
drop table federated.t1, federated.t2;
create table t1 (id int not null auto_increment primary key, val int);
create table t1
(id int not null auto_increment primary key, val int) engine=federated
connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
insert into t1 values (1,0),(2,0);
update t1 set val = NULL where id = 1;
select * from t1;
id val
1 NULL
2 0
select * from t1;
id val
1 NULL
2 0
drop table t1;
drop table t1;
End of 5.0 tests
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;

View file

@ -22,3 +22,117 @@ set GLOBAL init_connect="adsfsdfsdfs";
select @a;
Got one of the listed errors
drop table t1;
End of 4.1 tests
create table t1 (x int);
insert into t1 values (3), (5), (7);
create table t2 (y int);
create user mysqltest1@localhost;
grant all privileges on test.* to mysqltest1@localhost;
set global init_connect="create procedure p1() select * from t1";
call p1();
x
3
5
7
drop procedure p1;
set global init_connect="create procedure p1(x int)\
begin\
select count(*) from t1;\
select * from t1;\
set @x = x;
end";
call p1(42);
count(*)
3
x
3
5
7
select @x;
@x
42
set global init_connect="call p1(4711)";
select @x;
@x
4711
set global init_connect="drop procedure if exists p1";
call p1();
ERROR 42000: PROCEDURE test.p1 does not exist
create procedure p1(out sum int)
begin
declare n int default 0;
declare c cursor for select * from t1;
declare exit handler for not found
begin
close c;
set sum = n;
end;
open c;
loop
begin
declare x int;
fetch c into x;
if x > 3 then
set n = n + x;
end if;
end;
end loop;
end|
set global init_connect="call p1(@sum)";
select @sum;
@sum
12
drop procedure p1;
create procedure p1(tbl char(10), v int)
begin
set @s = concat('insert into ', tbl, ' values (?)');
set @v = v;
prepare stmt1 from @s;
execute stmt1 using @v;
deallocate prepare stmt1;
end|
set global init_connect="call p1('t1', 11)";
select * from t1;
x
3
5
7
11
drop procedure p1;
create function f1() returns int
begin
declare n int;
select count(*) into n from t1;
return n;
end|
set global init_connect="set @x = f1()";
select @x;
@x
4
set global init_connect="create view v1 as select f1()";
select * from v1;
f1()
4
set global init_connect="drop view v1";
select * from v1;
ERROR 42S02: Table 'test.v1' doesn't exist
drop function f1;
create trigger trg1
after insert on t2
for each row
insert into t1 values (new.y);
set global init_connect="insert into t2 values (13), (17), (19)";
select * from t1;
x
3
5
7
11
13
17
19
drop trigger trg1;
set global init_connect=default;
revoke all privileges, grant option from mysqltest1@localhost;
drop user mysqltest1@localhost;
drop table t1, t2;

View file

@ -1 +1,16 @@
ok
end of 4.1 tests
select * from t1;
x
3
5
7
11
13
select * from t2;
y
30
3
11
13
drop table t1, t2;

View file

@ -1436,12 +1436,27 @@ show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 a 1 a A 8 NULL NULL YES BTREE
drop table t1;
show create table t1;
show create table t1;
create table t1 (a int) engine=myisam select 42 a;
select * from t1;
a
9
select * from t1;
a
99
select * from t1;
a
42
drop table t1;
End of 4.1 tests
create table t1 (c1 int) engine=myisam pack_keys=0;
create table t2 (c1 int) engine=myisam pack_keys=1;
create table t3 (c1 int) engine=myisam pack_keys=default;
create table t4 (c1 int) engine=myisam pack_keys=2;
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 '2' at line 1
drop table t1, t2, t3;
End of 5.0 tests
create table t1 (a int not null, key `a` (a) key_block_size=1024);
show create table t1;
Table Create Table
@ -1588,3 +1603,4 @@ create table t1 (a int not null, key key_block_size=1024 (a));
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 '=1024 (a))' at line 1
create table t1 (a int not null, key `a` key_block_size=1024 (a));
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 'key_block_size=1024 (a))' at line 1
End of 5.1 tests

View file

@ -661,3 +661,56 @@ DROP VIEW test2.t3;
DROP TABLE test2.t1, test1.t0;
DROP DATABASE test2;
DROP DATABASE test1;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2;
DROP VIEW IF EXISTS v3;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
DROP PROCEDURE IF EXISTS p1;
CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu;
CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER
RETURN CURRENT_USER();
CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu;
CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER
SET cu= CURRENT_USER();
CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER
BEGIN
DECLARE cu VARCHAR(77);
CALL p1(cu);
RETURN cu;
END|
CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu;
CREATE USER mysqltest_u1@localhost;
GRANT ALL ON test.* TO mysqltest_u1@localhost;
The following tests should all return 1.
SELECT CURRENT_USER() = 'mysqltest_u1@localhost';
CURRENT_USER() = 'mysqltest_u1@localhost'
1
SELECT f1() = 'mysqltest_u1@localhost';
f1() = 'mysqltest_u1@localhost'
1
CALL p1(@cu);
SELECT @cu = 'mysqltest_u1@localhost';
@cu = 'mysqltest_u1@localhost'
1
SELECT f2() = 'mysqltest_u1@localhost';
f2() = 'mysqltest_u1@localhost'
1
SELECT cu = 'root@localhost' FROM v1;
cu = 'root@localhost'
1
SELECT cu = 'root@localhost' FROM v2;
cu = 'root@localhost'
1
SELECT cu = 'root@localhost' FROM v3;
cu = 'root@localhost'
1
DROP VIEW v3;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP FUNCTION f1;
DROP VIEW v2;
DROP VIEW v1;
DROP USER mysqltest_u1@localhost;

View file

@ -1 +1,29 @@
select * from mysql.user as t1, mysql.user as t2, mysql.user as t3;
use test;
drop table if exists t1;
create table t1 (x int);
drop table if exists t2;
create table t2 (y int);
drop procedure if exists p1;
create definer=root@localhost procedure p1() select * from t1;
call p1();
drop procedure p1;
create definer=root@localhost procedure p1() insert into t1 values (3),(5),(7);
call p1();
drop function if exists f1;
create definer=root@localhost function f1() returns int return (select count(*) from t1);
insert into t2 set y = f1()*10;
drop view if exists v1;
create definer=root@localhost view v1 as select f1();
insert into t2 (y) select * from v1;
create trigger trg1 after insert on t2 for each row insert into t1 values (new.y);
insert into t2 values (11), (13);
drop procedure p1;
drop function f1;
drop view v1;

View file

@ -18,3 +18,24 @@ show create table `about:text`;
drop table `about:text`;
# End of 5.0 tests
#
# Bug#16532:mysql server assert in debug if table det is removed
#
use test;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(a int) engine=myisam;
insert into t1 values(1);
--system rm -f $MYSQLTEST_VARDIR/master-data/test/t1.frm
--echo "We get an error because the table is in the definition cache"
--error ER_TABLE_EXISTS_ERROR
create table t1(a int, b int);
--echo "Flush the cache and recreate the table anew to be able to drop it"
flush tables;
show open tables like "t%";
create table t1(a int, b int, c int);
--echo "Try to select from the table. This should not crash the server"
select count(a) from t1;
drop table t1;

View file

@ -264,6 +264,20 @@ select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
--enable_ps_protocol
#
# Test of locale dependent date format (WL#2928 Date Translation NRE)
#
set names latin1;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
set lc_time_names=ru_RU;
set names koi8r;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
set lc_time_names=de_DE;
set names latin1;
select date_format('2004-01-01','%W (%a), %e %M (%b) %Y');
set names latin1;
set lc_time_names=en_US;
#
# Bug #14016
#

View file

@ -1366,25 +1366,6 @@ drop table federated.t1, federated.t2;
connection master;
--enable_parsing
#
# Bug #16494: Updates that set a column to NULL fail sometimes
#
connection slave;
create table t1 (id int not null auto_increment primary key, val int);
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table t1
(id int not null auto_increment primary key, val int) engine=federated
connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
insert into t1 values (1,0),(2,0);
update t1 set val = NULL where id = 1;
select * from t1;
connection slave;
select * from t1;
drop table t1;
connection master;
drop table t1;
#
# Additional test for bug#18437 "Wrong values inserted with a before
# update trigger on NDB table". SQL-layer didn't properly inform
@ -1479,5 +1460,26 @@ drop table federated.t1, federated.t2;
connection slave;
drop table federated.t1, federated.t2;
#
# Bug #16494: Updates that set a column to NULL fail sometimes
#
connection slave;
create table t1 (id int not null auto_increment primary key, val int);
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table t1
(id int not null auto_increment primary key, val int) engine=federated
connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
insert into t1 values (1,0),(2,0);
update t1 set val = NULL where id = 1;
select * from t1;
connection slave;
select * from t1;
drop table t1;
connection master;
drop table t1;
--echo End of 5.0 tests
source include/federated_cleanup.inc;

View file

@ -35,4 +35,205 @@ select @a;
connection con0;
drop table t1;
# End of 4.1 tests
disconnect con1;
disconnect con2;
disconnect con3;
disconnect con4;
disconnect con5;
--echo End of 4.1 tests
#
# Test 5.* features
#
create table t1 (x int);
insert into t1 values (3), (5), (7);
create table t2 (y int);
create user mysqltest1@localhost;
grant all privileges on test.* to mysqltest1@localhost;
#
# Create a simple procedure
#
set global init_connect="create procedure p1() select * from t1";
connect (con1,localhost,mysqltest1,,);
connection con1;
call p1();
drop procedure p1;
connection con0;
disconnect con1;
#
# Create a multi-result set procedure
#
set global init_connect="create procedure p1(x int)\
begin\
select count(*) from t1;\
select * from t1;\
set @x = x;
end";
connect (con1,localhost,mysqltest1,,);
connection con1;
call p1(42);
select @x;
connection con0;
disconnect con1;
#
# Just call it - this will not generate any output
#
set global init_connect="call p1(4711)";
connect (con1,localhost,mysqltest1,,);
connection con1;
select @x;
connection con0;
disconnect con1;
#
# Drop the procedure
#
set global init_connect="drop procedure if exists p1";
connect (con1,localhost,mysqltest1,,);
connection con1;
--error ER_SP_DOES_NOT_EXIST
call p1();
connection con0;
disconnect con1;
#
# Execution of a more complex procedure
#
delimiter |;
create procedure p1(out sum int)
begin
declare n int default 0;
declare c cursor for select * from t1;
declare exit handler for not found
begin
close c;
set sum = n;
end;
open c;
loop
begin
declare x int;
fetch c into x;
if x > 3 then
set n = n + x;
end if;
end;
end loop;
end|
delimiter ;|
# Call the procedure with a cursor
set global init_connect="call p1(@sum)";
connect (con1,localhost,mysqltest1,,);
connection con1;
select @sum;
connection con0;
disconnect con1;
drop procedure p1;
#
# Test Dynamic SQL
#
delimiter |;
create procedure p1(tbl char(10), v int)
begin
set @s = concat('insert into ', tbl, ' values (?)');
set @v = v;
prepare stmt1 from @s;
execute stmt1 using @v;
deallocate prepare stmt1;
end|
delimiter ;|
# Call the procedure with prepared statements
set global init_connect="call p1('t1', 11)";
connect (con1,localhost,mysqltest1,,);
connection con1;
select * from t1;
connection con0;
disconnect con1;
drop procedure p1;
#
# Stored functions
#
delimiter |;
create function f1() returns int
begin
declare n int;
select count(*) into n from t1;
return n;
end|
delimiter ;|
# Invoke a function
set global init_connect="set @x = f1()";
connect (con1,localhost,mysqltest1,,);
connection con1;
select @x;
connection con0;
disconnect con1;
#
# Create a view
#
set global init_connect="create view v1 as select f1()";
connect (con1,localhost,mysqltest1,,);
connection con1;
select * from v1;
connection con0;
disconnect con1;
#
# Drop the view
#
set global init_connect="drop view v1";
connect (con1,localhost,mysqltest1,,);
connection con1;
--error ER_NO_SUCH_TABLE
select * from v1;
connection con0;
disconnect con1;
drop function f1;
# We can't test "create trigger", since this requires super privileges
# in 5.0, but with super privileges, init_connect is not executed.
# (However, this can be tested in 5.1)
#
#set global init_connect="create trigger trg1\
# after insert on t2\
# for each row\
# insert into t1 values (new.y)";
#connect (con1,localhost,mysqltest1,,);
#connection con1;
#insert into t2 values (2), (4);
#select * from t1;
#
#connection con0;
#disconnect con1;
create trigger trg1
after insert on t2
for each row
insert into t1 values (new.y);
# Invoke trigger
set global init_connect="insert into t2 values (13), (17), (19)";
connect (con1,localhost,mysqltest1,,);
connection con1;
select * from t1;
connection con0;
disconnect con1;
drop trigger trg1;
set global init_connect=default;
revoke all privileges, grant option from mysqltest1@localhost;
drop user mysqltest1@localhost;
drop table t1, t2;

View file

@ -6,5 +6,15 @@
# mysql-test/t/init_file-master.opt for the actual test
#
# End of 4.1 tests
echo ok;
--echo ok
--echo end of 4.1 tests
#
# Chec 5.x features
#
# Expected:
# 3, 5, 7, 11, 13
select * from t1;
# Expected:
# 30, 3, 11, 13
select * from t2;
drop table t1, t2;

View file

@ -718,8 +718,6 @@ UPDATE t1 AS ta1,t1 AS ta2 SET ta1.b='aaaaaa',ta2.b='bbbbbb';
SELECT * FROM t1;
DROP TABLE t1;
# End of 4.1 tests
#
# Test varchar
#
@ -817,6 +815,42 @@ alter table t1 enable keys;
show keys from t1;
drop table t1;
#
# Bug#8706 - temporary table with data directory option fails
#
connect (session1,localhost,root,,);
connect (session2,localhost,root,,);
connection session1;
disable_query_log;
eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 9 a;
enable_query_log;
disable_result_log;
show create table t1;
enable_result_log;
connection session2;
disable_query_log;
eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 99 a;
enable_query_log;
disable_result_log;
show create table t1;
enable_result_log;
connection default;
create table t1 (a int) engine=myisam select 42 a;
connection session1;
select * from t1;
disconnect session1;
connection session2;
select * from t1;
disconnect session2;
connection default;
select * from t1;
drop table t1;
--echo End of 4.1 tests
#
# Bug#10056 - PACK_KEYS option take values greater than 1 while creating table
@ -828,6 +862,8 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
create table t4 (c1 int) engine=myisam pack_keys=2;
drop table t1, t2, t3;
--echo End of 5.0 tests
#
# Test of key_block_size
#
@ -890,3 +926,5 @@ drop table t1;
create table t1 (a int not null, key key_block_size=1024 (a));
--error 1064
create table t1 (a int not null, key `a` key_block_size=1024 (a));
--echo End of 5.1 tests

View file

@ -1168,12 +1168,11 @@ insert into t values(5, 51);
create view v1 as select qty, price, qty*price as value from t;
create view v2 as select qty from v1;
--echo mysqldump {
--exec $MYSQL_DUMP --compact -F --tab . test
--exec cat v1.sql
--exec $MYSQL_DUMP --compact -F --tab $MYSQLTEST_VARDIR/tmp test
--exec cat $MYSQLTEST_VARDIR/tmp/v1.sql
--echo } mysqldump {
--exec cat v2.sql
--exec cat $MYSQLTEST_VARDIR/tmp/v2.sql
--echo } mysqldump
--rm v.sql t.sql t.txt
drop view v1;
drop view v2;
drop table t;

View file

@ -872,3 +872,65 @@ DROP VIEW test2.t3;
DROP TABLE test2.t1, test1.t0;
DROP DATABASE test2;
DROP DATABASE test1;
#
# BUG#20570: CURRENT_USER() in a VIEW with SQL SECURITY DEFINER
# returns invoker name
#
--disable_warnings
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v2;
DROP VIEW IF EXISTS v3;
DROP FUNCTION IF EXISTS f1;
DROP FUNCTION IF EXISTS f2;
DROP PROCEDURE IF EXISTS p1;
--enable_warnings
CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu;
CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER
RETURN CURRENT_USER();
CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu;
CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER
SET cu= CURRENT_USER();
delimiter |;
CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER
BEGIN
DECLARE cu VARCHAR(77);
CALL p1(cu);
RETURN cu;
END|
delimiter ;|
CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu;
CREATE USER mysqltest_u1@localhost;
GRANT ALL ON test.* TO mysqltest_u1@localhost;
connect (conn1, localhost, mysqltest_u1,,);
--echo
--echo The following tests should all return 1.
--echo
SELECT CURRENT_USER() = 'mysqltest_u1@localhost';
SELECT f1() = 'mysqltest_u1@localhost';
CALL p1(@cu);
SELECT @cu = 'mysqltest_u1@localhost';
SELECT f2() = 'mysqltest_u1@localhost';
SELECT cu = 'root@localhost' FROM v1;
SELECT cu = 'root@localhost' FROM v2;
SELECT cu = 'root@localhost' FROM v3;
disconnect conn1;
connection default;
DROP VIEW v3;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP FUNCTION f1;
DROP VIEW v2;
DROP VIEW v1;
DROP USER mysqltest_u1@localhost;
# End of 5.0 tests.

View file

@ -53,7 +53,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc
sql_tablespace.cc events.cc ../sql-common/my_user.c
partition_info.cc rpl_injector.cc
partition_info.cc rpl_injector.cc sql_locale.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h

View file

@ -80,7 +80,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
set_var.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_prepare.cc sql_error.cc \
sql_prepare.cc sql_error.cc sql_locale.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \

View file

@ -296,12 +296,6 @@ Item *create_func_pow(Item* a, Item *b)
return new Item_func_pow(a,b);
}
Item *create_func_current_user()
{
current_thd->lex->safe_to_cache_query= 0;
return new Item_func_user(TRUE);
}
Item *create_func_radians(Item *a)
{
return new Item_func_units((char*) "radians",a,M_PI/180,0.0);

View file

@ -73,7 +73,6 @@ Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);

View file

@ -2505,8 +2505,7 @@ void udf_handler::cleanup()
{
if (u_d->func_deinit != NULL)
{
void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
u_d->func_deinit;
Udf_func_deinit deinit= u_d->func_deinit;
(*deinit)(&initid);
}
free_udf(u_d);
@ -2651,9 +2650,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
}
}
thd->net.last_error[0]=0;
my_bool (*init)(UDF_INIT *, UDF_ARGS *, char *)=
(my_bool (*)(UDF_INIT *, UDF_ARGS *, char *))
u_d->func_init;
Udf_func_init init= u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
{
my_error(ER_CANT_INITIALIZE_UDF, MYF(0),

View file

@ -1670,42 +1670,51 @@ String *Item_func_database::val_str(String *str)
return str;
}
// TODO: make USER() replicate properly (currently it is replicated to "")
String *Item_func_user::val_str(String *str)
/*
TODO: make USER() replicate properly (currently it is replicated to "")
*/
bool Item_func_user::init(const char *user, const char *host)
{
DBUG_ASSERT(fixed == 1);
THD *thd=current_thd;
CHARSET_INFO *cs= system_charset_info;
const char *host, *user;
uint res_length;
if (is_current)
{
user= thd->security_ctx->priv_user;
host= thd->security_ctx->priv_host;
}
else
{
user= thd->main_security_ctx.user;
host= thd->main_security_ctx.host_or_ip;
}
// For system threads (e.g. replication SQL thread) user may be empty
if (!user)
return &my_empty_string;
res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
if (str->alloc(res_length))
if (user)
{
null_value=1;
return 0;
CHARSET_INFO *cs= str_value.charset();
uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
if (str_value.alloc(res_length))
{
null_value=1;
return TRUE;
}
res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length,
"%s@%s", user, host);
str_value.length(res_length);
str_value.mark_as_const();
}
res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",
user, host);
str->length(res_length);
str->set_charset(cs);
return str;
return FALSE;
}
bool Item_func_user::fix_fields(THD *thd, Item **ref)
{
return (Item_func_sysconst::fix_fields(thd, ref) ||
init(thd->main_security_ctx.user,
thd->main_security_ctx.host_or_ip));
}
bool Item_func_current_user::fix_fields(THD *thd, Item **ref)
{
if (Item_func_sysconst::fix_fields(thd, ref))
return TRUE;
Security_context *ctx= (context->security_ctx
? context->security_ctx : thd->security_ctx);
return init(ctx->priv_user, ctx->priv_host);
}

View file

@ -393,21 +393,40 @@ public:
class Item_func_user :public Item_func_sysconst
{
bool is_current;
protected:
bool init (const char *user, const char *host);
public:
Item_func_user(bool is_current_arg)
:Item_func_sysconst(), is_current(is_current_arg) {}
String *val_str(String *);
Item_func_user()
{
str_value.set("", 0, system_charset_info);
}
String *val_str(String *)
{
DBUG_ASSERT(fixed == 1);
return (null_value ? 0 : &str_value);
}
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec()
{
max_length= ((USERNAME_LENGTH + HOSTNAME_LENGTH + 1) *
system_charset_info->mbmaxlen);
}
const char *func_name() const
{ return is_current ? "current_user" : "user"; }
const char *fully_qualified_func_name() const
{ return is_current ? "current_user()" : "user()"; }
const char *func_name() const { return "user"; }
const char *fully_qualified_func_name() const { return "user()"; }
};
class Item_func_current_user :public Item_func_user
{
Name_resolution_context *context;
public:
Item_func_current_user(Name_resolution_context *context_arg)
: context(context_arg) {}
bool fix_fields(THD *thd, Item **ref);
const char *func_name() const { return "current_user"; }
const char *fully_qualified_func_name() const { return "current_user()"; }
};

View file

@ -30,25 +30,6 @@
/* Day number for Dec 31st, 9999 */
#define MAX_DAY_NUMBER 3652424L
static const char *month_names[]=
{
"January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December", NullS
};
TYPELIB month_names_typelib=
{ array_elements(month_names)-1,"", month_names, NULL };
static const char *day_names[]=
{
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" ,"Sunday", NullS
};
TYPELIB day_names_typelib=
{ array_elements(day_names)-1,"", day_names, NULL};
/*
OPTIMIZATION TODO:
- Replace the switch with a function that should be called for each
@ -223,8 +204,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
val= tmp;
break;
case 'M':
if ((l_time->month= check_word(my_locale_en_US.month_names,
val, val_end, &val)) <= 0)
goto err;
break;
case 'b':
if ((l_time->month= check_word(&month_names_typelib,
if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
val, val_end, &val)) <= 0)
goto err;
break;
@ -299,8 +284,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
/* Exotic things */
case 'W':
if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
goto err;
break;
case 'a':
if ((weekday= check_word(&day_names_typelib, val, val_end, &val)) <= 0)
if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
goto err;
break;
case 'w':
@ -502,9 +490,16 @@ 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[STRING_BUFFER_USUAL_SIZE];
String tmp(buf, sizeof(buf), thd->variables.character_set_results);
uint errors= 0;
tmp.length(0);
str->length(0);
str->set_charset(&my_charset_bin);
locale = thd->variables.lc_time_names;
if (l_time->neg)
str->append('-');
@ -520,26 +515,38 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
case 'M':
if (!l_time->month)
return 1;
str->append(month_names[l_time->month-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;
case 'b':
if (!l_time->month)
return 1;
str->append(month_names[l_time->month-1],3);
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;
case 'W':
if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
str->append(day_names[weekday]);
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;
case 'a':
if (type == MYSQL_TIMESTAMP_TIME)
return 1;
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
l_time->day),0);
str->append(day_names[weekday],3);
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;
case 'D':
if (type == MYSQL_TIMESTAMP_TIME)
@ -872,6 +879,7 @@ String* Item_func_monthname::val_str(String* str)
DBUG_ASSERT(fixed == 1);
const char *month_name;
uint month= (uint) val_int();
THD *thd= current_thd;
if (null_value || !month)
{
@ -879,7 +887,7 @@ String* Item_func_monthname::val_str(String* str)
return (String*) 0;
}
null_value=0;
month_name= month_names[month-1];
month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
str->set(month_name, strlen(month_name), system_charset_info);
return str;
}
@ -1004,11 +1012,12 @@ String* Item_func_dayname::val_str(String* str)
DBUG_ASSERT(fixed == 1);
uint weekday=(uint) val_int(); // Always Item_func_daynr()
const char *name;
THD *thd= current_thd;
if (null_value)
return (String*) 0;
name= day_names[weekday];
name= thd->variables.lc_time_names->day_names->type_names[weekday];
str->set(name, strlen(name), system_charset_info);
return str;
}
@ -1652,7 +1661,7 @@ uint Item_func_date_format::format_length(const String *format)
switch(*++ptr) {
case 'M': /* month, textual */
case 'W': /* day (of the week), textual */
size += 9;
size += 64; /* large for UTF8 locale data */
break;
case 'D': /* day (of the month), numeric plus english suffix */
case 'Y': /* year, numeric, 4 digits */
@ -1662,6 +1671,8 @@ uint Item_func_date_format::format_length(const String *format)
break;
case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
case 'b': /* locale's abbreviated month name (Jan.Dec) */
size += 32; /* large for UTF8 locale data */
break;
case 'j': /* day of year (001..366) */
size += 3;
break;

View file

@ -101,6 +101,23 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
typedef struct my_locale_st
{
const char *name;
const char *description;
const bool is_ascii;
TYPELIB *month_names;
TYPELIB *ab_month_names;
TYPELIB *day_names;
TYPELIB *ab_day_names;
} MY_LOCALE;
extern MY_LOCALE my_locale_en_US;
extern MY_LOCALE *my_locales[];
MY_LOCALE *my_locale_by_name(const char *name);
/***************************************************************************
Configuration parameters
****************************************************************************/
@ -588,6 +605,7 @@ struct Query_cache_query_flags
ulong sql_mode;
ulong max_sort_length;
ulong group_concat_max_len;
MY_LOCALE *lc_time_names;
};
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#include "sql_cache.h"

View file

@ -109,7 +109,6 @@ extern ulong ndb_report_thresh_binlog_mem_usage;
static HASH system_variable_hash;
const char *bool_type_names[]= { "OFF", "ON", NullS };
TYPELIB bool_typelib=
@ -631,6 +630,9 @@ static sys_var_thd_ha_rows sys_select_limit("sql_select_limit",
static sys_var_timestamp sys_timestamp("timestamp");
static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
static sys_var_last_insert_id sys_identity("identity");
static sys_var_thd_lc_time_names sys_lc_time_names("lc_time_names");
static sys_var_insert_id sys_insert_id("insert_id");
static sys_var_readonly sys_error_count("error_count",
OPT_SESSION,
@ -871,6 +873,7 @@ SHOW_VAR init_vars[]= {
{"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
{"large_page_size", (char*) &opt_large_page_size, SHOW_INT},
{"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL},
{sys_lc_time_names.name, (char*) &sys_lc_time_names, SHOW_SYS},
{sys_license.name, (char*) &sys_license, SHOW_SYS},
{sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS},
#ifdef HAVE_MLOCKALL
@ -3011,6 +3014,40 @@ byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
return (byte*) &(max_user_connections);
}
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);
if (locale_match == NULL)
{
my_printf_error(ER_UNKNOWN_ERROR,
"Unknown locale: '%s'", MYF(0), locale_str);
return 1;
}
var->save_result.locale_value= locale_match;
return 0;
}
bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var)
{
thd->variables.lc_time_names= var->save_result.locale_value;
return 0;
}
byte *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
return (byte *)(thd->variables.lc_time_names->name);
}
void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
{
thd->variables.lc_time_names = &my_locale_en_US;
}
/*
Functions to update thd->options bits

View file

@ -28,6 +28,8 @@
class sys_var;
class set_var;
typedef struct system_variables SV;
typedef struct my_locale_st MY_LOCALE;
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
typedef int (*sys_check_func)(THD *, set_var *);
@ -903,6 +905,25 @@ public:
};
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)
{}
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 */
}
bool check_default(enum_var_type type) { return 0; }
bool update(THD *thd, set_var *var);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
virtual void set_default(THD *thd, enum_var_type type);
};
class sys_var_event_scheduler :public sys_var_long_ptr
{
/* We need a derived class only to have a warn_deprecated() */
@ -964,6 +985,7 @@ public:
handlerton *hton;
DATE_TIME_FORMAT *date_time_format;
Time_zone *time_zone;
MY_LOCALE *locale_value;
} save_result;
LEX_STRING base; /* for structs */

View file

@ -814,6 +814,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.time_zone= thd->variables.time_zone;
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.lc_time_names= thd->variables.lc_time_names;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
@ -1049,6 +1050,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.sql_mode= thd->variables.sql_mode;
flags.max_sort_length= thd->variables.max_sort_length;
flags.group_concat_max_len= thd->variables.group_concat_max_len;
flags.lc_time_names= thd->variables.lc_time_names;
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%lx, sort len: %lu, conncat len: %lu",

View file

@ -350,6 +350,7 @@ void THD::init(void)
reset_current_stmt_binlog_row_based();
#endif /*HAVE_ROW_BASED_REPLICATION*/
bzero((char *) &status_var, sizeof(status_var));
variables.lc_time_names = &my_locale_en_US;
}
@ -2040,6 +2041,7 @@ void Security_context::init()
{
host= user= priv_user= ip= 0;
host_or_ip= "connecting host";
priv_host[0]= '\0';
#ifndef NO_EMBEDDED_ACCESS_CHECKS
db_access= NO_ACCESS;
#endif

View file

@ -266,6 +266,9 @@ struct system_variables
CHARSET_INFO *collation_database;
CHARSET_INFO *collation_connection;
/* Locale Support */
MY_LOCALE *lc_time_names;
Time_zone *time_zone;
/* DATE, DATETIME and TIME formats */

View file

@ -428,7 +428,7 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
bool mysql_multi_delete_prepare(THD *thd)
{
LEX *lex= thd->lex;
TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxilliary_table_list.first;
TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first;
TABLE_LIST *target_tbl;
DBUG_ENTER("mysql_multi_delete_prepare");

View file

@ -937,7 +937,7 @@ typedef struct st_lex : public Query_tables_list
List<Name_resolution_context> context_stack;
List<LEX_STRING> db_list;
SQL_LIST proc_list, auxilliary_table_list, save_list;
SQL_LIST proc_list, auxiliary_table_list, save_list;
create_field *last_field;
Item_sum *in_sum_func;
udf_func udf;

1607
sql/sql_locale.cc Normal file

File diff suppressed because it is too large Load diff

View file

@ -1298,6 +1298,12 @@ pthread_handler_t handle_bootstrap(void *arg)
thd->security_ctx->priv_user=
thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
thd->security_ctx->priv_host[0]=0;
/*
Make the "client" handle multiple results. This is necessary
to enable stored procedures with SELECTs and Dynamic SQL
in init-file.
*/
thd->client_capabilities|= CLIENT_MULTI_RESULTS;
buff= (char*) thd->net.buff;
thd->init_for_queries();
@ -3502,7 +3508,7 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
(TABLE_LIST *)thd->lex->auxiliary_table_list.first;
multi_delete *result;
if (!thd->locked_tables &&
@ -6024,7 +6030,7 @@ void mysql_init_multi_delete(LEX *lex)
mysql_init_select(lex);
lex->select_lex.select_limit= 0;
lex->unit.select_limit_cnt= HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list);
lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
@ -7443,7 +7449,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
{
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
(TABLE_LIST *)thd->lex->auxiliary_table_list.first;
TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
DBUG_ENTER("multi_delete_precheck");
@ -7496,7 +7502,7 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
lex->table_count= 0;
for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first;
for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first;
target_tbl; target_tbl= target_tbl->next_local)
{
lex->table_count++;

View file

@ -3321,7 +3321,19 @@ bool mysql_create_table_internal(THD *thd,
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto unlock_and_end;
}
DBUG_ASSERT(get_cached_table_share(db, alias) == 0);
/*
We don't assert here, but check the result, because the table could be
in the table definition cache and in the same time the .frm could be
missing from the disk, in case of manual intervention which deletes
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
Then she could create the table. This case is pretty obscure and
therefore we don't introduce a new error message only for it.
*/
if (get_cached_table_share(db, alias))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto unlock_and_end;
}
}
/*

View file

@ -57,7 +57,7 @@ static char *init_syms(udf_func *tmp, char *nm)
{
char *end;
if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name.str))))
if (!((tmp->func= (Udf_func_any) dlsym(tmp->dlhandle, tmp->name.str))))
return tmp->name.str;
end=strmov(nm,tmp->name.str);
@ -65,18 +65,18 @@ static char *init_syms(udf_func *tmp, char *nm)
if (tmp->type == UDFTYPE_AGGREGATE)
{
(void)strmov(end, "_clear");
if (!((tmp->func_clear= dlsym(tmp->dlhandle, nm))))
if (!((tmp->func_clear= (Udf_func_clear) dlsym(tmp->dlhandle, nm))))
return nm;
(void)strmov(end, "_add");
if (!((tmp->func_add= dlsym(tmp->dlhandle, nm))))
if (!((tmp->func_add= (Udf_func_add) dlsym(tmp->dlhandle, nm))))
return nm;
}
(void) strmov(end,"_deinit");
tmp->func_deinit= dlsym(tmp->dlhandle, nm);
tmp->func_deinit= (Udf_func_deinit) dlsym(tmp->dlhandle, nm);
(void) strmov(end,"_init");
tmp->func_init= dlsym(tmp->dlhandle, nm);
tmp->func_init= (Udf_func_init) dlsym(tmp->dlhandle, nm);
/*
to prefent loading "udf" from, e.g. libc.so

View file

@ -23,6 +23,15 @@
enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE};
typedef void (*Udf_func_clear)(UDF_INIT *, uchar *, uchar *);
typedef void (*Udf_func_add)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *);
typedef void (*Udf_func_deinit)(UDF_INIT*);
typedef my_bool (*Udf_func_init)(UDF_INIT *, UDF_ARGS *, char *);
typedef void (*Udf_func_any)();
typedef double (*Udf_func_double)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *);
typedef longlong (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, uchar *,
uchar *);
typedef struct st_udf_func
{
LEX_STRING name;
@ -30,11 +39,11 @@ typedef struct st_udf_func
Item_udftype type;
char *dl;
void *dlhandle;
void *func;
void *func_init;
void *func_deinit;
void *func_clear;
void *func_add;
Udf_func_any func;
Udf_func_init func_init;
Udf_func_deinit func_deinit;
Udf_func_clear func_clear;
Udf_func_add func_add;
ulong usage_count;
} udf_func;
@ -76,8 +85,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return 0.0;
}
double (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
(double (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
Udf_func_double func= (Udf_func_double) u_d->func;
double tmp=func(&initid, &f_args, &is_null, &error);
if (is_null || error)
{
@ -95,8 +103,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return LL(0);
}
longlong (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
(longlong (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func;
Udf_func_longlong func= (Udf_func_longlong) u_d->func;
longlong tmp=func(&initid, &f_args, &is_null, &error);
if (is_null || error)
{
@ -110,8 +117,7 @@ class udf_handler :public Sql_alloc
void clear()
{
is_null= 0;
void (*func)(UDF_INIT *, uchar *, uchar *)=
(void (*)(UDF_INIT *, uchar *, uchar *)) u_d->func_clear;
Udf_func_clear func= u_d->func_clear;
func(&initid, &is_null, &error);
}
void add(my_bool *null_value)
@ -121,8 +127,7 @@ class udf_handler :public Sql_alloc
*null_value=1;
return;
}
void (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)=
(void (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func_add;
Udf_func_add func= u_d->func_add;
func(&initid, &f_args, &is_null, &error);
*null_value= (my_bool) (is_null || error);
}

View file

@ -459,7 +459,7 @@ int mysql_update(THD *thd,
can_compare_record= (!(table->file->ha_table_flags() &
HA_PARTIAL_COLUMN_READ) ||
bitmap_is_subset(table->write_set, table->read_set));
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (!(select && select->skip_record()))

View file

@ -6159,7 +6159,10 @@ simple_expr:
Lex->safe_to_cache_query=0;
}
| CURRENT_USER optional_braces
{ $$= create_func_current_user(); }
{
$$= new Item_func_current_user(Lex->current_context());
Lex->safe_to_cache_query= 0;
}
| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
{ $$= new Item_date_add_interval($3,$5,$6,0); }
| DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
@ -6518,7 +6521,7 @@ simple_expr:
| UNIX_TIMESTAMP '(' expr ')'
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
{ $$= new Item_func_user(FALSE); Lex->safe_to_cache_query=0; }
{ $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
| UTC_DATE_SYM optional_braces
{ $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
| UTC_TIME_SYM optional_braces

View file

@ -574,9 +574,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
char *iext= strrchr(ci->index_file_name, '.');
int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
MY_UNPACK_FILENAME| (have_iext ? MY_REPLACE_EXT :MY_APPEND_EXT));
if (options & HA_OPTION_TMP_TABLE)
{
char *path;
/* chop off the table name, tempory tables use generated name */
if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
*path= '\0';
fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
}
else
{
fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
MY_UNPACK_FILENAME | (have_iext ? MY_REPLACE_EXT :
MY_APPEND_EXT));
}
fn_format(linkname, name, "", MI_NAME_IEXT,
MY_UNPACK_FILENAME|MY_APPEND_EXT);
linkname_ptr=linkname;
@ -639,9 +651,22 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
char *dext= strrchr(ci->data_file_name, '.');
int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
MY_UNPACK_FILENAME |
(have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
if (options & HA_OPTION_TMP_TABLE)
{
char *path;
/* chop off the table name, tempory tables use generated name */
if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
*path= '\0';
fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
}
else
{
fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
MY_UNPACK_FILENAME |
(have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
}
fn_format(linkname, name, "",MI_NAME_DEXT,
MY_UNPACK_FILENAME | MY_APPEND_EXT);
linkname_ptr=linkname;