Commit afccd4af authored by marko's avatar marko

branches/zip: INFORMATION_SCHEMA.INNODB_LOCKS: Quote lock_table, lock_index.

innodb_information_schema.test. Add tests that display most columns from
INFORMATION_SCHEMA.INNODB_LOCKS.  Test that quoting of table names works
and respects SQL_MODE='ANSI_QUOTES'.

innobase_print_identifier(): Remove.

innobase_convert_identifier(): New function,
based on innobase_print_identifier().

innobase_convert_name(): New function, similar to ut_print_namel(), but
using a memory buffer.

ut_print_namel(): Use innobase_convert_name().

fill_innodb_locks_from_cache(): Convert lock_table and lock_index by
calling innobase_convert_name().
parent 3e2b5b65
......@@ -1249,69 +1249,145 @@ innobase_invalidate_query_cache(
}
/*********************************************************************
Display an SQL identifier. */
extern "C"
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen)/* in: length of name */
{
const char* s = name;
char* qname = NULL;
Convert an SQL identifier to the MySQL system_charset_info (UTF-8)
and quote it if needed. */
static
char*
innobase_convert_identifier(
/*========================*/
/* out: pointer to the end of buf */
char* buf, /* out: buffer for converted identifier */
ulint buflen, /* in: length of buf, in bytes */
const char* id, /* in: identifier to convert */
ulint idlen, /* in: length of id, in bytes */
void* thd, /* in: MySQL connection thread, or NULL */
ibool file_id)/* in: TRUE=id is a table or database name;
FALSE=id is an UTF-8 string */
{
char nz[NAME_LEN + 1];
char nz2[NAME_LEN + 1 + sizeof srv_mysql50_table_name_prefix];
const char* s = id;
int q;
if (table_id) {
if (file_id) {
/* Decode the table name. The filename_to_tablename()
function expects a NUL-terminated string. The input and
output strings buffers must not be shared. The function
only produces more output when the name contains other
characters than [0-9A-Z_a-z]. */
char* temp_name = (char*) my_malloc((uint) namelen + 1, MYF(MY_WME));
uint qnamelen = (uint) (namelen
+ (1 + sizeof srv_mysql50_table_name_prefix));
if (temp_name) {
qname = (char*) my_malloc(qnamelen, MYF(MY_WME));
if (qname) {
memcpy(temp_name, name, namelen);
temp_name[namelen] = 0;
s = qname;
namelen = filename_to_tablename(temp_name,
qname, qnamelen);
}
my_free(temp_name, MYF(0));
output strings buffers must not be shared. */
if (UNIV_UNLIKELY(idlen > (sizeof nz) - 1)) {
idlen = (sizeof nz) - 1;
}
}
if (!trx || !trx->mysql_thd) {
memcpy(nz, id, idlen);
nz[idlen] = 0;
s = nz2;
idlen = filename_to_tablename(nz, nz2, sizeof nz2);
}
/* See if the identifier needs to be quoted. */
if (UNIV_UNLIKELY(!thd)) {
q = '"';
} else {
q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
s, (int) namelen);
q = get_quote_char_for_identifier((THD*) thd, s, (int) idlen);
}
if (q == EOF) {
fwrite(s, 1, namelen, f);
} else {
const char* e = s + namelen;
putc(q, f);
while (s < e) {
int c = *s++;
if (c == q) {
putc(c, f);
if (UNIV_UNLIKELY(idlen > buflen)) {
idlen = buflen;
}
memcpy(buf, s, idlen);
return(buf + idlen);
}
/* Quote the identifier. */
if (buflen < 2) {
return(buf);
}
*buf++ = q;
buflen--;
for (; idlen; idlen--) {
int c = *s++;
if (UNIV_UNLIKELY(c == q)) {
if (UNIV_UNLIKELY(buflen < 3)) {
break;
}
putc(c, f);
*buf++ = c;
*buf++ = c;
buflen -= 2;
} else {
if (UNIV_UNLIKELY(buflen < 2)) {
break;
}
*buf++ = c;
buflen--;
}
}
*buf++ = q;
return(buf);
}
/*********************************************************************
Convert a table or index name to the MySQL system_charset_info (UTF-8)
and quote it if needed. */
extern "C"
char*
innobase_convert_name(
/*==================*/
/* out: pointer to the end of buf */
char* buf, /* out: buffer for converted identifier */
ulint buflen, /* in: length of buf, in bytes */
const char* id, /* in: identifier to convert */
ulint idlen, /* in: length of id, in bytes */
void* thd, /* in: MySQL connection thread, or NULL */
ibool table_id)/* in: TRUE=id is a table or database name;
FALSE=id is an index name */
{
char* s = buf;
const char* bufend = buf + buflen;
if (table_id) {
const char* slash = (const char*) memchr(id, '/', idlen);
if (!slash) {
goto no_db_name;
}
putc(q, f);
/* Print the database name and table name separately. */
s = innobase_convert_identifier(s, bufend - s, id, slash - id,
thd, TRUE);
if (UNIV_LIKELY(s < bufend)) {
*s++ = '.';
s = innobase_convert_identifier(s, bufend - s,
slash + 1, idlen
- (slash - id) - 1,
thd, TRUE);
}
} else if (UNIV_UNLIKELY(*id == TEMP_INDEX_PREFIX)) {
/* Temporary index name (smart ALTER TABLE) */
const char temp_index_suffix[]= "--temporary--";
s = innobase_convert_identifier(buf, buflen, id + 1, idlen - 1,
thd, FALSE);
if (s - buf + (sizeof temp_index_suffix - 1) < buflen) {
memcpy(s, temp_index_suffix,
sizeof temp_index_suffix - 1);
s += sizeof temp_index_suffix - 1;
}
} else {
no_db_name:
s = innobase_convert_identifier(buf, buflen, id, idlen,
thd, table_id);
}
my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
return(s);
}
/**************************************************************************
......
......@@ -23,6 +23,7 @@ extern "C" {
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
#include "buf0buddy.h" /* for i_s_zip */
#include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
#include "ha_prototypes.h" /* for innobase_convert_name() */
}
static const char plugin_author[] = "Innobase Oy";
......@@ -513,8 +514,7 @@ fill_innodb_locks_from_cache(
/*=========================*/
/* out: 0 on success */
trx_i_s_cache_t* cache, /* in: cache to read from */
THD* thd, /* in: used to call
schema_table_store_record() */
THD* thd, /* in: MySQL client connection */
TABLE* table) /* in/out: fill this table */
{
Field** fields;
......@@ -532,6 +532,10 @@ fill_innodb_locks_from_cache(
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
/* 2 * NAME_LEN for database and table name,
and some slack for the #mysql50# prefix and quotes */
char buf[3 * NAME_LEN];
const char* bufend;
row = (i_s_locks_row_t*)
trx_i_s_cache_get_nth_row(
......@@ -554,12 +558,20 @@ fill_innodb_locks_from_cache(
row->lock_type));
/* lock_table */
OK(field_store_string(fields[IDX_LOCK_TABLE],
row->lock_table));
bufend = innobase_convert_name(buf, sizeof buf,
row->lock_table,
strlen(row->lock_table),
thd, TRUE);
OK(fields[IDX_LOCK_TABLE]->store(buf, bufend - buf,
system_charset_info));
/* lock_index */
OK(field_store_string(fields[IDX_LOCK_INDEX],
row->lock_index));
bufend = innobase_convert_name(buf, sizeof buf,
row->lock_index,
strlen(row->lock_index),
thd, FALSE);
OK(fields[IDX_LOCK_INDEX]->store(buf, bufend - buf,
system_charset_info));
/* lock_space */
OK(field_store_ulint(fields[IDX_LOCK_SPACE],
......
......@@ -25,17 +25,20 @@ innobase_convert_string(
uint* errors);
/*********************************************************************
Display an SQL identifier. */
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen);/* in: length of name */
Convert a table or index name to the MySQL system_charset_info (UTF-8)
and quote it if needed. */
char*
innobase_convert_name(
/*==================*/
/* out: pointer to the end of buf */
char* buf, /* out: buffer for converted identifier */
ulint buflen, /* in: length of buf, in bytes */
const char* id, /* in: identifier to convert */
ulint idlen, /* in: length of id, in bytes */
void* thd, /* in: MySQL connection thread, or NULL */
ibool table_id);/* in: TRUE=id is a table or database name;
FALSE=id is an index name */
/**********************************************************************
Returns true if the thread is the replication thread on the slave
......
lock_data
'1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
'1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
'2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
'2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
'3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
'3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
'4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
'4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
-128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
-128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
supremum pseudo-record
supremum pseudo-record
lock_mode lock_type lock_table lock_index lock_rec lock_data
X RECORD `test`.```t'\"_str` NULL 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
X RECORD `test`.```t'\"_str` NULL 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
X RECORD `test`.```t'\"_str` NULL 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
X RECORD `test`.```t'\"_str` NULL 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
X RECORD `test`.```t'\"_str` NULL 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
X RECORD `test`.```t'\"_str` NULL 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
X RECORD `test`.```t'\"_str` NULL 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
X RECORD `test`.```t'\"_str` NULL 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
X RECORD `test`.`t_min` NULL 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
X RECORD `test`.`t_min` NULL 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
X RECORD `test`.`t_max` NULL 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
X RECORD `test`.`t_max` NULL 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
X RECORD `test`.```t'\"_str` NULL 1 supremum pseudo-record
X RECORD `test`.```t'\"_str` NULL 1 supremum pseudo-record
lock_table COUNT(*)
`test`.`t_max` 2
`test`.`t_min` 2
`test`.```t'\"_str` 10
lock_table COUNT(*)
"test"."t_max" 2
"test"."t_min" 2
"test"."`t'\""_str" 10
......@@ -45,7 +45,7 @@ INSERT INTO t_max VALUES
2147483647, 4294967295,
9223372036854775807, 18446744073709551615);
CREATE TABLE t_str (
CREATE TABLE ```t'\"_str` (
c1 VARCHAR(32),
c2 VARCHAR(32),
c3 VARCHAR(32),
......@@ -55,13 +55,13 @@ CREATE TABLE t_str (
c7 VARCHAR(32),
PRIMARY KEY(c1, c2, c3, c4, c5, c6, c7)
);
INSERT INTO t_str VALUES
INSERT INTO ```t'\"_str` VALUES
('1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc''''');
INSERT INTO t_str VALUES
INSERT INTO ```t'\"_str` VALUES
('2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""');
INSERT INTO t_str VALUES
INSERT INTO ```t'\"_str` VALUES
('3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\');
INSERT INTO t_str VALUES
INSERT INTO ```t'\"_str` VALUES
('4', 'abc', 0x00616263, 0x61626300, 0x61006263, 0x6100626300, 0x610062630000);
-- connect (con_lock,localhost,root,,)
......@@ -78,7 +78,7 @@ INSERT INTO t_str VALUES
SET autocommit=0;
SELECT * FROM t_min FOR UPDATE;
SELECT * FROM t_max FOR UPDATE;
SELECT * FROM t_str FOR UPDATE;
SELECT * FROM ```t'\"_str` FOR UPDATE;
-- connection con_min_trylock
-- send
......@@ -90,24 +90,24 @@ SELECT * FROM t_max FOR UPDATE;
-- connection con_str_insert_supremum
-- send
INSERT INTO t_str VALUES
INSERT INTO ```t'\"_str` VALUES
('z', 'z', 'z', 'z', 'z', 'z', 'z');
-- connection con_str_lock_row1
-- send
SELECT * FROM t_str WHERE c1 = '1' FOR UPDATE;
SELECT * FROM ```t'\"_str` WHERE c1 = '1' FOR UPDATE;
-- connection con_str_lock_row2
-- send
SELECT * FROM t_str WHERE c1 = '2' FOR UPDATE;
SELECT * FROM ```t'\"_str` WHERE c1 = '2' FOR UPDATE;
-- connection con_str_lock_row3
-- send
SELECT * FROM t_str WHERE c1 = '3' FOR UPDATE;
SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE;
-- connection con_str_lock_row4
-- send
SELECT * FROM t_str WHERE c1 = '4' FOR UPDATE;
SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE;
# Give time to the above 2 queries to execute before continuing.
# Without this sleep it sometimes happens that the SELECT from innodb_locks
......@@ -117,7 +117,17 @@ SELECT * FROM t_str WHERE c1 = '4' FOR UPDATE;
-- enable_result_log
-- connection con_verify_innodb_locks
SELECT lock_data FROM INFORMATION_SCHEMA.innodb_locks ORDER BY lock_data;
SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data
FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data;
SELECT lock_table,COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS
GROUP BY lock_table;
set @save_sql_mode = @@sql_mode;
SET SQL_MODE='ANSI_QUOTES';
SELECT lock_table,COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS
GROUP BY lock_table;
SET @@sql_mode=@save_sql_mode;
-- disable_result_log
-- connection default
......@@ -132,4 +142,4 @@ SELECT lock_data FROM INFORMATION_SCHEMA.innodb_locks ORDER BY lock_data;
-- disconnect con_str_lock_row4
-- disconnect con_verify_innodb_locks
DROP TABLE t_min, t_max, t_str;
DROP TABLE t_min, t_max, ```t'\"_str`;
......@@ -18,6 +18,9 @@ Created 5/11/1994 Heikki Tuuri
#include "trx0trx.h"
#include "ha_prototypes.h"
#ifndef UNIV_HOTBACKUP
# include "mysql_com.h" /* NAME_LEN */
#endif /* UNIV_HOTBACKUP */
ibool ut_always_false = FALSE;
......@@ -465,27 +468,17 @@ ut_print_namel(
#ifdef UNIV_HOTBACKUP
fwrite(name, 1, namelen, f);
#else
if (table_id) {
char* slash = memchr(name, '/', namelen);
if (!slash) {
/* 2 * NAME_LEN for database and table name,
and some slack for the #mysql50# prefix and quotes */
char buf[3 * NAME_LEN];
const char* bufend;
goto no_db_name;
}
bufend = innobase_convert_name(buf, sizeof buf,
name, namelen,
trx ? trx->mysql_thd : NULL,
table_id);
/* Print the database name and table name separately. */
innobase_print_identifier(f, trx, TRUE, name, slash - name);
putc('.', f);
innobase_print_identifier(f, trx, TRUE, slash + 1,
namelen - (slash - name) - 1);
} else if (UNIV_UNLIKELY(*name == TEMP_INDEX_PREFIX)) {
/* Temporary index */
innobase_print_identifier(f, trx, table_id, name + 1,
namelen - 1);
fputs("--temporary--", f);
} else {
no_db_name:
innobase_print_identifier(f, trx, table_id, name, namelen);
}
fwrite(buf, 1, bufend - buf, f);
#endif
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment