Merge ramayana.hindu.god:/home/tsmith/m/bk/50
into ramayana.hindu.god:/home/tsmith/m/bk/maint/50
This commit is contained in:
commit
c54e1855dc
@ -72,10 +72,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
|
||||||
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
|
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
|
||||||
info->lastkey_len= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
custom_arg.keyseg= keyinfo->seg;
|
custom_arg.keyseg= keyinfo->seg;
|
||||||
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||||
|
@ -35,6 +35,17 @@ int heap_rfirst(HP_INFO *info, byte *record, int inx)
|
|||||||
sizeof(byte*));
|
sizeof(byte*));
|
||||||
info->current_ptr = pos;
|
info->current_ptr = pos;
|
||||||
memcpy(record, pos, (size_t)share->reclength);
|
memcpy(record, pos, (size_t)share->reclength);
|
||||||
|
/*
|
||||||
|
If we're performing index_first on a table that was taken from
|
||||||
|
table cache, info->lastkey_len is initialized to previous query.
|
||||||
|
Thus we set info->lastkey_len to proper value for subsequent
|
||||||
|
heap_rnext() calls.
|
||||||
|
This is needed for DELETE queries only, otherwise this variable is
|
||||||
|
not used.
|
||||||
|
Note that the same workaround may be needed for heap_rlast(), but
|
||||||
|
for now heap_rlast() is never used for DELETE queries.
|
||||||
|
*/
|
||||||
|
info->lastkey_len= 0;
|
||||||
info->update = HA_STATE_AKTIV;
|
info->update = HA_STATE_AKTIV;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -33,11 +33,40 @@ int heap_rnext(HP_INFO *info, byte *record)
|
|||||||
heap_rb_param custom_arg;
|
heap_rb_param custom_arg;
|
||||||
|
|
||||||
if (info->last_pos)
|
if (info->last_pos)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We enter this branch for non-DELETE queries after heap_rkey()
|
||||||
|
or heap_rfirst(). As last key position (info->last_pos) is available,
|
||||||
|
we only need to climb the tree using tree_search_next().
|
||||||
|
*/
|
||||||
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
||||||
offsetof(TREE_ELEMENT, left),
|
offsetof(TREE_ELEMENT, left),
|
||||||
offsetof(TREE_ELEMENT, right));
|
offsetof(TREE_ELEMENT, right));
|
||||||
|
}
|
||||||
|
else if (!info->lastkey_len)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We enter this branch only for DELETE queries after heap_rfirst(). E.g.
|
||||||
|
DELETE FROM t1 WHERE a<10. As last key position is not available
|
||||||
|
(last key is removed by heap_delete()), we must restart search as it
|
||||||
|
is done in heap_rfirst().
|
||||||
|
|
||||||
|
It should be safe to handle this situation without this branch. That is
|
||||||
|
branch below should find smallest element in a tree as lastkey_len is
|
||||||
|
zero. tree_search_edge() is a kind of optimisation here as it should be
|
||||||
|
faster than tree_search_key().
|
||||||
|
*/
|
||||||
|
pos= tree_search_edge(&keyinfo->rb_tree, info->parents,
|
||||||
|
&info->last_pos, offsetof(TREE_ELEMENT, left));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
We enter this branch only for DELETE queries after heap_rkey(). E.g.
|
||||||
|
DELETE FROM t1 WHERE a=10. As last key position is not available
|
||||||
|
(last key is removed by heap_delete()), we must restart search as it
|
||||||
|
is done in heap_rkey().
|
||||||
|
*/
|
||||||
custom_arg.keyseg = keyinfo->seg;
|
custom_arg.keyseg = keyinfo->seg;
|
||||||
custom_arg.key_length = info->lastkey_len;
|
custom_arg.key_length = info->lastkey_len;
|
||||||
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
|
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
/* We have to do this define before including windows.h to get the AWE API
|
/* We have to do this define before including windows.h to get the AWE API
|
||||||
functions */
|
functions */
|
||||||
#define _WIN32_WINNT 0x0500
|
#define _WIN32_WINNT 0x0500
|
||||||
|
#else
|
||||||
|
/* Get NT 4.0 functions */
|
||||||
|
#define _WIN32_WINNT 0x0400
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
@ -116,6 +116,7 @@ struct timespec {
|
|||||||
|
|
||||||
void win_pthread_init(void);
|
void win_pthread_init(void);
|
||||||
int win_pthread_setspecific(void *A,void *B,uint length);
|
int win_pthread_setspecific(void *A,void *B,uint length);
|
||||||
|
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||||
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
|
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
|
||||||
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
|
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
|
||||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
||||||
@ -176,7 +177,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *);
|
|||||||
#else
|
#else
|
||||||
#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
|
#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
|
||||||
#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
|
#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
|
||||||
#define pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT)
|
#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A))
|
||||||
#define pthread_mutex_unlock(A) LeaveCriticalSection(A)
|
#define pthread_mutex_unlock(A) LeaveCriticalSection(A)
|
||||||
#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
|
#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
|
||||||
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
|
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
|
||||||
@ -574,7 +575,7 @@ typedef struct st_safe_mutex_info_t
|
|||||||
|
|
||||||
int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
|
int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
|
||||||
const char *file, uint line);
|
const char *file, uint line);
|
||||||
int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line);
|
int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line);
|
||||||
int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
|
int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
|
||||||
int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
|
int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
|
||||||
int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
|
int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
|
||||||
@ -597,12 +598,12 @@ void safe_mutex_end(FILE *file);
|
|||||||
#undef pthread_cond_timedwait
|
#undef pthread_cond_timedwait
|
||||||
#undef pthread_mutex_trylock
|
#undef pthread_mutex_trylock
|
||||||
#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__)
|
#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__)
|
||||||
#define pthread_mutex_lock(A) safe_mutex_lock((A),__FILE__,__LINE__)
|
#define pthread_mutex_lock(A) safe_mutex_lock((A), FALSE, __FILE__, __LINE__)
|
||||||
#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
|
#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
|
||||||
#define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__)
|
#define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__)
|
||||||
#define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__)
|
#define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__)
|
||||||
#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
|
#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
|
||||||
#define pthread_mutex_trylock(A) pthread_mutex_lock(A)
|
#define pthread_mutex_trylock(A) safe_mutex_lock((A), TRUE, __FILE__, __LINE__)
|
||||||
#define pthread_mutex_t safe_mutex_t
|
#define pthread_mutex_t safe_mutex_t
|
||||||
#define safe_mutex_assert_owner(mp) \
|
#define safe_mutex_assert_owner(mp) \
|
||||||
DBUG_ASSERT((mp)->count > 0 && \
|
DBUG_ASSERT((mp)->count > 0 && \
|
||||||
|
@ -307,6 +307,13 @@ UNIQUE USING BTREE(c1)
|
|||||||
) ENGINE= MEMORY DEFAULT CHARSET= utf8;
|
) ENGINE= MEMORY DEFAULT CHARSET= utf8;
|
||||||
INSERT INTO t1 VALUES('1'), ('2');
|
INSERT INTO t1 VALUES('1'), ('2');
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY;
|
||||||
|
INSERT INTO t1 VALUES(1),(2),(2);
|
||||||
|
DELETE FROM t1 WHERE a=2;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
End of 4.1 tests
|
End of 4.1 tests
|
||||||
CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
|
CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
|
||||||
INSERT INTO t1 VALUES(0);
|
INSERT INTO t1 VALUES(0);
|
||||||
|
@ -876,4 +876,9 @@ CHECK TABLE tm1;
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.tm1 check status OK
|
test.tm1 check status OK
|
||||||
DROP TABLE tm1, t1, t2;
|
DROP TABLE tm1, t1, t2;
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
CREATE TABLE t2 (c1 INT) ENGINE=MERGE UNION=(t1) INSERT_METHOD=FIRST;
|
||||||
|
CREATE TABLE IF NOT EXISTS t1 SELECT * FROM t2;
|
||||||
|
ERROR HY000: You can't specify target table 't1' for update in FROM clause
|
||||||
|
DROP TABLE t1, t2;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -1211,7 +1211,7 @@ ERROR 42S02: Unknown table 'c' in field list
|
|||||||
drop procedure bug15091;
|
drop procedure bug15091;
|
||||||
drop function if exists bug16896;
|
drop function if exists bug16896;
|
||||||
create aggregate function bug16896() returns int return 1;
|
create aggregate function bug16896() returns int return 1;
|
||||||
ERROR 42000: AGGREGATE is not supported for stored functions
|
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 '() returns int return 1' at line 1
|
||||||
DROP PROCEDURE IF EXISTS bug14702;
|
DROP PROCEDURE IF EXISTS bug14702;
|
||||||
CREATE IF NOT EXISTS PROCEDURE bug14702()
|
CREATE IF NOT EXISTS PROCEDURE bug14702()
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -1452,3 +1452,16 @@ end
|
|||||||
until true end repeat retry;
|
until true end repeat retry;
|
||||||
end//
|
end//
|
||||||
ERROR 42000: LEAVE with no matching label: retry
|
ERROR 42000: LEAVE with no matching label: retry
|
||||||
|
DROP DATABASE IF EXISTS mysqltest;
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
USE mysqltest;
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
SELECT inexistent(), 1 + ,;
|
||||||
|
ERROR 42000: FUNCTION inexistent does not exist
|
||||||
|
SELECT inexistent();
|
||||||
|
ERROR 42000: FUNCTION inexistent does not exist
|
||||||
|
SELECT .inexistent();
|
||||||
|
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 '()' at line 1
|
||||||
|
SELECT ..inexistent();
|
||||||
|
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 '.inexistent()' at line 1
|
||||||
|
USE test;
|
||||||
|
@ -5667,7 +5667,6 @@ t3_id_1 t3_id_2 t4_id
|
|||||||
DROP PROCEDURE p1|
|
DROP PROCEDURE p1|
|
||||||
DROP VIEW v1, v2|
|
DROP VIEW v1, v2|
|
||||||
DROP TABLE t3, t4|
|
DROP TABLE t3, t4|
|
||||||
End of 5.0 tests
|
|
||||||
DROP TABLE IF EXISTS bug23760|
|
DROP TABLE IF EXISTS bug23760|
|
||||||
DROP TABLE IF EXISTS bug23760_log|
|
DROP TABLE IF EXISTS bug23760_log|
|
||||||
DROP PROCEDURE IF EXISTS bug23760_update_log|
|
DROP PROCEDURE IF EXISTS bug23760_update_log|
|
||||||
@ -6145,7 +6144,6 @@ Procedure sql_mode Create Procedure
|
|||||||
proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`()
|
proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`()
|
||||||
`my_label`:BEGIN END
|
`my_label`:BEGIN END
|
||||||
drop procedure proc_21513|
|
drop procedure proc_21513|
|
||||||
End of 5.0 tests.
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
|
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
|
||||||
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
|
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
|
||||||
@ -6389,4 +6387,197 @@ DROP TABLE t1;
|
|||||||
|
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP PROCEDURE p2;
|
DROP PROCEDURE p2;
|
||||||
End of 5.0 tests
|
|
||||||
|
#
|
||||||
|
# Bug#31035.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Prepare.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
DROP FUNCTION IF EXISTS f2;
|
||||||
|
DROP FUNCTION IF EXISTS f3;
|
||||||
|
DROP FUNCTION IF EXISTS f4;
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Create required objects.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1), (2), (3);
|
||||||
|
|
||||||
|
CREATE FUNCTION f1()
|
||||||
|
RETURNS INT
|
||||||
|
NOT DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
CREATE FUNCTION f2(p INT)
|
||||||
|
RETURNS INT
|
||||||
|
NOT DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
CREATE FUNCTION f3()
|
||||||
|
RETURNS INT
|
||||||
|
DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
CREATE FUNCTION f4(p INT)
|
||||||
|
RETURNS INT
|
||||||
|
DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Check.
|
||||||
|
#
|
||||||
|
|
||||||
|
SELECT f1() AS a FROM t1 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
|
||||||
|
SELECT f2(@a) AS a FROM t1 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
|
||||||
|
SELECT f3() AS a FROM t1 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
|
||||||
|
SELECT f4(0) AS a FROM t1 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
|
||||||
|
SELECT f4(@a) AS a FROM t1 GROUP BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Cleanup.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
DROP FUNCTION f2;
|
||||||
|
DROP FUNCTION f3;
|
||||||
|
DROP FUNCTION f4;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#31191.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Prepare.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Create required objects.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
barcode INT(8) UNSIGNED ZEROFILL nOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY barcode (barcode)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1 (id, barcode) VALUES (1, 12345678);
|
||||||
|
INSERT INTO t1 (id, barcode) VALUES (2, 12345679);
|
||||||
|
|
||||||
|
CREATE TABLE test.t2 (
|
||||||
|
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
barcode BIGINT(11) UNSIGNED ZEROFILL NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO test.t2 (id, barcode) VALUES (1, 12345106708);
|
||||||
|
INSERT INTO test.t2 (id, barcode) VALUES (2, 12345106709);
|
||||||
|
|
||||||
|
CREATE FUNCTION f1(p INT(8))
|
||||||
|
RETURNS BIGINT(11) UNSIGNED
|
||||||
|
READS SQL DATA
|
||||||
|
RETURN FLOOR(p/1000)*1000000 + 100000 + FLOOR((p MOD 1000)/10)*100 + (p MOD 10);
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Check.
|
||||||
|
#
|
||||||
|
|
||||||
|
SELECT DISTINCT t1.barcode, f1(t1.barcode)
|
||||||
|
FROM t1
|
||||||
|
INNER JOIN t2
|
||||||
|
ON f1(t1.barcode) = t2.barcode
|
||||||
|
WHERE t1.barcode=12345678;
|
||||||
|
barcode f1(t1.barcode)
|
||||||
|
12345678 12345106708
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Cleanup.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#31226.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Prepare.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Create required objects.
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1(id INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1), (2), (3);
|
||||||
|
|
||||||
|
CREATE FUNCTION f1()
|
||||||
|
RETURNS DATETIME
|
||||||
|
NOT DETERMINISTIC NO SQL
|
||||||
|
RETURN NOW();
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Check.
|
||||||
|
#
|
||||||
|
|
||||||
|
SELECT f1() FROM t1 GROUP BY 1;
|
||||||
|
f1()
|
||||||
|
<timestamp>
|
||||||
|
|
||||||
|
#
|
||||||
|
# - Cleanup.
|
||||||
|
#
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS db28318_a.t1;
|
||||||
|
DROP PROCEDURE IF EXISTS db28318_b.t2;
|
||||||
|
DROP DATABASE IF EXISTS db28318_a;
|
||||||
|
DROP DATABASE IF EXISTS db28318_b;
|
||||||
|
CREATE DATABASE db28318_a;
|
||||||
|
CREATE DATABASE db28318_b;
|
||||||
|
CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1";
|
||||||
|
CREATE PROCEDURE db28318_b.t2() CALL t1();
|
||||||
|
use db28318_a;
|
||||||
|
CALL db28318_b.t2();
|
||||||
|
ERROR 42000: PROCEDURE db28318_b.t1 does not exist
|
||||||
|
DROP PROCEDURE db28318_a.t1;
|
||||||
|
DROP PROCEDURE db28318_b.t2;
|
||||||
|
DROP DATABASE db28318_a;
|
||||||
|
DROP DATABASE db28318_b;
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# -- End of 5.0 tests
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
@ -95,10 +95,10 @@ FR
|
|||||||
DROP TABLE bug19904;
|
DROP TABLE bug19904;
|
||||||
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
|
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
|
||||||
RETURNS STRING SONAME "should_not_parse.so";
|
RETURNS STRING SONAME "should_not_parse.so";
|
||||||
ERROR HY000: Incorrect usage of SONAME and DEFINER
|
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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2
|
||||||
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
|
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
|
||||||
RETURNS STRING SONAME "should_not_parse.so";
|
RETURNS STRING SONAME "should_not_parse.so";
|
||||||
ERROR HY000: Incorrect usage of SONAME and DEFINER
|
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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2
|
||||||
create table t1(f1 int);
|
create table t1(f1 int);
|
||||||
insert into t1 values(1),(2);
|
insert into t1 values(1),(2);
|
||||||
explain select myfunc_int(f1) from t1 order by 1;
|
explain select myfunc_int(f1) from t1 order by 1;
|
||||||
@ -296,6 +296,13 @@ Qcache_queries_in_cache 0
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
drop function metaphon;
|
drop function metaphon;
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
DROP DATABASE IF EXISTS mysqltest;
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
USE mysqltest;
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
|
||||||
|
DROP FUNCTION metaphon;
|
||||||
|
USE test;
|
||||||
CREATE TABLE const_len_bug (
|
CREATE TABLE const_len_bug (
|
||||||
str_const varchar(4000),
|
str_const varchar(4000),
|
||||||
result1 varchar(4000),
|
result1 varchar(4000),
|
||||||
|
@ -213,6 +213,15 @@ CREATE TABLE t1 (
|
|||||||
INSERT INTO t1 VALUES('1'), ('2');
|
INSERT INTO t1 VALUES('1'), ('2');
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#30590 - delete from memory table with composite btree primary key
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY;
|
||||||
|
INSERT INTO t1 VALUES(1),(2),(2);
|
||||||
|
DELETE FROM t1 WHERE a=2;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo End of 4.1 tests
|
--echo End of 4.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -507,4 +507,18 @@ SELECT * FROM tm1;
|
|||||||
CHECK TABLE tm1;
|
CHECK TABLE tm1;
|
||||||
DROP TABLE tm1, t1, t2;
|
DROP TABLE tm1, t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#15522 - create ... select and with merge tables
|
||||||
|
#
|
||||||
|
# This was fixed together with Bug#20662 (Infinite loop in CREATE TABLE
|
||||||
|
# IF NOT EXISTS ... SELECT with locked tables).
|
||||||
|
# The new behavior for MERGE tables is consistent with the
|
||||||
|
# CREATE TABLE SELECT behavior for ordinary tables.
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
CREATE TABLE t2 (c1 INT) ENGINE=MERGE UNION=(t1) INSERT_METHOD=FIRST;
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
CREATE TABLE IF NOT EXISTS t1 SELECT * FROM t2;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
@ -1744,7 +1744,7 @@ drop procedure bug15091;
|
|||||||
drop function if exists bug16896;
|
drop function if exists bug16896;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
--error ER_SP_NO_AGGREGATE
|
--error ER_PARSE_ERROR
|
||||||
create aggregate function bug16896() returns int return 1;
|
create aggregate function bug16896() returns int return 1;
|
||||||
|
|
||||||
|
|
||||||
@ -2089,6 +2089,29 @@ end//
|
|||||||
|
|
||||||
delimiter ;//
|
delimiter ;//
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#29816 Syntactically wrong query fails with misleading error message
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS mysqltest;
|
||||||
|
--enable_warnings
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
USE mysqltest;
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
# Both ER_SP_DOES_NOT_EXIST and ER_PARSE_ERROR are valid here,
|
||||||
|
# the result is implementation dependent:
|
||||||
|
# See Bug#29816 for details
|
||||||
|
--error ER_SP_DOES_NOT_EXIST
|
||||||
|
SELECT inexistent(), 1 + ,;
|
||||||
|
--error ER_SP_DOES_NOT_EXIST
|
||||||
|
SELECT inexistent();
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
SELECT .inexistent();
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
SELECT ..inexistent();
|
||||||
|
USE test;
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
|
@ -6642,9 +6642,6 @@ DROP VIEW v1, v2|
|
|||||||
DROP TABLE t3, t4|
|
DROP TABLE t3, t4|
|
||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#23760: ROW_COUNT() and store procedure not owrking together
|
# BUG#23760: ROW_COUNT() and store procedure not owrking together
|
||||||
#
|
#
|
||||||
@ -7076,9 +7073,6 @@ show create procedure proc_21513|
|
|||||||
|
|
||||||
drop procedure proc_21513|
|
drop procedure proc_21513|
|
||||||
|
|
||||||
###
|
|
||||||
--echo End of 5.0 tests.
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
#
|
#
|
||||||
@ -7387,4 +7381,325 @@ DROP TABLE t1;
|
|||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP PROCEDURE p2;
|
DROP PROCEDURE p2;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
###########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#31035: select from function, group by result crasher.
|
||||||
|
#
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#31035.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Prepare.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
DROP FUNCTION IF EXISTS f2;
|
||||||
|
DROP FUNCTION IF EXISTS f3;
|
||||||
|
DROP FUNCTION IF EXISTS f4;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Create required objects.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE TABLE t1(c1 INT);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1), (2), (3);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f1()
|
||||||
|
RETURNS INT
|
||||||
|
NOT DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f2(p INT)
|
||||||
|
RETURNS INT
|
||||||
|
NOT DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f3()
|
||||||
|
RETURNS INT
|
||||||
|
DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f4(p INT)
|
||||||
|
RETURNS INT
|
||||||
|
DETERMINISTIC
|
||||||
|
RETURN 1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Check.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
# Not deterministic function, no arguments.
|
||||||
|
|
||||||
|
SELECT f1() AS a FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
# Not deterministic function, non-constant argument.
|
||||||
|
|
||||||
|
SELECT f2(@a) AS a FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
# Deterministic function, no arguments.
|
||||||
|
|
||||||
|
SELECT f3() AS a FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
# Deterministic function, constant argument.
|
||||||
|
|
||||||
|
SELECT f4(0) AS a FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
# Deterministic function, non-constant argument.
|
||||||
|
|
||||||
|
SELECT f4(@a) AS a FROM t1 GROUP BY a;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Cleanup.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
DROP FUNCTION f2;
|
||||||
|
DROP FUNCTION f3;
|
||||||
|
DROP FUNCTION f4;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#31191: JOIN in combination with stored function crashes the server.
|
||||||
|
#
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#31191.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Prepare.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Create required objects.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
barcode INT(8) UNSIGNED ZEROFILL nOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY barcode (barcode)
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
INSERT INTO t1 (id, barcode) VALUES (1, 12345678);
|
||||||
|
INSERT INTO t1 (id, barcode) VALUES (2, 12345679);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE TABLE test.t2 (
|
||||||
|
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
barcode BIGINT(11) UNSIGNED ZEROFILL NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
INSERT INTO test.t2 (id, barcode) VALUES (1, 12345106708);
|
||||||
|
INSERT INTO test.t2 (id, barcode) VALUES (2, 12345106709);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f1(p INT(8))
|
||||||
|
RETURNS BIGINT(11) UNSIGNED
|
||||||
|
READS SQL DATA
|
||||||
|
RETURN FLOOR(p/1000)*1000000 + 100000 + FLOOR((p MOD 1000)/10)*100 + (p MOD 10);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Check.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
SELECT DISTINCT t1.barcode, f1(t1.barcode)
|
||||||
|
FROM t1
|
||||||
|
INNER JOIN t2
|
||||||
|
ON f1(t1.barcode) = t2.barcode
|
||||||
|
WHERE t1.barcode=12345678;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Cleanup.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#31226: Group by function crashes mysql.
|
||||||
|
#
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#31226.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Prepare.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP FUNCTION IF EXISTS f1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Create required objects.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE TABLE t1(id INT);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1), (2), (3);
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
CREATE FUNCTION f1()
|
||||||
|
RETURNS DATETIME
|
||||||
|
NOT DETERMINISTIC NO SQL
|
||||||
|
RETURN NOW();
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Check.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--replace_column 1 <timestamp>
|
||||||
|
SELECT f1() FROM t1 GROUP BY 1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # - Cleanup.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
--echo
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28318 (CREATE FUNCTION (UDF) requires a schema)
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP PROCEDURE IF EXISTS db28318_a.t1;
|
||||||
|
DROP PROCEDURE IF EXISTS db28318_b.t2;
|
||||||
|
DROP DATABASE IF EXISTS db28318_a;
|
||||||
|
DROP DATABASE IF EXISTS db28318_b;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE DATABASE db28318_a;
|
||||||
|
CREATE DATABASE db28318_b;
|
||||||
|
|
||||||
|
CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1";
|
||||||
|
CREATE PROCEDURE db28318_b.t2() CALL t1();
|
||||||
|
|
||||||
|
use db28318_a;
|
||||||
|
|
||||||
|
# In db28318_b.t2, t1 refers to db28318_b.t1
|
||||||
|
--error ER_SP_DOES_NOT_EXIST
|
||||||
|
CALL db28318_b.t2();
|
||||||
|
|
||||||
|
DROP PROCEDURE db28318_a.t1;
|
||||||
|
DROP PROCEDURE db28318_b.t2;
|
||||||
|
DROP DATABASE db28318_a;
|
||||||
|
DROP DATABASE db28318_b;
|
||||||
|
|
||||||
|
|
||||||
|
--echo # ------------------------------------------------------------------
|
||||||
|
--echo # -- End of 5.0 tests
|
||||||
|
--echo # ------------------------------------------------------------------
|
||||||
|
@ -113,11 +113,11 @@ DROP TABLE bug19904;
|
|||||||
# Bug#21269: DEFINER-clause is allowed for UDF-functions
|
# Bug#21269: DEFINER-clause is allowed for UDF-functions
|
||||||
#
|
#
|
||||||
|
|
||||||
--error ER_WRONG_USAGE
|
--error ER_PARSE_ERROR
|
||||||
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
|
CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse
|
||||||
RETURNS STRING SONAME "should_not_parse.so";
|
RETURNS STRING SONAME "should_not_parse.so";
|
||||||
|
|
||||||
--error ER_WRONG_USAGE
|
--error ER_PARSE_ERROR
|
||||||
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
|
CREATE DEFINER=someone@somewhere FUNCTION should_not_parse
|
||||||
RETURNS STRING SONAME "should_not_parse.so";
|
RETURNS STRING SONAME "should_not_parse.so";
|
||||||
#
|
#
|
||||||
@ -311,6 +311,20 @@ drop table t1;
|
|||||||
drop function metaphon;
|
drop function metaphon;
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28318 CREATE FUNCTION (UDF) requires a schema
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS mysqltest;
|
||||||
|
--enable_warnings
|
||||||
|
CREATE DATABASE mysqltest;
|
||||||
|
USE mysqltest;
|
||||||
|
DROP DATABASE mysqltest;
|
||||||
|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
|
||||||
|
eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
|
||||||
|
DROP FUNCTION metaphon;
|
||||||
|
USE test;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug #29804 UDF parameters don't contain correct string length
|
# Bug #29804 UDF parameters don't contain correct string length
|
||||||
|
@ -40,6 +40,29 @@ void win_pthread_init(void)
|
|||||||
pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adapter to @c pthread_mutex_trylock()
|
||||||
|
|
||||||
|
@retval 0 Mutex was acquired
|
||||||
|
@retval EBUSY Mutex was already locked by a thread
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
win_pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
if (TryEnterCriticalSection(mutex))
|
||||||
|
{
|
||||||
|
/* Don't allow recursive lock */
|
||||||
|
if (mutex->RecursionCount > 1){
|
||||||
|
LeaveCriticalSection(mutex);
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** We have tried to use '_beginthreadex' instead of '_beginthread' here
|
** We have tried to use '_beginthreadex' instead of '_beginthread' here
|
||||||
** but in this case the program leaks about 512 characters for each
|
** but in this case the program leaks about 512 characters for each
|
||||||
|
@ -91,7 +91,7 @@ int safe_mutex_init(safe_mutex_t *mp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
|
int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
if (!mp->file)
|
if (!mp->file)
|
||||||
@ -104,15 +104,50 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&mp->global);
|
pthread_mutex_lock(&mp->global);
|
||||||
if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread))
|
if (mp->count > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"safe_mutex: Trying to lock mutex at %s, line %d, when the mutex was already locked at %s, line %d in thread %s\n",
|
if (try_lock)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&mp->global);
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
else if (pthread_equal(pthread_self(),mp->thread))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"safe_mutex: Trying to lock mutex at %s, line %d, when the"
|
||||||
|
" mutex was already locked at %s, line %d in thread %s\n",
|
||||||
file,line,mp->file, mp->line, my_thread_name());
|
file,line,mp->file, mp->line, my_thread_name());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&mp->global);
|
pthread_mutex_unlock(&mp->global);
|
||||||
error=pthread_mutex_lock(&mp->mutex);
|
|
||||||
|
/*
|
||||||
|
If we are imitating trylock(), we need to take special
|
||||||
|
precautions.
|
||||||
|
|
||||||
|
- We cannot use pthread_mutex_lock() only since another thread can
|
||||||
|
overtake this thread and take the lock before this thread
|
||||||
|
causing pthread_mutex_trylock() to hang. In this case, we should
|
||||||
|
just return EBUSY. Hence, we use pthread_mutex_trylock() to be
|
||||||
|
able to return immediately.
|
||||||
|
|
||||||
|
- We cannot just use trylock() and continue execution below, since
|
||||||
|
this would generate an error and abort execution if the thread
|
||||||
|
was overtaken and trylock() returned EBUSY . In this case, we
|
||||||
|
instead just return EBUSY, since this is the expected behaviour
|
||||||
|
of trylock().
|
||||||
|
*/
|
||||||
|
if (try_lock)
|
||||||
|
{
|
||||||
|
error= pthread_mutex_trylock(&mp->mutex);
|
||||||
|
if (error == EBUSY)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error= pthread_mutex_lock(&mp->mutex);
|
||||||
|
|
||||||
if (error || (error=pthread_mutex_lock(&mp->global)))
|
if (error || (error=pthread_mutex_lock(&mp->global)))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n",
|
fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n",
|
||||||
|
@ -4364,12 +4364,14 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
|
|||||||
return new Field_blob(max_length, maybe_null, name, table,
|
return new Field_blob(max_length, maybe_null, name, table,
|
||||||
collation.collation);
|
collation.collation);
|
||||||
break; // Blob handled outside of case
|
break; // Blob handled outside of case
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
case MYSQL_TYPE_GEOMETRY:
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
return new Field_geom(max_length, maybe_null, name, table,
|
return new Field_geom(max_length, maybe_null, name, table,
|
||||||
(Field::geometry_type)
|
(Field::geometry_type)
|
||||||
((type() == Item::TYPE_HOLDER) ?
|
((type() == Item::TYPE_HOLDER) ?
|
||||||
((Item_type_holder *)this)->get_geometry_type() :
|
((Item_type_holder *)this)->get_geometry_type() :
|
||||||
((Item_geometry_func *)this)->get_geometry_type()));
|
((Item_geometry_func *)this)->get_geometry_type()));
|
||||||
|
#endif /* HAVE_SPATIAL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6489,10 +6491,12 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
|||||||
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
if (Field::result_merge_type(fld_type) == INT_RESULT)
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
prev_decimal_int_part= item->decimal_int_part();
|
prev_decimal_int_part= item->decimal_int_part();
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
if (item->field_type() == MYSQL_TYPE_GEOMETRY)
|
if (item->field_type() == MYSQL_TYPE_GEOMETRY)
|
||||||
geometry_type= (item->type() == Item::FIELD_ITEM) ?
|
geometry_type= (item->type() == Item::FIELD_ITEM) ?
|
||||||
((Item_field *)item)->get_geometry_type() :
|
((Item_field *)item)->get_geometry_type() :
|
||||||
(Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type();
|
(Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type();
|
||||||
|
#endif /* HAVE_SPATIAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5584,8 +5584,13 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
|||||||
|
|
||||||
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_sp->m_chistics->detistic)
|
if (!m_sp->m_chistics->detistic)
|
||||||
|
{
|
||||||
used_tables_cache |= RAND_TABLE_BIT;
|
used_tables_cache |= RAND_TABLE_BIT;
|
||||||
|
const_item_cache= FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5593,6 +5598,10 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
|||||||
void Item_func_sp::update_used_tables()
|
void Item_func_sp::update_used_tables()
|
||||||
{
|
{
|
||||||
Item_func::update_used_tables();
|
Item_func::update_used_tables();
|
||||||
|
|
||||||
if (!m_sp->m_chistics->detistic)
|
if (!m_sp->m_chistics->detistic)
|
||||||
|
{
|
||||||
used_tables_cache |= RAND_TABLE_BIT;
|
used_tables_cache |= RAND_TABLE_BIT;
|
||||||
|
const_item_cache= FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,7 +731,6 @@ pthread_handler_t handle_bootstrap(void *arg);
|
|||||||
void end_thread(THD *thd,bool put_in_cache);
|
void end_thread(THD *thd,bool put_in_cache);
|
||||||
void flush_thread_cache();
|
void flush_thread_cache();
|
||||||
bool mysql_execute_command(THD *thd);
|
bool mysql_execute_command(THD *thd);
|
||||||
bool do_command(THD *thd);
|
|
||||||
bool dispatch_command(enum enum_server_command command, THD *thd,
|
bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||||
char* packet, uint packet_length);
|
char* packet, uint packet_length);
|
||||||
void log_slow_statement(THD *thd);
|
void log_slow_statement(THD *thd);
|
||||||
|
@ -784,7 +784,6 @@ sys_var *sys_variables[]=
|
|||||||
&sys_innodb_max_purge_lag,
|
&sys_innodb_max_purge_lag,
|
||||||
&sys_innodb_table_locks,
|
&sys_innodb_table_locks,
|
||||||
&sys_innodb_support_xa,
|
&sys_innodb_support_xa,
|
||||||
&sys_innodb_max_purge_lag,
|
|
||||||
&sys_innodb_autoextend_increment,
|
&sys_innodb_autoextend_increment,
|
||||||
&sys_innodb_sync_spin_loops,
|
&sys_innodb_sync_spin_loops,
|
||||||
&sys_innodb_concurrency_tickets,
|
&sys_innodb_concurrency_tickets,
|
||||||
|
13
sql/sp.cc
13
sql/sp.cc
@ -1405,12 +1405,12 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
|
|||||||
{
|
{
|
||||||
Sroutine_hash_entry *rn=
|
Sroutine_hash_entry *rn=
|
||||||
(Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
|
(Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) +
|
||||||
key->length);
|
key->length + 1);
|
||||||
if (!rn) // OOM. Error will be reported using fatal_error().
|
if (!rn) // OOM. Error will be reported using fatal_error().
|
||||||
return FALSE;
|
return FALSE;
|
||||||
rn->key.length= key->length;
|
rn->key.length= key->length;
|
||||||
rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
|
rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry);
|
||||||
memcpy(rn->key.str, key->str, key->length);
|
memcpy(rn->key.str, key->str, key->length + 1);
|
||||||
my_hash_insert(&lex->sroutines, (byte *)rn);
|
my_hash_insert(&lex->sroutines, (byte *)rn);
|
||||||
lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next);
|
lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next);
|
||||||
rn->belong_to_view= belong_to_view;
|
rn->belong_to_view= belong_to_view;
|
||||||
@ -1595,7 +1595,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
|
|||||||
|
|
||||||
for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
|
for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
|
||||||
{
|
{
|
||||||
sp_name name(rt->key.str, rt->key.length);
|
sp_name name(thd, rt->key.str, rt->key.length);
|
||||||
int type= rt->key.str[0];
|
int type= rt->key.str[0];
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
|
|
||||||
@ -1603,13 +1603,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
|
|||||||
&thd->sp_func_cache : &thd->sp_proc_cache),
|
&thd->sp_func_cache : &thd->sp_proc_cache),
|
||||||
&name)))
|
&name)))
|
||||||
{
|
{
|
||||||
name.m_name.str= strchr(name.m_qname.str, '.');
|
|
||||||
name.m_db.length= name.m_name.str - name.m_qname.str;
|
|
||||||
name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str,
|
|
||||||
name.m_db.length);
|
|
||||||
name.m_name.str+= 1;
|
|
||||||
name.m_name.length= name.m_qname.length - name.m_db.length - 1;
|
|
||||||
|
|
||||||
switch ((ret= db_find_routine(thd, type, &name, &sp)))
|
switch ((ret= db_find_routine(thd, type, &name, &sp)))
|
||||||
{
|
{
|
||||||
case SP_OK:
|
case SP_OK:
|
||||||
|
@ -369,17 +369,42 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
sp_name::sp_name(THD *thd, char *key, uint key_len)
|
||||||
|
{
|
||||||
|
m_sroutines_key.str= key;
|
||||||
|
m_sroutines_key.length= key_len;
|
||||||
|
m_qname.str= ++key;
|
||||||
|
m_qname.length= key_len - 1;
|
||||||
|
if ((m_name.str= strchr(m_qname.str, '.')))
|
||||||
|
{
|
||||||
|
m_db.length= m_name.str - key;
|
||||||
|
m_db.str= strmake_root(thd->mem_root, key, m_db.length);
|
||||||
|
m_name.str++;
|
||||||
|
m_name.length= m_qname.length - m_db.length - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_name.str= m_qname.str;
|
||||||
|
m_name.length= m_qname.length;
|
||||||
|
m_db.str= 0;
|
||||||
|
m_db.length= 0;
|
||||||
|
}
|
||||||
|
m_explicit_name= false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_name::init_qname(THD *thd)
|
sp_name::init_qname(THD *thd)
|
||||||
{
|
{
|
||||||
m_sroutines_key.length= m_db.length + m_name.length + 2;
|
const uint dot= !!m_db.length;
|
||||||
|
/* m_sroutines format: m_type + [database + dot] + name + nul */
|
||||||
|
m_sroutines_key.length= 1 + m_db.length + dot + m_name.length;
|
||||||
if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1)))
|
if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1)))
|
||||||
return;
|
return;
|
||||||
m_qname.length= m_sroutines_key.length - 1;
|
m_qname.length= m_sroutines_key.length - 1;
|
||||||
m_qname.str= m_sroutines_key.str + 1;
|
m_qname.str= m_sroutines_key.str + 1;
|
||||||
sprintf(m_qname.str, "%.*s.%.*s",
|
sprintf(m_qname.str, "%.*s%.*s%.*s",
|
||||||
m_db.length, (m_db.length ? m_db.str : ""),
|
m_db.length, (m_db.length ? m_db.str : ""),
|
||||||
m_name.length, m_name.str);
|
dot, ".", m_name.length, m_name.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,16 +72,7 @@ public:
|
|||||||
Creates temporary sp_name object from key, used mainly
|
Creates temporary sp_name object from key, used mainly
|
||||||
for SP-cache lookups.
|
for SP-cache lookups.
|
||||||
*/
|
*/
|
||||||
sp_name(char *key, uint key_len)
|
sp_name(THD *thd, char *key, uint key_len);
|
||||||
{
|
|
||||||
m_sroutines_key.str= key;
|
|
||||||
m_sroutines_key.length= key_len;
|
|
||||||
m_name.str= m_qname.str= key + 1;
|
|
||||||
m_name.length= m_qname.length= key_len - 1;
|
|
||||||
m_db.str= 0;
|
|
||||||
m_db.length= 0;
|
|
||||||
m_explicit_name= false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init. the qualified name from the db and name.
|
// Init. the qualified name from the db and name.
|
||||||
void init_qname(THD *thd); // thd for memroot allocation
|
void init_qname(THD *thd); // thd for memroot allocation
|
||||||
|
@ -1745,7 +1745,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close handler tables which are marked for flush */
|
/*
|
||||||
|
In order for the back off and re-start process to work properly,
|
||||||
|
handler tables having old versions (due to FLUSH TABLES or pending
|
||||||
|
name-lock) MUST be closed. This is specially important if a name-lock
|
||||||
|
is pending for any table of the handler_tables list, otherwise a
|
||||||
|
deadlock may occur.
|
||||||
|
*/
|
||||||
if (thd->handler_tables)
|
if (thd->handler_tables)
|
||||||
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
|
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
|
||||||
|
|
||||||
@ -1810,6 +1816,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
|||||||
table->db_stat == 0 signals wait_for_locked_table_names
|
table->db_stat == 0 signals wait_for_locked_table_names
|
||||||
that the tables in question are not used any more. See
|
that the tables in question are not used any more. See
|
||||||
table_is_used call for details.
|
table_is_used call for details.
|
||||||
|
|
||||||
|
Notice that HANDLER tables were already taken care of by
|
||||||
|
the earlier call to mysql_ha_flush() in this same critical
|
||||||
|
section.
|
||||||
*/
|
*/
|
||||||
close_old_data_files(thd,thd->open_tables,0,0);
|
close_old_data_files(thd,thd->open_tables,0,0);
|
||||||
/*
|
/*
|
||||||
|
@ -65,11 +65,6 @@
|
|||||||
static enum enum_ha_read_modes rkey_to_rnext[]=
|
static enum enum_ha_read_modes rkey_to_rnext[]=
|
||||||
{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
|
{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
|
||||||
|
|
||||||
#define HANDLER_TABLES_HACK(thd) { \
|
|
||||||
TABLE *tmp=thd->open_tables; \
|
|
||||||
thd->open_tables=thd->handler_tables; \
|
|
||||||
thd->handler_tables=tmp; }
|
|
||||||
|
|
||||||
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags);
|
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags);
|
||||||
|
|
||||||
|
|
||||||
@ -187,6 +182,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
|||||||
char *db, *name, *alias;
|
char *db, *name, *alias;
|
||||||
uint dblen, namelen, aliaslen, counter;
|
uint dblen, namelen, aliaslen, counter;
|
||||||
int error;
|
int error;
|
||||||
|
TABLE *backup_open_tables;
|
||||||
DBUG_ENTER("mysql_ha_open");
|
DBUG_ENTER("mysql_ha_open");
|
||||||
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
|
||||||
tables->db, tables->table_name, tables->alias,
|
tables->db, tables->table_name, tables->alias,
|
||||||
@ -215,18 +211,40 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Save and reset the open_tables list so that open_tables() won't
|
||||||
|
be able to access (or know about) the previous list. And on return
|
||||||
|
from open_tables(), thd->open_tables will contain only the opened
|
||||||
|
table.
|
||||||
|
|
||||||
|
The thd->handler_tables list is kept as-is to avoid deadlocks if
|
||||||
|
open_table(), called by open_tables(), needs to back-off because
|
||||||
|
of a pending name-lock on the table being opened.
|
||||||
|
|
||||||
|
See open_table() back-off comments for more details.
|
||||||
|
*/
|
||||||
|
backup_open_tables= thd->open_tables;
|
||||||
|
thd->open_tables= NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
open_tables() will set 'tables->table' if successful.
|
open_tables() will set 'tables->table' if successful.
|
||||||
It must be NULL for a real open when calling open_tables().
|
It must be NULL for a real open when calling open_tables().
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(! tables->table);
|
DBUG_ASSERT(! tables->table);
|
||||||
HANDLER_TABLES_HACK(thd);
|
|
||||||
|
|
||||||
/* for now HANDLER can be used only for real TABLES */
|
/* for now HANDLER can be used only for real TABLES */
|
||||||
tables->required_type= FRMTYPE_TABLE;
|
tables->required_type= FRMTYPE_TABLE;
|
||||||
error= open_tables(thd, &tables, &counter, 0);
|
error= open_tables(thd, &tables, &counter, 0);
|
||||||
|
|
||||||
HANDLER_TABLES_HACK(thd);
|
/* restore the state and merge the opened table into handler_tables list */
|
||||||
|
if (thd->open_tables)
|
||||||
|
{
|
||||||
|
thd->open_tables->next= thd->handler_tables;
|
||||||
|
thd->handler_tables= thd->open_tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
thd->open_tables= backup_open_tables;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -351,7 +369,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
|
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
|
||||||
{
|
{
|
||||||
TABLE_LIST *hash_tables;
|
TABLE_LIST *hash_tables;
|
||||||
TABLE *table;
|
TABLE *table, *backup_open_tables;
|
||||||
MYSQL_LOCK *lock;
|
MYSQL_LOCK *lock;
|
||||||
List<Item> list;
|
List<Item> list;
|
||||||
Protocol *protocol= thd->protocol;
|
Protocol *protocol= thd->protocol;
|
||||||
@ -361,7 +379,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
uint num_rows;
|
uint num_rows;
|
||||||
byte *key;
|
byte *key;
|
||||||
uint key_len;
|
uint key_len;
|
||||||
bool not_used;
|
bool need_reopen;
|
||||||
DBUG_ENTER("mysql_ha_read");
|
DBUG_ENTER("mysql_ha_read");
|
||||||
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
|
||||||
tables->db, tables->table_name, tables->alias));
|
tables->db, tables->table_name, tables->alias));
|
||||||
@ -375,6 +393,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
List_iterator<Item> it(list);
|
List_iterator<Item> it(list);
|
||||||
it++;
|
it++;
|
||||||
|
|
||||||
|
retry:
|
||||||
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
||||||
(byte*) tables->alias,
|
(byte*) tables->alias,
|
||||||
strlen(tables->alias) + 1)))
|
strlen(tables->alias) + 1)))
|
||||||
@ -427,9 +446,34 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
}
|
}
|
||||||
tables->table=table;
|
tables->table=table;
|
||||||
|
|
||||||
HANDLER_TABLES_HACK(thd);
|
/* save open_tables state */
|
||||||
lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used);
|
backup_open_tables= thd->open_tables;
|
||||||
HANDLER_TABLES_HACK(thd);
|
/*
|
||||||
|
mysql_lock_tables() needs thd->open_tables to be set correctly to
|
||||||
|
be able to handle aborts properly. When the abort happens, it's
|
||||||
|
safe to not protect thd->handler_tables because it won't close any
|
||||||
|
tables.
|
||||||
|
*/
|
||||||
|
thd->open_tables= thd->handler_tables;
|
||||||
|
|
||||||
|
lock= mysql_lock_tables(thd, &tables->table, 1,
|
||||||
|
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen);
|
||||||
|
|
||||||
|
/* restore previous context */
|
||||||
|
thd->open_tables= backup_open_tables;
|
||||||
|
|
||||||
|
if (need_reopen)
|
||||||
|
{
|
||||||
|
mysql_ha_close_table(thd, tables);
|
||||||
|
hash_tables->table= NULL;
|
||||||
|
/*
|
||||||
|
The lock might have been aborted, we need to manually reset
|
||||||
|
thd->some_tables_deleted because handler's tables are closed
|
||||||
|
in a non-standard way. Otherwise we might loop indefinitely.
|
||||||
|
*/
|
||||||
|
thd->some_tables_deleted= 0;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lock)
|
if (!lock)
|
||||||
goto err0; // mysql_lock_tables() printed error message already
|
goto err0; // mysql_lock_tables() printed error message already
|
||||||
|
@ -93,6 +93,10 @@ const char *xa_state_names[]={
|
|||||||
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
|
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
static bool do_command(THD *thd);
|
||||||
|
#endif // EMBEDDED_LIBRARY
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
static void test_signal(int sig_ptr)
|
static void test_signal(int sig_ptr)
|
||||||
{
|
{
|
||||||
@ -1199,21 +1203,26 @@ pthread_handler_t handle_one_connection(void *arg)
|
|||||||
}
|
}
|
||||||
if (thd->user_connect)
|
if (thd->user_connect)
|
||||||
decrease_user_connections(thd->user_connect);
|
decrease_user_connections(thd->user_connect);
|
||||||
|
|
||||||
|
if (thd->killed ||
|
||||||
|
net->vio && net->error && net->report_error)
|
||||||
|
{
|
||||||
|
statistic_increment(aborted_threads, &LOCK_status);
|
||||||
|
}
|
||||||
|
|
||||||
if (net->error && net->vio != 0 && net->report_error)
|
if (net->error && net->vio != 0 && net->report_error)
|
||||||
{
|
{
|
||||||
if (!thd->killed && thd->variables.log_warnings > 1)
|
if (!thd->killed && thd->variables.log_warnings > 1)
|
||||||
|
{
|
||||||
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
|
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
|
||||||
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
||||||
sctx->user ? sctx->user : "unauthenticated",
|
sctx->user ? sctx->user : "unauthenticated",
|
||||||
sctx->host_or_ip,
|
sctx->host_or_ip,
|
||||||
(net->last_errno ? ER(net->last_errno) :
|
(net->last_errno ? ER(net->last_errno) :
|
||||||
ER(ER_UNKNOWN_ERROR)));
|
ER(ER_UNKNOWN_ERROR)));
|
||||||
net_send_error(thd, net->last_errno, NullS);
|
|
||||||
statistic_increment(aborted_threads,&LOCK_status);
|
|
||||||
}
|
}
|
||||||
else if (thd->killed)
|
|
||||||
{
|
net_send_error(thd, net->last_errno, NullS);
|
||||||
statistic_increment(aborted_threads,&LOCK_status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end_thread:
|
end_thread:
|
||||||
@ -1520,7 +1529,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
|
|||||||
1 request of thread shutdown (see dispatch_command() description)
|
1 request of thread shutdown (see dispatch_command() description)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool do_command(THD *thd)
|
static bool do_command(THD *thd)
|
||||||
{
|
{
|
||||||
char *packet= 0;
|
char *packet= 0;
|
||||||
ulong packet_length;
|
ulong packet_length;
|
||||||
@ -1550,12 +1559,12 @@ bool do_command(THD *thd)
|
|||||||
DBUG_PRINT("info",("Got error %d reading command from socket %s",
|
DBUG_PRINT("info",("Got error %d reading command from socket %s",
|
||||||
net->error,
|
net->error,
|
||||||
vio_description(net->vio)));
|
vio_description(net->vio)));
|
||||||
|
|
||||||
/* Check if we can continue without closing the connection */
|
/* Check if we can continue without closing the connection */
|
||||||
|
|
||||||
if (net->error != 3)
|
if (net->error != 3)
|
||||||
{
|
|
||||||
statistic_increment(aborted_threads,&LOCK_status);
|
|
||||||
DBUG_RETURN(TRUE); // We have to close it.
|
DBUG_RETURN(TRUE); // We have to close it.
|
||||||
}
|
|
||||||
net_send_error(thd, net->last_errno, NullS);
|
net_send_error(thd, net->last_errno, NullS);
|
||||||
net->error= 0;
|
net->error= 0;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
@ -4007,12 +4016,6 @@ end_with_restore_list:
|
|||||||
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
|
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
|
|
||||||
&thd->sp_func_cache, FALSE))
|
|
||||||
{
|
|
||||||
my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (!(res = mysql_create_function(thd, &lex->udf)))
|
if (!(res = mysql_create_function(thd, &lex->udf)))
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
#else
|
#else
|
||||||
|
@ -426,14 +426,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
|
|||||||
}
|
}
|
||||||
if (udf->name.length > NAME_LEN)
|
if (udf->name.length > NAME_LEN)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name);
|
my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name.str);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
rw_wrlock(&THR_LOCK_udf);
|
rw_wrlock(&THR_LOCK_udf);
|
||||||
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
|
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
|
||||||
{
|
{
|
||||||
my_error(ER_UDF_EXISTS, MYF(0), udf->name);
|
my_error(ER_UDF_EXISTS, MYF(0), udf->name.str);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!(dl = find_udf_dl(udf->dl)))
|
if (!(dl = find_udf_dl(udf->dl)))
|
||||||
|
347
sql/sql_yacc.yy
347
sql/sql_yacc.yy
@ -1121,8 +1121,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
|
|
||||||
%type <cast_type> cast_type
|
%type <cast_type> cast_type
|
||||||
|
|
||||||
%type <udf_type> udf_func_type
|
|
||||||
|
|
||||||
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
|
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
|
||||||
|
|
||||||
%type <lex_user> user grant_user
|
%type <lex_user> user grant_user
|
||||||
@ -1181,11 +1179,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
statement sp_suid
|
statement sp_suid
|
||||||
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
||||||
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||||
definer view_replace_or_algorithm view_replace view_algorithm_opt
|
view_replace_or_algorithm view_replace view_algorithm_opt
|
||||||
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
|
view_algorithm view_or_trigger_or_sp definer_tail
|
||||||
view_suid view_tail view_list_opt view_list view_select
|
view_suid view_tail view_list_opt view_list view_select
|
||||||
view_check_option trigger_tail sp_tail
|
view_check_option trigger_tail sp_tail sf_tail udf_tail
|
||||||
case_stmt_specification simple_case_stmt searched_case_stmt
|
case_stmt_specification simple_case_stmt searched_case_stmt
|
||||||
|
definer_opt no_definer definer
|
||||||
END_OF_INPUT
|
END_OF_INPUT
|
||||||
|
|
||||||
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
|
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
|
||||||
@ -1571,6 +1570,7 @@ sp_name:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
LEX_STRING db;
|
LEX_STRING db;
|
||||||
|
|
||||||
if (check_routine_name($1))
|
if (check_routine_name($1))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
|
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
|
||||||
@ -1584,124 +1584,6 @@ sp_name:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
create_function_tail:
|
|
||||||
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
|
|
||||||
{
|
|
||||||
LEX *lex=Lex;
|
|
||||||
if (lex->definer != NULL)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
DEFINER is a concept meaningful when interpreting SQL code.
|
|
||||||
UDF functions are compiled.
|
|
||||||
Using DEFINER with UDF has therefore no semantic,
|
|
||||||
and is considered a parsing error.
|
|
||||||
*/
|
|
||||||
my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
|
||||||
lex->udf.name = lex->spname->m_name;
|
|
||||||
lex->udf.returns=(Item_result) $2;
|
|
||||||
lex->udf.dl=$4.str;
|
|
||||||
}
|
|
||||||
| '('
|
|
||||||
{
|
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
|
||||||
sp_head *sp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
First check if AGGREGATE was used, in that case it's a
|
|
||||||
syntax error.
|
|
||||||
*/
|
|
||||||
if (lex->udf.type == UDFTYPE_AGGREGATE)
|
|
||||||
{
|
|
||||||
my_error(ER_SP_NO_AGGREGATE, MYF(0));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lex->sphead)
|
|
||||||
{
|
|
||||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
/* Order is important here: new - reset - init */
|
|
||||||
sp= new sp_head();
|
|
||||||
sp->reset_thd_mem_root(thd);
|
|
||||||
sp->init(lex);
|
|
||||||
sp->init_sp_name(thd, lex->spname);
|
|
||||||
|
|
||||||
sp->m_type= TYPE_ENUM_FUNCTION;
|
|
||||||
lex->sphead= sp;
|
|
||||||
/*
|
|
||||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
|
||||||
* stored procedure, otherwise yylex will chop it into pieces
|
|
||||||
* at each ';'.
|
|
||||||
*/
|
|
||||||
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
|
||||||
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
|
||||||
lex->sphead->m_param_begin= lip->tok_start+1;
|
|
||||||
}
|
|
||||||
sp_fdparam_list ')'
|
|
||||||
{
|
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
|
||||||
|
|
||||||
lex->sphead->m_param_end= lip->tok_start;
|
|
||||||
}
|
|
||||||
RETURNS_SYM
|
|
||||||
{
|
|
||||||
LEX *lex= Lex;
|
|
||||||
lex->charset= NULL;
|
|
||||||
lex->length= lex->dec= NULL;
|
|
||||||
lex->interval_list.empty();
|
|
||||||
lex->type= 0;
|
|
||||||
}
|
|
||||||
type
|
|
||||||
{
|
|
||||||
LEX *lex= Lex;
|
|
||||||
sp_head *sp= lex->sphead;
|
|
||||||
|
|
||||||
if (sp->fill_field_definition(YYTHD, lex,
|
|
||||||
(enum enum_field_types) $8,
|
|
||||||
&sp->m_return_field_def))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
|
|
||||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
|
||||||
}
|
|
||||||
sp_c_chistics
|
|
||||||
{
|
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
|
||||||
|
|
||||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
|
||||||
lex->sphead->m_body_begin= lip->tok_start;
|
|
||||||
}
|
|
||||||
sp_proc_stmt
|
|
||||||
{
|
|
||||||
LEX *lex= Lex;
|
|
||||||
sp_head *sp= lex->sphead;
|
|
||||||
|
|
||||||
if (sp->is_not_allowed_in_function("function"))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
|
|
||||||
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
|
||||||
sp->init_strings(YYTHD, lex);
|
|
||||||
if (!(sp->m_flags & sp_head::HAS_RETURN))
|
|
||||||
{
|
|
||||||
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
/* Restore flag if it was cleared above */
|
|
||||||
if (sp->m_old_cmq)
|
|
||||||
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
|
||||||
sp->restore_thd_mem_root(YYTHD);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
sp_a_chistics:
|
sp_a_chistics:
|
||||||
/* Empty */ {}
|
/* Empty */ {}
|
||||||
| sp_a_chistics sp_chistic {}
|
| sp_a_chistics sp_chistic {}
|
||||||
@ -3002,10 +2884,6 @@ opt_select_from:
|
|||||||
opt_limit_clause {}
|
opt_limit_clause {}
|
||||||
| select_from select_lock_type;
|
| select_from select_lock_type;
|
||||||
|
|
||||||
udf_func_type:
|
|
||||||
/* empty */ { $$ = UDFTYPE_FUNCTION; }
|
|
||||||
| AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; };
|
|
||||||
|
|
||||||
udf_type:
|
udf_type:
|
||||||
STRING_SYM {$$ = (int) STRING_RESULT; }
|
STRING_SYM {$$ = (int) STRING_RESULT; }
|
||||||
| REAL {$$ = (int) REAL_RESULT; }
|
| REAL {$$ = (int) REAL_RESULT; }
|
||||||
@ -3669,7 +3547,7 @@ alter:
|
|||||||
lex->sql_command= SQLCOM_ALTER_FUNCTION;
|
lex->sql_command= SQLCOM_ALTER_FUNCTION;
|
||||||
lex->spname= $3;
|
lex->spname= $3;
|
||||||
}
|
}
|
||||||
| ALTER view_algorithm_opt definer view_suid
|
| ALTER view_algorithm_opt definer_opt view_suid
|
||||||
VIEW_SYM table_ident
|
VIEW_SYM table_ident
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
@ -5196,8 +5074,30 @@ simple_expr:
|
|||||||
{
|
{
|
||||||
THD *thd= lex->thd;
|
THD *thd= lex->thd;
|
||||||
LEX_STRING db;
|
LEX_STRING db;
|
||||||
|
if (! thd->db && ! lex->sphead)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The proper error message should be in the lines of:
|
||||||
|
Can't resolve <name>() to a function call,
|
||||||
|
because this function:
|
||||||
|
- is not a native function,
|
||||||
|
- is not a user defined function,
|
||||||
|
- can not match a stored function since no database is selected.
|
||||||
|
Reusing ER_SP_DOES_NOT_EXIST have a message consistent with
|
||||||
|
the case when a default database exist, see below.
|
||||||
|
*/
|
||||||
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
|
||||||
|
"FUNCTION", $1.str);
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (lex->copy_db_to(&db.str, &db.length))
|
if (lex->copy_db_to(&db.str, &db.length))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
From here, the parser assumes <name>() is a stored function,
|
||||||
|
as a last choice. This later can lead to ER_SP_DOES_NOT_EXIST.
|
||||||
|
*/
|
||||||
sp_name *name= new sp_name(db, $1, false);
|
sp_name *name= new sp_name(db, $1, false);
|
||||||
if (name)
|
if (name)
|
||||||
name->init_qname(thd);
|
name->init_qname(thd);
|
||||||
@ -6499,9 +6399,11 @@ drop:
|
|||||||
lex->drop_if_exists=$3;
|
lex->drop_if_exists=$3;
|
||||||
lex->name=$4.str;
|
lex->name=$4.str;
|
||||||
}
|
}
|
||||||
| DROP FUNCTION_SYM if_exists sp_name
|
| DROP FUNCTION_SYM if_exists ident '.' ident
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
sp_name *spname;
|
||||||
if (lex->sphead)
|
if (lex->sphead)
|
||||||
{
|
{
|
||||||
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
|
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
|
||||||
@ -6509,7 +6411,28 @@ drop:
|
|||||||
}
|
}
|
||||||
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
||||||
lex->drop_if_exists= $3;
|
lex->drop_if_exists= $3;
|
||||||
lex->spname= $4;
|
spname= new sp_name($4, $6, true);
|
||||||
|
spname->init_qname(thd);
|
||||||
|
lex->spname= spname;
|
||||||
|
}
|
||||||
|
| DROP FUNCTION_SYM if_exists ident
|
||||||
|
{
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
LEX_STRING db= {0, 0};
|
||||||
|
sp_name *spname;
|
||||||
|
if (lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
if (thd->db && lex->copy_db_to(&db.str, &db.length))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
lex->sql_command = SQLCOM_DROP_FUNCTION;
|
||||||
|
lex->drop_if_exists= $3;
|
||||||
|
spname= new sp_name(db, $4, false);
|
||||||
|
spname->init_qname(thd);
|
||||||
|
lex->spname= spname;
|
||||||
}
|
}
|
||||||
| DROP PROCEDURE if_exists sp_name
|
| DROP PROCEDURE if_exists sp_name
|
||||||
{
|
{
|
||||||
@ -9558,19 +9481,27 @@ subselect_end:
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
view_or_trigger_or_sp:
|
view_or_trigger_or_sp:
|
||||||
definer view_or_trigger_or_sp_tail
|
definer definer_tail
|
||||||
{}
|
{}
|
||||||
| view_replace_or_algorithm definer view_tail
|
| no_definer no_definer_tail
|
||||||
|
{}
|
||||||
|
| view_replace_or_algorithm definer_opt view_tail
|
||||||
{}
|
{}
|
||||||
;
|
;
|
||||||
|
|
||||||
view_or_trigger_or_sp_tail:
|
definer_tail:
|
||||||
view_tail
|
view_tail
|
||||||
{}
|
|
||||||
| trigger_tail
|
| trigger_tail
|
||||||
{}
|
|
||||||
| sp_tail
|
| sp_tail
|
||||||
{}
|
| sf_tail
|
||||||
|
;
|
||||||
|
|
||||||
|
no_definer_tail:
|
||||||
|
view_tail
|
||||||
|
| trigger_tail
|
||||||
|
| sp_tail
|
||||||
|
| sf_tail
|
||||||
|
| udf_tail
|
||||||
;
|
;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@ -9579,7 +9510,12 @@ view_or_trigger_or_sp_tail:
|
|||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
definer:
|
definer_opt:
|
||||||
|
no_definer
|
||||||
|
| definer
|
||||||
|
;
|
||||||
|
|
||||||
|
no_definer:
|
||||||
/* empty */
|
/* empty */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -9591,11 +9527,14 @@ definer:
|
|||||||
*/
|
*/
|
||||||
YYTHD->lex->definer= 0;
|
YYTHD->lex->definer= 0;
|
||||||
}
|
}
|
||||||
| DEFINER_SYM EQ user
|
;
|
||||||
|
|
||||||
|
definer:
|
||||||
|
DEFINER_SYM EQ user
|
||||||
{
|
{
|
||||||
YYTHD->lex->definer= get_current_user(YYTHD, $3);
|
YYTHD->lex->definer= get_current_user(YYTHD, $3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
|
||||||
@ -9807,17 +9746,131 @@ trigger_tail:
|
|||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
sp_tail:
|
udf_tail:
|
||||||
udf_func_type remember_name FUNCTION_SYM sp_name
|
AGGREGATE_SYM remember_name FUNCTION_SYM ident
|
||||||
|
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->udf.type= $1;
|
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
||||||
|
lex->udf.type= UDFTYPE_AGGREGATE;
|
||||||
lex->stmt_definition_begin= $2;
|
lex->stmt_definition_begin= $2;
|
||||||
lex->spname= $4;
|
lex->udf.name = $4;
|
||||||
|
lex->udf.returns=(Item_result) $6;
|
||||||
|
lex->udf.dl=$8.str;
|
||||||
}
|
}
|
||||||
create_function_tail
|
| remember_name FUNCTION_SYM ident
|
||||||
{}
|
RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
|
||||||
| PROCEDURE remember_name sp_name
|
{
|
||||||
|
LEX *lex=Lex;
|
||||||
|
lex->sql_command = SQLCOM_CREATE_FUNCTION;
|
||||||
|
lex->udf.type= UDFTYPE_FUNCTION;
|
||||||
|
lex->stmt_definition_begin= $1;
|
||||||
|
lex->udf.name = $3;
|
||||||
|
lex->udf.returns=(Item_result) $5;
|
||||||
|
lex->udf.dl=$7.str;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
sf_tail:
|
||||||
|
remember_name /* $1 */
|
||||||
|
FUNCTION_SYM /* $2 */
|
||||||
|
sp_name /* $3 */
|
||||||
|
'(' /* 44 */
|
||||||
|
{ /* $5 */
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
sp_head *sp;
|
||||||
|
|
||||||
|
lex->stmt_definition_begin= $1;
|
||||||
|
lex->spname= $3;
|
||||||
|
|
||||||
|
if (lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Order is important here: new - reset - init */
|
||||||
|
sp= new sp_head();
|
||||||
|
sp->reset_thd_mem_root(thd);
|
||||||
|
sp->init(lex);
|
||||||
|
sp->init_sp_name(thd, lex->spname);
|
||||||
|
|
||||||
|
sp->m_type= TYPE_ENUM_FUNCTION;
|
||||||
|
lex->sphead= sp;
|
||||||
|
/*
|
||||||
|
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||||
|
* stored procedure, otherwise yylex will chop it into pieces
|
||||||
|
* at each ';'.
|
||||||
|
*/
|
||||||
|
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||||
|
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||||
|
lex->sphead->m_param_begin= lip->tok_start+1;
|
||||||
|
}
|
||||||
|
sp_fdparam_list /* $6 */
|
||||||
|
')' /* $7 */
|
||||||
|
{ /* $8 */
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
|
lex->sphead->m_param_end= lip->tok_start;
|
||||||
|
}
|
||||||
|
RETURNS_SYM /* $9 */
|
||||||
|
{ /* $10 */
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->charset= NULL;
|
||||||
|
lex->length= lex->dec= NULL;
|
||||||
|
lex->interval_list.empty();
|
||||||
|
lex->type= 0;
|
||||||
|
}
|
||||||
|
type /* $11 */
|
||||||
|
{ /* $12 */
|
||||||
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
|
if (sp->fill_field_definition(YYTHD, lex,
|
||||||
|
(enum enum_field_types) $11,
|
||||||
|
&sp->m_return_field_def))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
|
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||||
|
}
|
||||||
|
sp_c_chistics /* $13 */
|
||||||
|
{ /* $14 */
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
|
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||||
|
lex->sphead->m_body_begin= lip->tok_start;
|
||||||
|
}
|
||||||
|
sp_proc_stmt /* $15 */
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
|
if (sp->is_not_allowed_in_function("function"))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
|
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
||||||
|
sp->init_strings(YYTHD, lex);
|
||||||
|
if (!(sp->m_flags & sp_head::HAS_RETURN))
|
||||||
|
{
|
||||||
|
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
/* Restore flag if it was cleared above */
|
||||||
|
if (sp->m_old_cmq)
|
||||||
|
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
||||||
|
sp->restore_thd_mem_root(YYTHD);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
sp_tail:
|
||||||
|
PROCEDURE remember_name sp_name
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user