Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
fac0e0e0
Commit
fac0e0e0
authored
May 21, 2011
by
Dmitry Shulga
Browse files
Options
Browse Files
Download
Plain Diff
Manual merge of patch for Bug#11749345 (formerly known as bug#38813)
from 5.1->5.5.
parents
a91d168d
733893ba
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
188 additions
and
158 deletions
+188
-158
sql/sql_show.cc
sql/sql_show.cc
+188
-158
No files found.
sql/sql_show.cc
View file @
fac0e0e0
...
@@ -2407,12 +2407,11 @@ bool schema_table_store_record(THD *thd, TABLE *table)
...
@@ -2407,12 +2407,11 @@ bool schema_table_store_record(THD *thd, TABLE *table)
}
}
int
make_table_list
(
THD
*
thd
,
SELECT_LEX
*
sel
,
static
int
make_table_list
(
THD
*
thd
,
SELECT_LEX
*
sel
,
LEX_STRING
*
db_name
,
LEX_STRING
*
table_name
)
LEX_STRING
*
db_name
,
LEX_STRING
*
table_name
)
{
{
Table_ident
*
table_ident
;
Table_ident
*
table_ident
;
table_ident
=
new
Table_ident
(
thd
,
*
db_name
,
*
table_name
,
1
);
table_ident
=
new
Table_ident
(
thd
,
*
db_name
,
*
table_name
,
1
);
sel
->
init_query
();
if
(
!
sel
->
add_table_to_list
(
thd
,
table_ident
,
0
,
0
,
TL_READ
,
MDL_SHARED_READ
))
if
(
!
sel
->
add_table_to_list
(
thd
,
table_ident
,
0
,
0
,
TL_READ
,
MDL_SHARED_READ
))
return
1
;
return
1
;
return
0
;
return
0
;
...
@@ -2982,91 +2981,190 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
...
@@ -2982,91 +2981,190 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
/**
/**
@brief Fill I_S table for SHOW COLUMNS|INDEX commands
Fill I_S table with data obtained by performing full-blown table open.
@param thd Thread handler.
@param is_show_fields_or_keys Indicates whether it is a legacy SHOW
COLUMNS or SHOW KEYS statement.
@param table TABLE object for I_S table to be filled.
@param schema_table I_S table description structure.
@param orig_db_name Database name.
@param orig_table_name Table name.
@param open_tables_state_backup Open_tables_state object which is used
to save/restore original status of
variables related to open tables state.
@param can_deadlock Indicates that deadlocks are possible
due to metadata locks, so to avoid
them we should not wait in case if
conflicting lock is present.
@retval FALSE - Success.
@retval TRUE - Failure.
*/
static
bool
fill_schema_table_by_open
(
THD
*
thd
,
bool
is_show_fields_or_keys
,
TABLE
*
table
,
ST_SCHEMA_TABLE
*
schema_table
,
LEX_STRING
*
orig_db_name
,
LEX_STRING
*
orig_table_name
,
Open_tables_backup
*
open_tables_state_backup
,
bool
can_deadlock
)
{
Query_arena
i_s_arena
(
thd
->
mem_root
,
Query_arena
::
STMT_CONVENTIONAL_EXECUTION
),
backup_arena
,
*
old_arena
;
LEX
*
old_lex
=
thd
->
lex
,
temp_lex
,
*
lex
;
LEX_STRING
db_name
,
table_name
;
TABLE_LIST
*
table_list
;
bool
result
=
true
;
DBUG_ENTER
(
"fill_schema_table_by_open"
);
/*
When a view is opened its structures are allocated on a permanent
statement arena and linked into the LEX tree for the current statement
(this happens even in cases when view is handled through TEMPTABLE
algorithm).
@param[in] thd thread handler
To prevent this process from unnecessary hogging of memory in the permanent
@param[in] tables TABLE_LIST for I_S table
arena of our I_S query and to avoid damaging its LEX we use temporary
@param[in] schema_table pointer to I_S structure
arena and LEX for table/view opening.
@param[in] can_deadlock Indicates that deadlocks are possible
due to metadata locks, so to avoid
them we should not wait in case if
conflicting lock is present.
@param[in] open_tables_state_backup pointer to Open_tables_backup object
which is used to save|restore original
status of variables related to
open tables state
@return Operation status
Use temporary arena instead of statement permanent arena. Also make
@retval 0 success
it active arena and save original one for successive restoring.
@retval 1 error
*/
*/
old_arena
=
thd
->
stmt_arena
;
thd
->
stmt_arena
=
&
i_s_arena
;
thd
->
set_n_backup_active_arena
(
&
i_s_arena
,
&
backup_arena
);
static
int
/* Prepare temporary LEX. */
fill_schema_show_cols_or_idxs
(
THD
*
thd
,
TABLE_LIST
*
tables
,
thd
->
lex
=
lex
=
&
temp_lex
;
ST_SCHEMA_TABLE
*
schema_table
,
lex_start
(
thd
);
bool
can_deadlock
,
Open_tables_backup
*
open_tables_state_backup
)
/* Disable constant subquery evaluation as we won't be locking tables. */
{
lex
->
context_analysis_only
=
CONTEXT_ANALYSIS_ONLY_VIEW
;
LEX
*
lex
=
thd
->
lex
;
bool
res
;
/*
LEX_STRING
tmp_lex_string
,
tmp_lex_string1
,
*
db_name
,
*
table_name
;
Some of process_table() functions rely on wildcard being passed from
enum_sql_command
save_sql_command
=
lex
->
sql_command
;
old LEX (or at least being initialized).
TABLE_LIST
*
show_table_list
=
tables
->
schema_select_lex
->
table_list
.
first
;
*/
TABLE
*
table
=
tables
->
table
;
lex
->
wild
=
old_lex
->
wild
;
int
error
=
1
;
DBUG_ENTER
(
"fill_schema_show"
);
/*
Since make_table_list() might change database and table name passed
to it we create copies of orig_db_name and orig_table_name here.
These copies are used for make_table_list() while unaltered values
are passed to process_table() functions.
*/
if
(
!
thd
->
make_lex_string
(
&
db_name
,
orig_db_name
->
str
,
orig_db_name
->
length
,
FALSE
)
||
!
thd
->
make_lex_string
(
&
table_name
,
orig_table_name
->
str
,
orig_table_name
->
length
,
FALSE
))
goto
end
;
lex
->
all_selects_list
=
tables
->
schema_select_lex
;
/*
/*
Restore thd->temporary_tables to be able to process
Create table list element for table to be open. Link it with the
temporary tables(only for 'show index' & 'show columns').
temporary LEX. The latter is required to correctly open views and
This should be changed when processing of temporary tables for
produce table describing their structure.
I_S tables will be done.
*/
*/
thd
->
temporary_tables
=
open_tables_state_backup
->
temporary_tables
;
if
(
make_table_list
(
thd
,
&
lex
->
select_lex
,
&
db_name
,
&
table_name
))
goto
end
;
table_list
=
lex
->
select_lex
.
table_list
.
first
;
if
(
is_show_fields_or_keys
)
{
/*
Restore thd->temporary_tables to be able to process
temporary tables (only for 'show index' & 'show columns').
This should be changed when processing of temporary tables for
I_S tables will be done.
*/
thd
->
temporary_tables
=
open_tables_state_backup
->
temporary_tables
;
}
else
{
/*
Apply optimization flags for table opening which are relevant for
this I_S table. We can't do this for SHOW COLUMNS/KEYS because of
backward compatibility.
*/
table_list
->
i_s_requested_object
=
schema_table
->
i_s_requested_object
;
}
/*
/*
Let us set fake sql_command so views won't try to merge
Let us set fake sql_command so views won't try to merge
themselves into main statement. If we don't do this,
themselves into main statement. If we don't do this,
SELECT * from information_schema.xxxx will cause problems.
SELECT * from information_schema.xxxx will cause problems.
SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
SQLCOM_SHOW_FIELDS is used because it satisfies
'only_view_structure()'.
*/
*/
lex
->
sql_command
=
SQLCOM_SHOW_FIELDS
;
lex
->
sql_command
=
SQLCOM_SHOW_FIELDS
;
res
=
open_normal_and_derived_tables
(
thd
,
show_table_list
,
result
=
open_normal_and_derived_tables
(
thd
,
table_list
,
(
MYSQL_OPEN_IGNORE_FLUSH
|
(
MYSQL_OPEN_IGNORE_FLUSH
|
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL
|
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL
|
(
can_deadlock
?
(
can_deadlock
?
MYSQL_OPEN_FAIL_ON_MDL_CONFLICT
:
0
)));
MYSQL_OPEN_FAIL_ON_MDL_CONFLICT
:
0
)));
lex
->
sql_command
=
save_sql_command
;
/*
Restore old value of sql_command back as it is being looked at in
process_table() function.
*/
lex
->
sql_command
=
old_lex
->
sql_command
;
DEBUG_SYNC
(
thd
,
"after_open_table_ignore_flush"
);
DEBUG_SYNC
(
thd
,
"after_open_table_ignore_flush"
);
/*
/*
get_all_tables() returns 1 on failure and 0 on success thus
XXX: show_table_list has a flag i_is_requested,
return only these and not the result code of ::process_table
()
and when it's set, open_normal_and_derived_tables
()
can return an error without setting an error message
We should use show_table_list->alias instead of
in THD, which is a hack. This is why we have to
show_table_list->table_name because table_name
check for res, then for thd->is_error() and only then
could be changed during opening of I_S tables. It's safe
for thd->main_da.sql_errno().
to use alias because alias contains original table name
in this case(this part of code is used only for
Again we don't do this for SHOW COLUMNS/KEYS because
'show columns' & 'show statistics' commands)
.
of backward compatibility
.
*/
*/
table_name
=
thd
->
make_lex_string
(
&
tmp_lex_string1
,
show_table_list
->
alias
,
if
(
!
is_show_fields_or_keys
&&
result
&&
thd
->
is_error
()
&&
strlen
(
show_table_list
->
alias
),
FALSE
);
thd
->
stmt_da
->
sql_errno
()
==
ER_NO_SUCH_TABLE
)
if
(
!
show_table_list
->
view
)
{
db_name
=
thd
->
make_lex_string
(
&
tmp_lex_string
,
show_table_list
->
db
,
/*
show_table_list
->
db_length
,
FALSE
);
Hide error for a non-existing table.
else
For example, this error can occur when we use a where condition
db_name
=
&
show_table_list
->
view_db
;
with a db name and table, but the table does not exist.
*/
result
=
false
;
error
=
test
(
schema_table
->
process_table
(
thd
,
show_table_list
,
thd
->
clear_error
();
table
,
res
,
db_name
,
}
table_name
));
else
thd
->
temporary_tables
=
0
;
{
close_tables_for_reopen
(
thd
,
&
show_table_list
,
result
=
schema_table
->
process_table
(
thd
,
table_list
,
open_tables_state_backup
->
mdl_system_tables_svp
);
table
,
result
,
DBUG_RETURN
(
error
);
orig_db_name
,
orig_table_name
);
}
end:
lex
->
unit
.
cleanup
();
/* Restore original LEX value, statement's arena and THD arena values. */
lex_end
(
thd
->
lex
);
if
(
i_s_arena
.
free_list
)
i_s_arena
.
free_items
();
/*
For safety reset list of open temporary tables before closing
all tables open within this Open_tables_state.
*/
thd
->
temporary_tables
=
NULL
;
close_thread_tables
(
thd
);
thd
->
mdl_context
.
rollback_to_savepoint
(
open_tables_state_backup
->
mdl_system_tables_svp
);
thd
->
lex
=
old_lex
;
thd
->
stmt_arena
=
old_arena
;
thd
->
restore_active_arena
(
&
i_s_arena
,
&
backup_arena
);
DBUG_RETURN
(
result
);
}
}
...
@@ -3477,10 +3575,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3477,10 +3575,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
{
LEX
*
lex
=
thd
->
lex
;
LEX
*
lex
=
thd
->
lex
;
TABLE
*
table
=
tables
->
table
;
TABLE
*
table
=
tables
->
table
;
SELECT_LEX
*
old_all_select_lex
=
lex
->
all_selects_list
;
SELECT_LEX
*
lsel
=
tables
->
schema_select_lex
;
SELECT_LEX
*
lsel
=
tables
->
schema_select_lex
;
ST_SCHEMA_TABLE
*
schema_table
=
tables
->
schema_table
;
ST_SCHEMA_TABLE
*
schema_table
=
tables
->
schema_table
;
SELECT_LEX
sel
;
LOOKUP_FIELD_VALUES
lookup_field_vals
;
LOOKUP_FIELD_VALUES
lookup_field_vals
;
LEX_STRING
*
db_name
,
*
table_name
;
LEX_STRING
*
db_name
,
*
table_name
;
bool
with_i_schema
;
bool
with_i_schema
;
...
@@ -3488,11 +3584,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3488,11 +3584,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
List
<
LEX_STRING
>
db_names
;
List
<
LEX_STRING
>
db_names
;
List_iterator_fast
<
LEX_STRING
>
it
(
db_names
);
List_iterator_fast
<
LEX_STRING
>
it
(
db_names
);
COND
*
partial_cond
=
0
;
COND
*
partial_cond
=
0
;
uint
derived_tables
=
lex
->
derived_tables
;
int
error
=
1
;
int
error
=
1
;
Open_tables_backup
open_tables_state_backup
;
Open_tables_backup
open_tables_state_backup
;
uint8
save_context_analysis_only
=
lex
->
context_analysis_only
;
Query_tables_list
query_tables_list_backup
;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context
*
sctx
=
thd
->
security_ctx
;
Security_context
*
sctx
=
thd
->
security_ctx
;
#endif
#endif
...
@@ -3511,15 +3604,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3511,15 +3604,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
*/
can_deadlock
=
thd
->
mdl_context
.
has_locks
();
can_deadlock
=
thd
->
mdl_context
.
has_locks
();
lex
->
context_analysis_only
|=
CONTEXT_ANALYSIS_ONLY_VIEW
;
lex
->
reset_n_backup_query_tables_list
(
&
query_tables_list_backup
);
/*
Restore Query_tables_list::sql_command value, which was reset
above, as ST_SCHEMA_TABLE::process_table() functions often rely
that this value reflects which SHOW statement is executed.
*/
lex
->
sql_command
=
query_tables_list_backup
.
sql_command
;
/*
/*
We should not introduce deadlocks even if we already have some
We should not introduce deadlocks even if we already have some
tables open and locked, since we won't lock tables which we will
tables open and locked, since we won't lock tables which we will
...
@@ -3539,9 +3623,19 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3539,9 +3623,19 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
*/
if
(
lsel
&&
lsel
->
table_list
.
first
)
if
(
lsel
&&
lsel
->
table_list
.
first
)
{
{
error
=
fill_schema_show_cols_or_idxs
(
thd
,
tables
,
schema_table
,
LEX_STRING
db_name
,
table_name
;
can_deadlock
,
&
open_tables_state_backup
);
db_name
.
str
=
lsel
->
table_list
.
first
->
db
;
db_name
.
length
=
lsel
->
table_list
.
first
->
db_length
;
table_name
.
str
=
lsel
->
table_list
.
first
->
table_name
;
table_name
.
length
=
lsel
->
table_list
.
first
->
table_name_length
;
error
=
fill_schema_table_by_open
(
thd
,
TRUE
,
table
,
schema_table
,
&
db_name
,
&
table_name
,
&
open_tables_state_backup
,
can_deadlock
);
goto
err
;
goto
err
;
}
}
...
@@ -3595,12 +3689,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3595,12 +3689,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
it
.
rewind
();
/* To get access to new elements in basis list */
it
.
rewind
();
/* To get access to new elements in basis list */
while
((
db_name
=
it
++
))
while
((
db_name
=
it
++
))
{
{
LEX_STRING
orig_db_name
;
/* db_name can be changed in make_table_list() func */
if
(
!
thd
->
make_lex_string
(
&
orig_db_name
,
db_name
->
str
,
db_name
->
length
,
FALSE
))
goto
err
;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
!
(
check_access
(
thd
,
SELECT_ACL
,
db_name
->
str
,
if
(
!
(
check_access
(
thd
,
SELECT_ACL
,
db_name
->
str
,
&
thd
->
col_access
,
NULL
,
0
,
1
)
||
&
thd
->
col_access
,
NULL
,
0
,
1
)
||
...
@@ -3678,66 +3766,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3678,66 +3766,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
continue
;
continue
;
}
}
int
res
;
if
(
fill_schema_table_by_open
(
thd
,
FALSE
,
LEX_STRING
tmp_lex_string
;
table
,
schema_table
,
/*
db_name
,
table_name
,
Set the parent lex of 'sel' because it is needed by
&
open_tables_state_backup
,
sel.init_query() which is called inside make_table_list.
can_deadlock
))
*/
sel
.
parent_lex
=
lex
;
if
(
make_table_list
(
thd
,
&
sel
,
db_name
,
table_name
))
goto
err
;
TABLE_LIST
*
show_table_list
=
sel
.
table_list
.
first
;
lex
->
all_selects_list
=
&
sel
;
lex
->
derived_tables
=
0
;
lex
->
sql_command
=
SQLCOM_SHOW_FIELDS
;
show_table_list
->
i_s_requested_object
=
schema_table
->
i_s_requested_object
;
DEBUG_SYNC
(
thd
,
"before_open_in_get_all_tables"
);
res
=
open_normal_and_derived_tables
(
thd
,
show_table_list
,
(
MYSQL_OPEN_IGNORE_FLUSH
|
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL
|
(
can_deadlock
?
MYSQL_OPEN_FAIL_ON_MDL_CONFLICT
:
0
)));
lex
->
sql_command
=
query_tables_list_backup
.
sql_command
;
/*
XXX: show_table_list has a flag i_is_requested,
and when it's set, open_normal_and_derived_tables()
can return an error without setting an error message
in THD, which is a hack. This is why we have to
check for res, then for thd->is_error() only then
for thd->stmt_da->sql_errno().
*/
if
(
res
&&
thd
->
is_error
()
&&
thd
->
stmt_da
->
sql_errno
()
==
ER_NO_SUCH_TABLE
)
{
/*
Hide error for not existing table.
This error can occur for example when we use
where condition with db name and table name and this
table does not exist.
*/
res
=
0
;
thd
->
clear_error
();
}
else
{
/*
We should use show_table_list->alias instead of
show_table_list->table_name because table_name
could be changed during opening of I_S tables. It's safe
to use alias because alias contains original table name
in this case.
*/
thd
->
make_lex_string
(
&
tmp_lex_string
,
show_table_list
->
alias
,
strlen
(
show_table_list
->
alias
),
FALSE
);
res
=
schema_table
->
process_table
(
thd
,
show_table_list
,
table
,
res
,
&
orig_db_name
,
&
tmp_lex_string
);
close_tables_for_reopen
(
thd
,
&
show_table_list
,
open_tables_state_backup
.
mdl_system_tables_svp
);
}
DBUG_ASSERT
(
!
lex
->
query_tables_own_last
);
if
(
res
)
goto
err
;
goto
err
;
}
}
}
}
...
@@ -3753,10 +3786,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
...
@@ -3753,10 +3786,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
error
=
0
;
error
=
0
;
err:
err:
thd
->
restore_backup_open_tables_state
(
&
open_tables_state_backup
);
thd
->
restore_backup_open_tables_state
(
&
open_tables_state_backup
);
lex
->
restore_backup_query_tables_list
(
&
query_tables_list_backup
);
lex
->
derived_tables
=
derived_tables
;
lex
->
all_selects_list
=
old_all_select_lex
;
lex
->
context_analysis_only
=
save_context_analysis_only
;
DBUG_RETURN
(
error
);
DBUG_RETURN
(
error
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment