Merge 10.6 into 10.11

This commit is contained in:
Marko Mäkelä 2026-01-02 11:06:05 +02:00
commit 8fab129382
36 changed files with 594 additions and 512 deletions

View file

@ -79,6 +79,7 @@ extern int (*dbug_sanity)(void);
#define DBUG_PRINT(keyword,arglist) \
do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
#ifdef HAVE_ATTRIBUTE_CLEANUP
#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \
@ -98,6 +99,7 @@ extern int (*dbug_sanity)(void);
#define DBUG_RETURN(a1) return(a1)
#define DBUG_VOID_RETURN return
#define DBUG_PRINT(keyword,arglist) do{} while(0)
#define DBUG_DUMP(keyword,a1,a2) do{} while(0)
#endif
#define DBUG_EXECUTE(keyword,a1) \
@ -115,7 +117,6 @@ extern int (*dbug_sanity)(void);
#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
#define DBUG_PROCESS(a1) _db_process_(a1)
#define DBUG_FILE _db_fp_()
#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
#define DBUG_END() _db_end_ ()
#define DBUG_LOCK_FILE _db_lock_file_()
#define DBUG_UNLOCK_FILE _db_unlock_file_()
@ -234,7 +235,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
one should #include <sstream>. We intentionally avoid including it here to save
compilation time.
*/
# ifdef DBUG_OFF
# if defined DBUG_OFF || !defined DBUG_TRACE
# define DBUG_LOG(keyword, v) do {} while (0)
# else
# define DBUG_LOG(keyword, v) do { \

View file

@ -121,3 +121,46 @@ connection default;
DROP DATABASE meow;
set local sql_mode=default;
set global sql_mode=default;
#
# MDEV-37950: INSERT ... RETURNING exposes columns for which
# the user lacks SELECT privilege
#
CREATE USER regular;
GRANT INSERT ON *.* TO regular;
GRANT DELETE ON *.* TO regular;
CREATE DATABASE test1;
DROP TABLE IF EXISTS test1.t_trigger_test1;
Warnings:
Note 1051 Unknown table 'test1.t_trigger_test1'
CREATE TABLE test1.t_trigger_test1 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
note VARCHAR(100)
);
CREATE TRIGGER test1.trg_before_insert
BEFORE INSERT ON test1.t_trigger_test1
FOR EACH ROW
BEGIN
SET NEW.name = CONCAT('BEFORE_', NEW.name);
END |
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
# same for DELETE because delete with "WHERE" still requires to
# read from the table, which basically means having select privileges
DELETE FROM test1.t_trigger_test1 WHERE id=1;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
DELETE FROM test1.t_trigger_test1 RETURNING *;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
DELETE FROM test1.t_trigger_test1 RETURNING id;
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
DELETE FROM test1.t_trigger_test1;
DROP TRIGGER test1.trg_before_insert;
DROP TABLE test1.t_trigger_test1;
DROP USER regular;
DROP DATABASE test1;

View file

@ -158,3 +158,60 @@ DROP DATABASE meow;
set local sql_mode=default;
set global sql_mode=default;
--echo #
--echo # MDEV-37950: INSERT ... RETURNING exposes columns for which
--echo # the user lacks SELECT privilege
--echo #
CREATE USER regular;
GRANT INSERT ON *.* TO regular;
GRANT DELETE ON *.* TO regular;
CREATE DATABASE test1;
DROP TABLE IF EXISTS test1.t_trigger_test1;
CREATE TABLE test1.t_trigger_test1 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
note VARCHAR(100)
);
DELIMITER |;
CREATE TRIGGER test1.trg_before_insert
BEFORE INSERT ON test1.t_trigger_test1
FOR EACH ROW
BEGIN
SET NEW.name = CONCAT('BEFORE_', NEW.name);
END |
DELIMITER ;|
change_user regular;
--error ER_COLUMNACCESS_DENIED_ERROR
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *;
--error ER_COLUMNACCESS_DENIED_ERROR
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note;
--echo # same for DELETE because delete with "WHERE" still requires to
--echo # read from the table, which basically means having select privileges
--error ER_COLUMNACCESS_DENIED_ERROR
DELETE FROM test1.t_trigger_test1 WHERE id=1;
--error ER_COLUMNACCESS_DENIED_ERROR
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id;
--error ER_COLUMNACCESS_DENIED_ERROR
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *;
--error ER_COLUMNACCESS_DENIED_ERROR
DELETE FROM test1.t_trigger_test1 RETURNING *;
--error ER_COLUMNACCESS_DENIED_ERROR
DELETE FROM test1.t_trigger_test1 RETURNING id;
DELETE FROM test1.t_trigger_test1;
change_user root;
DROP TRIGGER test1.trg_before_insert;
DROP TABLE test1.t_trigger_test1;
DROP USER regular;
DROP DATABASE test1;

View file

@ -17283,8 +17283,7 @@ set f1 = f1;
return f1;
END//
SELECT fn104('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?\0\0\0\0\0\0?\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0@\0\0\0\0\0\0@');
fn104('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?\0\0\0\0\0\0?\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0@\0\0\0\0\0\0@')
??@@@@
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
DROP FUNCTION IF EXISTS fn105;
CREATE FUNCTION fn105( f1 point) returns point
BEGIN
@ -18418,8 +18417,7 @@ set f1 = f1;
SELECT f1;
END//
CALL sp104('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?\0\0\0\0\0\0?\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0@\0\0\0\0\0\0@');
f1
??@@@@
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
DROP PROCEDURE IF EXISTS sp105;
CREATE PROCEDURE sp105( f1 point)
BEGIN

View file

