Skip to content

Commit ce95a09

Browse files
lthjtolmer
authored andcommitted
Fix row count for audit plugin
Summary: The audit plugin implementation MySQL is reusing a variable that does not always reflect rows sent to client. This means that that in many cases, it is not counting the actual rows sent to the client. There is a more accurate count on the THD object that should be used instead. I am ignoring the documentation so that it just returns the number of rows returned the client: (https://dev.mysql.com/doc/refman/5.5/en/writing-audit-plugins.html) I am also adding new fields that will be passed into the audit plugin. This includes, number of affected rows, the connection certificate, and query attributes. Query attributes and connection certificates are currently not implemented, but will come shortly. If the distinction between commands that return no results, and commands that return empty results is important, then look at affected rows. For commands that return no results, affected rows is non-negative. For SELECTs that return empty results, affected rows is -1. Test Plan: Tested manually in gdb with SELECT/INSERT/UPDATE/DELETE queries: create table t (i int); select * from t; result rows: 0 affect rows: -1 insert into t values (1), (2); result rows: 0 affect rows: 2 update t set i = 3 where i = 2; result rows: 0 affect rows: 1 select * from t; result rows: 2 affect rows: -1 delete from t; result rows: 0 affect rows: 2 Reviewers: jtolmer, tianx Reviewed By: tianx Subscribers: webscalesql-eng Differential Revision: https://reviews.facebook.net/D49329
1 parent dea28af commit ce95a09

File tree

4 files changed

+68
-16
lines changed

4 files changed

+68
-16
lines changed

include/mysql/plugin_audit.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#define MYSQL_AUDIT_CLASS_MASK_SIZE 1
2727

28-
#define MYSQL_AUDIT_INTERFACE_VERSION 0x0302
28+
#define MYSQL_AUDIT_INTERFACE_VERSION 0x0303
2929

3030

3131
/*************************************************************************
@@ -67,6 +67,12 @@ struct mysql_event_general
6767
long long query_id;
6868
const char *database;
6969
unsigned int database_length;
70+
/* Added in version 0x303 */
71+
unsigned long long affected_rows;
72+
const char *connection_certificate;
73+
unsigned int connection_certificate_length;
74+
const char *query_attributes;
75+
unsigned int query_attributes_length;
7076
};
7177

7278

include/mysql/plugin_audit.h.pp

+5
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@
286286
long long query_id;
287287
const char *database;
288288
unsigned int database_length;
289+
unsigned long long affected_rows;
290+
const char *connection_certificate;
291+
unsigned int connection_certificate_length;
292+
const char *query_attributes;
293+
unsigned int query_attributes_length;
289294
};
290295
struct mysql_event_connection
291296
{

sql/sql_audit.cc

+5
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,17 @@ static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
8383
event.general_query_length= va_arg(ap, unsigned int);
8484
event.general_charset= va_arg(ap, struct charset_info_st *);
8585
event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
86+
event.affected_rows= (long long) va_arg(ap, longlong);
8687
event.general_sql_command= va_arg(ap, MYSQL_LEX_STRING);
8788
event.general_host= va_arg(ap, MYSQL_LEX_STRING);
8889
event.general_external_user= va_arg(ap, MYSQL_LEX_STRING);
8990
event.general_ip= va_arg(ap, MYSQL_LEX_STRING);
9091
event.database= va_arg(ap, const char *);
9192
event.database_length= va_arg(ap, unsigned int);
93+
event.connection_certificate= va_arg(ap, const char*);
94+
event.connection_certificate_length= va_arg(ap, unsigned int);
95+
event.query_attributes= va_arg(ap, const char*);
96+
event.query_attributes_length= va_arg(ap, unsigned int);
9297
event.query_id= (unsigned long long) thd->query_id;
9398
event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
9499
}

sql/sql_audit.h