@ -0,0 +1,14 @@
connection node_2;
connection node_1;
#
# MDEV-38374 nonsense code in wsrep_store_key_val_for_row()
#
create table t1 (
id int auto_increment primary key,
blob_data longblob not null,
unique key idx_blob_prefix (blob_data(3072))
) engine=innodb;
insert into t1 (blob_data) values ('a');
update t1 set blob_data = repeat('x', 4000) where id = 1;
drop table t1;
# End of 10.6 tests

View file

@ -0,0 +1,17 @@
source include/galera_cluster.inc;
source include/have_innodb.inc;
--echo #
--echo # MDEV-38374 nonsense code in wsrep_store_key_val_for_row()
--echo #
create table t1 (
id int auto_increment primary key,
blob_data longblob not null,
unique key idx_blob_prefix (blob_data(3072))
) engine=innodb;
insert into t1 (blob_data) values ('a');
update t1 set blob_data = repeat('x', 4000) where id = 1;
drop table t1;
--echo # End of 10.6 tests

View file

@ -617,3 +617,15 @@ commit;
disconnect a;
connection default;
drop table t1;
#
# MDEV-38372 ASAN error in InnoDB on malformed WKB
#
create table t1 (
id int auto_increment primary key,
geom geometry not null,
spatial index (geom)
) engine=innodb;
insert t1 (geom) values (X'000000000107000000FF000000');
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1;
# End of 10.6 tests

View file

@ -40,5 +40,18 @@ disconnect a;
connection default;
drop table t1;
--echo #
--echo # MDEV-38372 ASAN error in InnoDB on malformed WKB
--echo #
create table t1 (
id int auto_increment primary key,
geom geometry not null,
spatial index (geom)
) engine=innodb;
--error ER_CANT_CREATE_GEOMETRY_OBJECT
insert t1 (geom) values (X'000000000107000000FF000000');
drop table t1;
--echo # End of 10.6 tests

View file

@ -450,8 +450,6 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD \n# comment\nFOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1=<secret>',ID
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0

View file

@ -361,8 +361,6 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD\n# comment\nFOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1=<secret>',ID
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_events=\'\'',0

View file