+51-15
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,18 @@ void mysql_audit_general_log(THD *thd, const char *cmd, uint cmdlen,
7575
MYSQL_LEX_STRING sql_command, ip, host, external_user;
7676
MYSQL_LEX_STRING query={ (char *)query_str, query_len };
7777
static MYSQL_LEX_STRING empty= { C_STRING_WITH_LEN("") };
78-
ha_rows rows= 0;
78+
ha_rows resultrows= 0;
79+
longlong affectrows= 0;
7980
int error_code= 0;
8081
char user_buff[MAX_USER_HOST_SIZE + 1];
81-
const char *user= user_buff;
82-
uint userlen= make_user_name(thd, user_buff);
82+
uint userlen, databaselen, certlen, queryattrlen;
83+
const char *user, *database, *cert, *queryattr;
8384
time_t time= (time_t) thd->start_time.tv_sec;
84-
size_t databaselen;
85-
const char *database;
8685

8786
if (thd)
8887
{
88+
user= user_buff;
89+
userlen= make_user_name(thd, user_buff);
8990
if (!query_len)
9091
{
9192
/* no query specified, fetch from THD */
@@ -112,23 +113,34 @@ void mysql_audit_general_log(THD *thd, const char *cmd, uint cmdlen,
112113
sql_command.length= sql_statement_names[thd->lex->sql_command].length;
113114
database= thd->db;
114115
databaselen= thd->db_length;
116+
cert= 0;
117+
certlen= 0;
118+
queryattr= 0;
119+
queryattrlen= 0;
115120
}
116121
else
117122
{
123+
user= 0;
124+
userlen= 0;
118125
ip= empty;
119126
host= empty;
120127
external_user= empty;
121128
sql_command= empty;
122129
database= 0;
123130
databaselen= 0;
131+
cert= 0;
132+
certlen= 0;
133+
queryattr= 0;
134+
queryattrlen= 0;
124135
}
125136
const CHARSET_INFO *clientcs= thd ? thd->variables.character_set_client
126137
: global_system_variables.character_set_client;
127138

128139
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG,
129140
error_code, time, user, userlen, cmd, cmdlen, query.str,
130-
query.length, clientcs, rows, sql_command, host,
131-
external_user, ip, database, databaselen);
141+
query.length, clientcs, resultrows, affectrows,
142+
sql_command, host, external_user, ip, database,
143+
databaselen, cert, certlen, queryattr, queryattrlen);
132144
}
133145
#endif
134146
}
@@ -155,12 +167,17 @@ void mysql_audit_general(THD *thd, uint event_subtype,
155167
{
156168
time_t time= my_time(0);
157169
uint msglen= msg ? strlen(msg) : 0;
158-
uint userlen, databaselen;
159-
const char *user, *database;
170+
uint userlen, databaselen, certlen, queryattrlen;
171+
const char *user, *database, *cert, *queryattr;
160172
char user_buff[MAX_USER_HOST_SIZE];
161173
CSET_STRING query;
162174
MYSQL_LEX_STRING ip, host, external_user, sql_command;
163-
ha_rows rows;
175+
// Result rows will hold the number of rows sent to the client.
176+
ha_rows resultrows;
177+
// Affected rows will hold the number of modified rows for DML statements.
178+
// For SELECT statements, it is -1. For other statements, it is 0. See
179+
// THD::get_row_count_func for details.
180+
longlong affectrows;
164181
static MYSQL_LEX_STRING empty= { C_STRING_WITH_LEN("") };
165182

166183

@@ -176,7 +193,16 @@ void mysql_audit_general(THD *thd, uint event_subtype,
176193
query= thd->query_string;
177194
user= user_buff;
178195
userlen= make_user_name(thd, user_buff);
179-
rows= thd->get_stmt_da()->current_row_for_warning();
196+
if (event_subtype == MYSQL_AUDIT_GENERAL_STATUS)
197+
{
198+
affectrows= 0;
199+
resultrows= 0;
200+
}
201+
else
202+
{
203+
affectrows= thd->get_row_count_func();
204+
resultrows= thd->get_sent_row_count();
205+
}
180206
ip.str= (char *) thd->security_ctx->get_ip()->ptr();
181207
ip.length= thd->security_ctx->get_ip()->length();
182208
host.str= (char *) thd->security_ctx->get_host()->ptr();
@@ -187,6 +213,10 @@ void mysql_audit_general(THD *thd, uint event_subtype,
187213
sql_command.length= sql_statement_names[thd->lex->sql_command].length;
188214
database= thd->db;
189215
databaselen= thd->db_length;
216+
cert= 0;
217+
certlen= 0;
218+
queryattr= 0;
219+
queryattrlen= 0;
190220
}
191221
else
192222
{
@@ -196,16 +226,22 @@ void mysql_audit_general(THD *thd, uint event_subtype,
196226
host= empty;
197227
external_user= empty;
198228
sql_command= empty;
199-
rows= 0;
229+
resultrows= 0;
230+
affectrows= 0;
200231
database= 0;
201232
databaselen= 0;
233+
cert= 0;
234+
certlen= 0;
235+
queryattr= 0;
236+
queryattrlen= 0;
202237
}
203238

204239
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype,
205240
error_code, time, user, userlen, msg, msglen,
206-
query.str(), query.length(), query.charset(), rows,
207-
sql_command, host, external_user, ip, database,
208-
databaselen);
241+
query.str(), query.length(), query.charset(),
242+
resultrows, affectrows, sql_command, host,
243+
external_user, ip, database, databaselen,
244+
cert, certlen, queryattr, queryattrlen);
209245
}
210246
#endif
211247
}

0 commit comments

Comments
 (0)