@ -22,6 +22,7 @@
#include <my_config.h>
#include <assert.h>
#include "sql_command.h"
#ifndef _WIN32
#define DO_SYSLOG
@ -811,189 +812,6 @@ static int user_coll_fill(struct user_coll *c, char *users,
}
enum sa_keywords
{
SQLCOM_NOTHING=0,
SQLCOM_DDL,
SQLCOM_DML,
SQLCOM_GRANT,
SQLCOM_CREATE_USER,
SQLCOM_ALTER_USER,
SQLCOM_CHANGE_MASTER,
SQLCOM_CREATE_SERVER,
SQLCOM_SET_OPTION,
SQLCOM_ALTER_SERVER,
SQLCOM_TRUNCATE,
SQLCOM_QUERY_ADMIN,
SQLCOM_DCL,
SQLCOM_FOUND=-1,
};
struct sa_keyword
{
int length;
const char *wd;
struct sa_keyword *next;
enum sa_keywords type;
};
struct sa_keyword xml_word[]=
{
{3, "XML", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword user_word[]=
{
{4, "USER", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword data_word[]=
{
{4, "DATA", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword server_word[]=
{
{6, "SERVER", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword master_word[]=
{
{6, "MASTER", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword password_word[]=
{
{8, "PASSWORD", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword function_word[]=
{
{8, "FUNCTION", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword statement_word[]=
{
{9, "STATEMENT", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword procedure_word[]=
{
{9, "PROCEDURE", 0, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword replace_user_word[]=
{
{7, "REPLACE", user_word, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword or_replace_user_word[]=
{
{2, "OR", replace_user_word, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword replace_server_word[]=
{
{7, "REPLACE", server_word, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword or_replace_server_word[]=
{
{2, "OR", replace_server_word, SQLCOM_FOUND},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword keywords_to_skip[]=
{
{3, "SET", statement_word, SQLCOM_QUERY_ADMIN},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword not_ddl_keywords[]=
{
{4, "DROP", user_word, SQLCOM_DCL},
{6, "CREATE", user_word, SQLCOM_DCL},
{6, "CREATE", or_replace_user_word, SQLCOM_DCL},
{6, "RENAME", user_word, SQLCOM_DCL},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword ddl_keywords[]=
{
{4, "DROP", 0, SQLCOM_DDL},
{5, "ALTER", 0, SQLCOM_DDL},
{6, "CREATE", 0, SQLCOM_DDL},
{6, "RENAME", 0, SQLCOM_DDL},
{8, "TRUNCATE", 0, SQLCOM_DDL},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword dml_keywords[]=
{
{2, "DO", 0, SQLCOM_DML},
{4, "CALL", 0, SQLCOM_DML},
{4, "LOAD", data_word, SQLCOM_DML},
{4, "LOAD", xml_word, SQLCOM_DML},
{6, "DELETE", 0, SQLCOM_DML},
{6, "INSERT", 0, SQLCOM_DML},
{6, "SELECT", 0, SQLCOM_DML},
{6, "UPDATE", 0, SQLCOM_DML},
{7, "HANDLER", 0, SQLCOM_DML},
{7, "REPLACE", 0, SQLCOM_DML},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword dml_no_select_keywords[]=
{
{2, "DO", 0, SQLCOM_DML},
{4, "CALL", 0, SQLCOM_DML},
{4, "LOAD", data_word, SQLCOM_DML},
{4, "LOAD", xml_word, SQLCOM_DML},
{6, "DELETE", 0, SQLCOM_DML},
{6, "INSERT", 0, SQLCOM_DML},
{6, "UPDATE", 0, SQLCOM_DML},
{7, "HANDLER", 0, SQLCOM_DML},
{7, "REPLACE", 0, SQLCOM_DML},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword dcl_keywords[]=
{
{6, "CREATE", user_word, SQLCOM_DCL},
{6, "CREATE", or_replace_user_word, SQLCOM_DCL},
{4, "DROP", user_word, SQLCOM_DCL},
{6, "RENAME", user_word, SQLCOM_DCL},
{5, "GRANT", 0, SQLCOM_DCL},
{6, "REVOKE", 0, SQLCOM_DCL},
{3, "SET", password_word, SQLCOM_DCL},
{0, NULL, 0, SQLCOM_NOTHING}
};
struct sa_keyword passwd_keywords[]=
{
{3, "SET", password_word, SQLCOM_SET_OPTION},
{5, "ALTER", server_word, SQLCOM_ALTER_SERVER},
{5, "ALTER", user_word, SQLCOM_ALTER_USER},
{5, "GRANT", 0, SQLCOM_GRANT},
{6, "CREATE", user_word, SQLCOM_CREATE_USER},
{6, "CREATE", or_replace_user_word, SQLCOM_CREATE_USER},
{6, "CREATE", server_word, SQLCOM_CREATE_SERVER},
{6, "CREATE", or_replace_server_word, SQLCOM_CREATE_SERVER},
{6, "CHANGE", master_word, SQLCOM_CHANGE_MASTER},
{0, NULL, 0, SQLCOM_NOTHING}
};
#define MAX_KEYWORD 9
static void error_header()
{
struct tm tm_time;
@ -1107,6 +925,78 @@ static int get_user_host(const char *uh_line, unsigned int uh_len,
return 0;
}
static int sql_command_to_cmdtype(int sql_command)
{
switch (sql_command)
{
case SQLCOM_ALTER_DB:
case SQLCOM_ALTER_DB_UPGRADE:
case SQLCOM_ALTER_FUNCTION:
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_ALTER_TABLE:
case SQLCOM_CREATE_DB:
case SQLCOM_CREATE_INDEX:
case SQLCOM_CREATE_PACKAGE:
case SQLCOM_CREATE_PACKAGE_BODY:
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SEQUENCE:
case SQLCOM_CREATE_SPFUNCTION:
case SQLCOM_CREATE_TABLE:
case SQLCOM_CREATE_TRIGGER:
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_DB:
case SQLCOM_DROP_FUNCTION:
case SQLCOM_DROP_INDEX:
case SQLCOM_DROP_PACKAGE:
case SQLCOM_DROP_PACKAGE_BODY:
case SQLCOM_DROP_PROCEDURE:
case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
case SQLCOM_DROP_TRIGGER:
case SQLCOM_DROP_VIEW:
case SQLCOM_RENAME_TABLE:
case SQLCOM_TRUNCATE:
return EVENT_QUERY_DDL;
case SQLCOM_DO:
case SQLCOM_CALL:
case SQLCOM_LOAD:
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_INSERT:
case SQLCOM_INSERT_SELECT:
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
case SQLCOM_HA_OPEN:
case SQLCOM_HA_READ:
case SQLCOM_HA_CLOSE:
case SQLCOM_REPLACE:
case SQLCOM_REPLACE_SELECT:
return EVENT_QUERY_DML | EVENT_QUERY_DML_NO_SELECT;
case SQLCOM_SELECT:
return EVENT_QUERY_DML;
case SQLCOM_CREATE_USER:
case SQLCOM_CREATE_ROLE:
case SQLCOM_DROP_ROLE:
case SQLCOM_DROP_USER:
case SQLCOM_RENAME_USER:
case SQLCOM_GRANT:
case SQLCOM_GRANT_ROLE:
case SQLCOM_REVOKE:
case SQLCOM_REVOKE_ROLE:
case SQLCOM_REVOKE_ALL:
return EVENT_QUERY_DCL;
default:
return EVENT_QUERY_ALL;
};
}
#if defined(_WIN32) && !defined(S_ISDIR)
#define S_ISDIR(x) ((x) & _S_IFDIR)
#endif /*_WIN32 && !S_ISDIR*/
@ -1755,118 +1645,8 @@ static int do_log_user(const char *name, int len,
}
static int get_next_word(const char *query, char *word)
{
int len= 0;
char c;
while ((c= query[len]))
{
if (c >= 'a' && c <= 'z')
word[len]= 'A' + (c-'a');
else if (c >= 'A' && c <= 'Z')
word[len]= c;
else
break;
if (len++ == MAX_KEYWORD)
return 0;
}
word[len]= 0;
return len;
}
static int filter_query_type(const char *query, struct sa_keyword *kwd)
{
int qwe_in_list;
char fword[MAX_KEYWORD + 1], nword[MAX_KEYWORD + 1];
int len, nlen= 0;
const struct sa_keyword *l_keywords;
if (!query)
return SQLCOM_NOTHING;
while (*query && (is_space(*query) || *query == '(' || *query == '/'))
{
/* comment handling */
if (*query == '/' && query[1] == '*')
{
if (query[2] == '!')
{
query+= 3;
while (*query >= '0' && *query <= '9')
query++;
continue;
}
query+= 2;
while (*query)
{
if (*query=='*' && query[1] == '/')
{
query+= 2;
break;
}
query++;
}
continue;
}
query++;
}
qwe_in_list= SQLCOM_NOTHING;
if (!(len= get_next_word(query, fword)))
goto not_in_list;
query+= len+1;
l_keywords= kwd;
while (l_keywords->length)
{
if (l_keywords->length == len && strncmp(l_keywords->wd, fword, len) == 0)
{
if (l_keywords->next)
{
if (nlen == 0)
{
while (*query && is_space(*query))
query++;
nlen= get_next_word(query, nword);
}
if (filter_query_type(query, l_keywords->next) == SQLCOM_NOTHING)
goto do_loop;
}
qwe_in_list= l_keywords->type;
break;
};
do_loop:
l_keywords++;
}
not_in_list:
return qwe_in_list;
}
static const char *skip_set_statement(const char *query)
{
if (filter_query_type(query, keywords_to_skip))
{
char fword[MAX_KEYWORD + 1];
int len;
do
{
len= get_next_word(query, fword);
query+= len ? len : 1;
if (len == 3 && strncmp(fword, "FOR", 3) == 0)
break;
} while (*query);
if (*query == 0)
return 0;
}
return query;
}
static int log_statement_ex(const struct connection_info *cn,
time_t ev_time, unsigned long thd_id,
time_t ev_time, unsigned long thd_id, int sql_cmd,
const char *query, unsigned int query_len,
int error_code, const char *type, int take_lock)
{
@ -1881,6 +1661,7 @@ static int log_statement_ex(const struct connection_info *cn,
long long query_id;
int result;
char *big_buffer= NULL;
int cmdtype= sql_command_to_cmdtype(sql_cmd);
if ((db= cn->db))
db_length= cn->db_length;
@ -1907,30 +1688,14 @@ static int log_statement_ex(const struct connection_info *cn,
{
const char *orig_query= query;
if ((query= skip_set_statement(query)) == SQLCOM_NOTHING)
return 0;
if (events & EVENT_QUERY_DDL)
{
if (!filter_query_type(query, not_ddl_keywords) &&
filter_query_type(query, ddl_keywords))
goto do_log_query;
}
if (events & EVENT_QUERY_DML)
{
if (filter_query_type(query, dml_keywords))
goto do_log_query;
}
if (events & EVENT_QUERY_DML_NO_SELECT)
{
if (filter_query_type(query, dml_no_select_keywords))
goto do_log_query;
}
if (events & EVENT_QUERY_DCL)
{
if (filter_query_type(query, dcl_keywords))
goto do_log_query;
}
if (events & EVENT_QUERY_DDL && cmdtype & EVENT_QUERY_DDL)
goto do_log_query;
if (events & EVENT_QUERY_DML && cmdtype & EVENT_QUERY_DML)
goto do_log_query;
if (events & EVENT_QUERY_DML_NO_SELECT && cmdtype & EVENT_QUERY_DML_NO_SELECT)
goto do_log_query;
if (events & EVENT_QUERY_DCL && cmdtype & EVENT_QUERY_DCL)
goto do_log_query;
return 0;
do_log_query:
@ -1964,7 +1729,7 @@ do_log_query:
if (query_log_limit > 0 && uh_buffer_size > query_log_limit+2)
uh_buffer_size= query_log_limit+2;
switch (filter_query_type(skip_set_statement(query), passwd_keywords))
switch (sql_cmd)
{
case SQLCOM_GRANT:
case SQLCOM_CREATE_USER:
@ -1990,8 +1755,8 @@ do_log_query:
case SQLCOM_SET_OPTION:
csize+= escape_string_hide_passwords(query, query_len,
uh_buffer, uh_buffer_size,
NULL, 0, NULL, 0,
"=", 1, 0);
"PASSWORD", 8, "=", 1,
"PASSWORD", 8, '(');
break;
default:
csize+= escape_string(query, query_len,
@ -2011,7 +1776,7 @@ do_log_query:
static int log_statement(const struct connection_info *cn,
const struct mysql_event_general *event,
const char *type)
const char *type, int sql_command)
{
DBUG_PRINT("info", ("log_statement: event_subclass=%d, general_command=%.*s, "
"cn->query_id=%lld, cn->query=%.*s, event->query_id=%lld, "
@ -2024,7 +1789,8 @@ static int log_statement(const struct connection_info *cn,
event->query_id, event->general_query_length,
event->general_query, type));
return log_statement_ex(cn, event->general_time, event->general_thread_id,
event->general_query, event->general_query_length,
sql_command, event->general_query,
event->general_query_length,
event->general_error_code, type, 1);
}
@ -2340,7 +2106,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
event_query_command(event))
{
log_statement(cn, event, "QUERY");
log_statement(cn, event, "QUERY", thd_sql_command(thd));
cn->query_length= 0; /* So the log_current_query() won't log this again. */
cn->query_id= 0;
cn->log_always= 0;
@ -2879,7 +2645,8 @@ static void log_current_query(MYSQL_THD thd)
{
cn->log_always= 1;
log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),
cn->query, cn->query_length, 0, "QUERY", 0);
thd_sql_command(thd), cn->query, cn->query_length, 0,
"QUERY", 0);
cn->log_always= 0;
}
}

View file

@ -216,7 +216,7 @@ private:
Log_event *m_ev; // Used for Flashback
};
#ifndef DBUG_OFF
#if !defined DBUG_OFF && defined DBUG_TRACE
#define DBUG_DUMP_EVENT_BUF(B,L) \
do { \
const uchar *_buf=(uchar*)(B); \

View file

@ -100,7 +100,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
length is stored in little-endian format, since this is the
format used for the binlog.
*/
#ifndef DBUG_OFF
#if !defined DBUG_OFF && defined DBUG_TRACE
const uchar *old_pack_ptr= pack_ptr;
#endif
pack_ptr= field->pack(pack_ptr, field->ptr + offset,

View file

@ -269,6 +269,19 @@ public:
virtual const Class_info *get_class_info() const=0;
virtual uint32 get_data_size() const=0;
/*
The 'binary_valid' spatial object can be stored in the database
and be the correct argument to the spatial functions.
It can still be not valid by the OPENGIS standard like
having self-intersecting borders.
*/
bool is_binary_valid() const
{
uint32 data_size= get_data_size();
return (data_size == GET_SIZE_ERROR) ? false : !no_data(m_data, data_size);
}
virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
/* returns the length of the wkb that was read */
virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,

View file

@ -8266,12 +8266,23 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
int setup_returning_fields(THD* thd, TABLE_LIST* table_list)
{
GRANT_INFO *saved_grant;
int res= 0;
if (!thd->lex->has_returning())
return 0;
return setup_wild(thd, table_list, thd->lex->returning()->item_list, NULL,
thd->lex->returning(), true)
|| setup_fields(thd, Ref_ptr_array(), thd->lex->returning()->item_list,
MARK_COLUMNS_READ, NULL, NULL, 0, THD_WHERE::RETURNING);
saved_grant= &table_list->table->grant;
table_list->table->grant.want_privilege|= SELECT_ACL;
res= setup_wild(thd, table_list, thd->lex->returning()->item_list, NULL,
thd->lex->returning(), true)
|| setup_fields(thd, Ref_ptr_array(), thd->lex->returning()->item_list,
MARK_COLUMNS_READ, NULL, NULL, 0, THD_WHERE::RETURNING);
table_list->table->grant= *saved_grant;
return res;
}

View file

@ -20,104 +20,7 @@
#ifndef SQL_CMD_INCLUDED
#define SQL_CMD_INCLUDED
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st status_vars[]= {" ...
If the command returns a result set or is not allowed in stored
functions or triggers, please also make sure that
sp_get_flags_for_command (sp_head.cc) returns proper flags for the
added SQLCOM_.
*/
enum enum_sql_command {
SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX,
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_BINLOG_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_SHOW_TRIGGERS,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_CONTRIBUTORS,
SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
SQLCOM_SHOW_RELAYLOG_EVENTS,
SQLCOM_GET_DIAGNOSTICS,
SQLCOM_SLAVE_ALL_START, SQLCOM_SLAVE_ALL_STOP,
SQLCOM_SHOW_EXPLAIN,
SQLCOM_SHOW_ANALYZE, SQLCOM_SHUTDOWN,
SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE,
SQLCOM_COMPOUND,
SQLCOM_SHOW_GENERIC,
SQLCOM_ALTER_USER,
SQLCOM_SHOW_CREATE_USER,
SQLCOM_EXECUTE_IMMEDIATE,
SQLCOM_CREATE_SEQUENCE,
SQLCOM_DROP_SEQUENCE,
SQLCOM_ALTER_SEQUENCE,
SQLCOM_CREATE_PACKAGE,
SQLCOM_DROP_PACKAGE,
SQLCOM_CREATE_PACKAGE_BODY,
SQLCOM_DROP_PACKAGE_BODY,
SQLCOM_SHOW_CREATE_PACKAGE,
SQLCOM_SHOW_CREATE_PACKAGE_BODY,
SQLCOM_SHOW_STATUS_PACKAGE,
SQLCOM_SHOW_STATUS_PACKAGE_BODY,
SQLCOM_SHOW_PACKAGE_BODY_CODE,
SQLCOM_BACKUP, SQLCOM_BACKUP_LOCK,
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st com_status_vars[]= {" ...
*/
/* This should be the last !!! */
SQLCOM_END
};
#include "sql_command.h"
class Storage_engine_name
{

112
sql/sql_command.h Normal file
View file

@ -0,0 +1,112 @@
/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st status_vars[]= {" ...
If the command returns a result set or is not allowed in stored
functions or triggers, please also make sure that
sp_get_flags_for_command (sp_head.cc) returns proper flags for the
added SQLCOM_.
*/
enum enum_sql_command {
SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX,
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_BINLOG_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_SHOW_TRIGGERS,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_CONTRIBUTORS,
SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
SQLCOM_SHOW_RELAYLOG_EVENTS,
SQLCOM_GET_DIAGNOSTICS,
SQLCOM_SLAVE_ALL_START, SQLCOM_SLAVE_ALL_STOP,
SQLCOM_SHOW_EXPLAIN,
SQLCOM_SHOW_ANALYZE, SQLCOM_SHUTDOWN,
SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE,
SQLCOM_COMPOUND,
SQLCOM_SHOW_GENERIC,
SQLCOM_ALTER_USER,
SQLCOM_SHOW_CREATE_USER,
SQLCOM_EXECUTE_IMMEDIATE,
SQLCOM_CREATE_SEQUENCE,
SQLCOM_DROP_SEQUENCE,
SQLCOM_ALTER_SEQUENCE,
SQLCOM_CREATE_PACKAGE,
SQLCOM_DROP_PACKAGE,
SQLCOM_CREATE_PACKAGE_BODY,
SQLCOM_DROP_PACKAGE_BODY,
SQLCOM_SHOW_CREATE_PACKAGE,
SQLCOM_SHOW_CREATE_PACKAGE_BODY,
SQLCOM_SHOW_STATUS_PACKAGE,
SQLCOM_SHOW_STATUS_PACKAGE_BODY,
SQLCOM_SHOW_PACKAGE_BODY_CODE,
SQLCOM_BACKUP, SQLCOM_BACKUP_LOCK,
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st com_status_vars[]= {" ...
*/
/* This should be the last !!! */
SQLCOM_END
};

View file

@ -1607,6 +1607,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
NET *net= &thd->net;
bool error= 0;
bool do_end_of_statement= true;
bool log_slow_done= false;
DBUG_ENTER("dispatch_command");
DBUG_PRINT("info", ("command: %d %s", command,
(command_name[command].str != 0 ?
@ -1833,6 +1834,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
case COM_STMT_BULK_EXECUTE:
{
mysqld_stmt_bulk_execute(thd, packet, packet_length);
log_slow_done= true;
#ifdef WITH_WSREP
if (WSREP(thd))
{
@ -1844,6 +1846,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
case COM_STMT_EXECUTE:
{
mysqld_stmt_execute(thd, packet, packet_length);
log_slow_done= true;
#ifdef WITH_WSREP
if (WSREP(thd))
{
@ -2020,6 +2023,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
mysql_parse(thd, beginning_of_next_stmt, length, &parser_state);
}
log_slow_done= thd->lex->sql_command == SQLCOM_EXECUTE;
DBUG_PRINT("info",("query ready"));
break;
@ -2473,22 +2477,19 @@ resume:
if (likely(!thd->is_error() && !thd->killed_errno()))
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
thd->get_stmt_da()->is_error() ?
thd->get_stmt_da()->sql_errno() : 0,
command_name[command].str);
if (!log_slow_done)
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
thd->get_stmt_da()->is_error() ?
thd->get_stmt_da()->sql_errno() : 0,
command_name[command].str);
thd->update_all_stats();
/*
Write to slow query log only those statements that received via the text
protocol except the EXECUTE statement. The reason we do that way is
that for statements received via binary protocol and for the EXECUTE
statement, the slow statements have been already written to slow query log
inside the method Prepared_statement::execute().
for backward compatibility we only log COM_QUERY here,
as if COM_STMT_PREPARE or COM_FIELD_LIST couldn't be slow.
*/
if(command == COM_QUERY &&
thd->lex->sql_command != SQLCOM_EXECUTE)
if (command == COM_QUERY && !log_slow_done)
log_slow_statement(thd);
else
delete_explain_query(thd->lex);

View file

@ -5330,6 +5330,11 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
*/
cleanup_stmt(false);
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_STATUS,
thd->get_stmt_da()->is_error() ?
thd->get_stmt_da()->sql_errno() : 0,
command_name[thd->get_command()].str);
/*
Log the statement to slow query log if it passes filtering.
We do it here for prepared statements despite of the fact that the function

View file

@ -8147,6 +8147,12 @@ void Type_handler_string_result::Item_param_set_param_func(Item_param *param,
}
void Type_handler_null::Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const
{
}
void Type_handler_time_common::Item_param_set_param_func(Item_param *param,
uchar **pos,
ulong len) const

View file

@ -7000,6 +7000,8 @@ public:
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const override;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const override;
};

View file

@ -853,6 +853,12 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
wkb_type > (uint32) Geometry::wkb_last)
goto err;
const char *dummy;
Geometry_buffer buffer;
Geometry *geom= Geometry::construct(&buffer, from, uint32(length));
if (!geom || !geom->is_binary_valid())
goto err;
if (m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRY &&
m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRYCOLLECTION &&
(uint32) m_type_handler->geometry_type() != wkb_type)
@ -865,21 +871,14 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
if (!tab_name)
tab_name= "";
Geometry_buffer buffer;
Geometry *geom= NULL;
String wkt;
const char *dummy;
wkt.set_charset(&my_charset_latin1);
if (!(geom= Geometry::construct(&buffer, from, uint32(length))) ||
geom->as_wkt(&wkt, &dummy))
StringBuffer<STRING_BUFFER_USUAL_SIZE> wkt(&my_charset_latin1);
if (geom->as_wkt(&wkt, &dummy))
goto err;
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str,
wkt.c_ptr_safe(),
db, tab_name, field_name.str,
(ulong) table->in_use->get_stmt_da()->
current_row_for_warning());
wkt.c_ptr_safe(), db, tab_name, field_name.str,
(ulong) table->in_use->get_stmt_da()->current_row_for_warning());
goto err_exit;
}

View file

@ -3674,7 +3674,7 @@ buf_block_t*
buf_page_create(fil_space_t *space, uint32_t offset,
ulint zip_size, mtr_t *mtr, buf_block_t *free_block) noexcept
{
space->free_page(offset, false);
space->free_page<false>(offset);
return buf_page_create_low({space->id, offset}, zip_size, mtr, free_block);
}

View file

@ -2022,7 +2022,7 @@ static void fil_crypt_thread()
#endif /* UNIV_PFS_THREAD */
mysql_mutex_lock(&fil_crypt_threads_mutex);
rotate_thread_t thr(srv_n_fil_crypt_threads_started++);
pthread_cond_signal(&fil_crypt_cond); /* signal that we started */
pthread_cond_broadcast(&fil_crypt_cond);
if (!thr.should_shutdown()) {
/* if we find a tablespace that is starting, skip over it
@ -2094,7 +2094,7 @@ wait_for_work:
fil_crypt_return_iops(&thr);
srv_n_fil_crypt_threads_started--;
pthread_cond_signal(&fil_crypt_cond); /* signal that we stopped */
pthread_cond_broadcast(&fil_crypt_cond);
mysql_mutex_unlock(&fil_crypt_threads_mutex);
my_thread_end();

View file

@ -1673,8 +1673,7 @@ fseg_create(fil_space_t *space, ulint byte_offset, mtr_t *mtr, dberr_t *err,
{
fseg_inode_t* inode;
ib_id_t seg_id;
uint32_t n_reserved;
bool reserved_extent = false;
uint32_t n_reserved = 0;
DBUG_ENTER("fseg_create");
@ -1702,16 +1701,16 @@ inode_alloc:
if (!inode) {
block = nullptr;
reserve_extent:
if (!has_done_reservation && !reserved_extent) {
if (!has_done_reservation && !n_reserved) {
*err = fsp_reserve_free_extents(&n_reserved, space, 2,
FSP_NORMAL, mtr);
if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
DBUG_RETURN(nullptr);
}
ut_ad(n_reserved > 0);
/* Extents reserved successfully. So
try allocating the page or inode */
reserved_extent = true;
if (inode) {
goto page_alloc;
}
@ -1781,7 +1780,8 @@ page_alloc:
+ block->page.frame, space->id);
funct_exit:
if (!has_done_reservation && reserved_extent) {
if (n_reserved) {
ut_ad(!has_done_reservation);
space->release_free_extents(n_reserved);
}
@ -2165,8 +2165,6 @@ take_hinted_page:
buf_block_t* block = fsp_alloc_free_page(
space, hint, mtr, init_mtr, err);
ut_ad(block || !has_done_reservation || *err);
if (block) {
/* Put the page in the fragment page array of the
segment */
@ -2179,6 +2177,8 @@ take_hinted_page:
fseg_set_nth_frag_page_no(
seg_inode, iblock, n,
block->page.id().page_no(), mtr);
} else {
ut_ad(*err != DB_SUCCESS);
}
/* fsp_alloc_free_page() invoked fsp_init_file_page()

View file

@ -281,12 +281,15 @@ dberr_t flst_add_last(buf_block_t *base, uint16_t boffset,
return DB_CORRUPTION;
buf_block_t *cur= add;
dberr_t err;
if (addr.page != add->page.id().page_no() &&
!(cur= buf_page_get_gen(page_id_t{add->page.id().space(), addr.page},
add->zip_size(), RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr, &err)))
return err;
if (addr.page != add->page.id().page_no())
{
dberr_t err;
cur= buf_page_get_gen(page_id_t{add->page.id().space(), addr.page},
add->zip_size(), RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr, &err);
if (!cur)
return err;
}
return flst_insert_after(base, boffset, cur, addr.boffset,
add, aoffset, limit, mtr);
}
@ -382,16 +385,21 @@ dberr_t flst_remove(buf_block_t *base, uint16_t boffset,
prev_addr.page, prev_addr.boffset, mtr);
else
{
dberr_t err2;
if (next_addr.page == cur->page.id().page_no() ||
(cur= buf_page_get_gen(page_id_t(cur->page.id().space(),
next_addr.page),
cur->zip_size(), RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr, &err2)))
if (next_addr.page == cur->page.id().page_no())
write_addr:
flst_write_addr(*cur, cur->page.frame + next_addr.boffset + FLST_PREV,
prev_addr.page, prev_addr.boffset, mtr);
else if (err == DB_SUCCESS)
err= err2;
else
{
dberr_t err2;
cur= buf_page_get_gen(page_id_t(cur->page.id().space(), next_addr.page),
cur->zip_size(), RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr, &err2);
if (cur)
goto write_addr;
if (err == DB_SUCCESS)
err= err2;
}
}
byte *len= &base->page.frame[boffset + FLST_LEN];

View file

@ -6842,12 +6842,12 @@ wsrep_store_key_val_for_row(
wsrep_thd_query(thd));
true_len = buff_space;
}
memcpy(buff, normalized, true_len);
buff += true_len;
buff_space -= true_len;
} else {
buff += key_len;
}
memcpy(buff, normalized, true_len);
} else {
/* Here we handle all other data types except the
true VARCHAR, BLOB and TEXT. Note that the column

View file

@ -950,19 +950,16 @@ public:
@retval nullptr if the tablespace is missing or inaccessible */
static fil_space_t *get_for_write(uint32_t id) noexcept;
/** Add/remove the free page in the freed ranges list.
@param[in] offset page number to be added
@param[in] free true if page to be freed */
void free_page(uint32_t offset, bool add=true) noexcept
/** Add/remove a page in freed_ranges.
@tparam add true=add, false=remove
@param offset page number */
template<bool add=true> void free_page(uint32_t offset) noexcept
{
std::lock_guard<std::mutex> freed_lock(freed_range_mutex);
if (add)
return freed_ranges.add_value(offset);
if (freed_ranges.empty())
return;
return freed_ranges.remove_value(offset);
freed_ranges.add_value(offset);
else
freed_ranges.remove_value(offset);
}
/** Add the range of freed pages */

View file

@ -2278,8 +2278,13 @@ void store_freed_or_init_rec(page_id_t page_id, bool freed) noexcept
uint32_t page_no= page_id.page_no();
if (space_id == TRX_SYS_SPACE || srv_is_undo_tablespace(space_id))
{
if (srv_immediate_scrub_data_uncompressed)
fil_space_get(space_id)->free_page(page_no, freed);
if (!srv_immediate_scrub_data_uncompressed)
return;
fil_space_t *space= fil_space_get(space_id);
if (freed)
space->free_page<true>(page_no);
else
space->free_page<false>(page_no);
return;
}

View file

@ -2806,10 +2806,10 @@ process_next_block:
ut_ad(0);
goto unexpected_eof;
} else {
memcpy(index->online_log->head.buf, mrec,
ulint(mrec_end - mrec));
mrec_end -= ulint(mrec - index->online_log->head.buf);
const size_t s = size_t(mrec_end - mrec);
memcpy(index->online_log->head.buf, mrec, s);
mrec = index->online_log->head.buf;
mrec_end = mrec + s;
goto process_next_block;
}
}
@ -3698,10 +3698,10 @@ process_next_block:
ut_ad(0);
goto unexpected_eof;
} else {
memcpy(index->online_log->head.buf, mrec,
ulint(mrec_end - mrec));
mrec_end -= ulint(mrec - index->online_log->head.buf);
const size_t s = size_t(mrec_end - mrec);
memcpy(index->online_log->head.buf, mrec, s);
mrec = index->online_log->head.buf;
mrec_end = mrec + s;
goto process_next_block;
}
}

View file

@ -0,0 +1 @@
# see .opt file

View file

@ -0,0 +1 @@
--loose_spider_disable_group_by_handler=0

View file

@ -0,0 +1,28 @@
install plugin spider soname 'ha_spider';
#
# MDEV-38368 Spider crash on fake loop detection variables
#
set global spider_same_server_link=1;
create server srv1
foreign data wrapper mysql
options (
host 'localhost',
user 'root',
socket '$MASTER_1_MYSOCK'
);
create table t1 (id int primary key, data varchar(255));
insert into t1 values (1, 'test'), (2, 'data');
create table st1 (id int primary key, data varchar(255)) engine=spider
comment='wrapper "mysql", srv "srv1", table "t1"';
set @`spider_lc_./test/st1` = concat('-', repeat('x', 900000), '-pid-tbl-');
select * from st1 limit 1;
id data
1 test
drop table st1, t1;
drop server srv1;
uninstall plugin spider;
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown
drop tables mysql.spider_link_failed_log, mysql.spider_link_mon_servers, mysql.spider_tables, mysql.spider_table_crd, mysql.spider_table_position_for_recovery, mysql.spider_table_sts, mysql.spider_xa, mysql.spider_xa_failed_log, mysql.spider_xa_member;
truncate mysql.func;
# End of 10.6 tests

View file

@ -0,0 +1,36 @@
# group by hander doesn't matter here, let's not run this test twice
source include/have_group_by_handler.inc;
install plugin spider soname 'ha_spider';
--echo #
--echo # MDEV-38368 Spider crash on fake loop detection variables
--echo #
set global spider_same_server_link=1;
evalp create server srv1
foreign data wrapper mysql
options (
host 'localhost',
user 'root',
socket '$MASTER_1_MYSOCK'
);
create table t1 (id int primary key, data varchar(255));
insert into t1 values (1, 'test'), (2, 'data');
create table st1 (id int primary key, data varchar(255)) engine=spider
comment='wrapper "mysql", srv "srv1", table "t1"';
set @`spider_lc_./test/st1` = concat('-', repeat('x', 900000), '-pid-tbl-');
select * from st1 limit 1;
drop table st1, t1;
drop server srv1;
uninstall plugin spider;
drop tables mysql.spider_link_failed_log, mysql.spider_link_mon_servers, mysql.spider_tables, mysql.spider_table_crd, mysql.spider_table_position_for_recovery, mysql.spider_table_sts, mysql.spider_xa, mysql.spider_xa_failed_log, mysql.spider_xa_member;
truncate mysql.func;
--echo # End of 10.6 tests

View file

@ -1236,7 +1236,7 @@ int spider_conn_queue_loop_check(
*/
lex_str.length = top_share->path.length + SPIDER_SQL_LOP_CHK_PRM_PRF_LEN;
buf_sz = lex_str.length + 2;
loop_check_buf = (char *) my_alloca(buf_sz);
loop_check_buf = (char *) my_safe_alloca(buf_sz);
if (unlikely(!loop_check_buf))
{
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@ -1303,7 +1303,7 @@ int spider_conn_queue_loop_check(
from_str.length = tmp_name - lex_str.str + 1;
}
}
my_afree(loop_check_buf);
my_safe_afree(loop_check_buf, buf_sz);
/*
construct loop_check_buf as <from_str>-<cur>-<to_str> e.g.
"-<mac>-<pid>-./test/t0--./test/t1-./test/t2", later used as
@ -1319,7 +1319,7 @@ int spider_conn_queue_loop_check(
to_str.str = path;
DBUG_PRINT("info", ("spider to=%s", to_str.str));
buf_sz = from_str.length + top_share->path.length + to_str.length + 3;
loop_check_buf = (char *) my_alloca(buf_sz);
loop_check_buf = (char *) my_safe_alloca(buf_sz);
if (unlikely(!loop_check_buf))
{
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@ -1370,7 +1370,7 @@ int spider_conn_queue_loop_check(
lex_str.length + 2),
NullS)
)) {
my_afree(loop_check_buf);
my_safe_afree(loop_check_buf, buf_sz);
goto error_alloc_loop_check;
}
lcptr->flag = 0;
@ -1399,7 +1399,7 @@ int spider_conn_queue_loop_check(
*/
if (unlikely(my_hash_insert(&conn->loop_checked, (uchar *) lcptr)))
{
my_afree(loop_check_buf);
my_safe_afree(loop_check_buf, buf_sz);
goto error_hash_insert;
}
} else {
@ -1410,11 +1410,11 @@ int spider_conn_queue_loop_check(
lcptr->flag |= SPIDER_LOP_CHK_IGNORED;
}
pthread_mutex_unlock(&conn->loop_check_mutex);
my_afree(loop_check_buf);
my_safe_afree(loop_check_buf, buf_sz);
DBUG_PRINT("info", ("spider be sent or queued already"));
DBUG_RETURN(0);
}
my_afree(loop_check_buf);
my_safe_afree(loop_check_buf, buf_sz);
if ((error_num = spider_conn_queue_and_merge_loop_check(conn, lcptr)))
{

View file

@ -22956,7 +22956,42 @@ static void test_cache_metadata()
mysql_stmt_close(stmt);
}
void test_mdev_10075()
static void test_mdev_38242()
{
MYSQL_STMT *stmt;
int rc;
MYSQL_BIND param[2];
int val1=117440769, val2;
my_bool null1=0, null2=1;
myheader("test_mdev_38242");
stmt= mysql_stmt_init(mysql);
check_stmt(stmt);
rc= mysql_stmt_prepare(stmt, STRING_WITH_LEN("SELECT 1 WHERE ?=0 AND ?=0"));
check_execute(stmt, rc);
bzero(param, sizeof(param));
param[0].buffer= &val1;
param[0].buffer_type= MYSQL_TYPE_LONG;
param[0].is_null= &null1;
param[1].buffer= &val2;
param[1].buffer_type= MYSQL_TYPE_LONG;
param[1].is_null= &null2;
rc= mysql_stmt_bind_param(stmt, param);
check_execute(stmt, rc);
stmt->send_types_to_server= 0;
rc= mysql_stmt_execute(stmt);
check_execute_r(stmt, rc);
mysql_stmt_close(stmt);
}
static void test_mdev_10075()
{
MYSQL_STMT *stmt;
int rc;
@ -23405,6 +23440,7 @@ static struct my_tests_st my_tests[]= {
{ "test_connect_autocommit", test_connect_autocommit},
{ "test_execute_direct", test_execute_direct },
{ "test_cache_metadata", test_cache_metadata},
{ "test_mdev_38242", test_mdev_38242 },
#ifndef EMBEDDED_LIBRARY
{ "test_mdev_24411", test_mdev_24411},
{ "test_mdev_34718_bu", test_mdev_34718_bu },