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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
4d50594d
Commit
4d50594d
authored
Aug 15, 2017
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-13529 Add class Sql_cmd_call
parent
966cc802
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
120 additions
and
68 deletions
+120
-68
mysql-test/r/lowercase_fs_off.result
mysql-test/r/lowercase_fs_off.result
+1
-1
sql/item_func.cc
sql/item_func.cc
+13
-12
sql/item_func.h
sql/item_func.h
+1
-1
sql/sp_head.cc
sql/sp_head.cc
+8
-0
sql/sp_head.h
sql/sp_head.h
+2
-0
sql/sql_cmd.h
sql/sql_cmd.h
+29
-0
sql/sql_lex.cc
sql/sql_lex.cc
+2
-0
sql/sql_parse.cc
sql/sql_parse.cc
+64
-54
No files found.
mysql-test/r/lowercase_fs_off.result
View file @
4d50594d
...
...
@@ -61,7 +61,7 @@ connect con2,localhost,USER_1,,db1;
call p1();
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
call P1();
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.
P
1'
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.
p
1'
select f1(1);
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
connection default;
...
...
sql/item_func.cc
View file @
4d50594d
...
...
@@ -6256,7 +6256,7 @@ void my_missing_function_error(const LEX_CSTRING &token, const char *func_name)
*/
bool
Item_func_sp
::
init_result_field
(
THD
*
thd
)
Item_func_sp
::
init_result_field
(
THD
*
thd
,
sp_head
*
sp
)
{
TABLE_SHARE
*
share
;
DBUG_ENTER
(
"Item_func_sp::init_result_field"
);
...
...
@@ -6264,7 +6264,7 @@ Item_func_sp::init_result_field(THD *thd)
DBUG_ASSERT
(
m_sp
==
NULL
);
DBUG_ASSERT
(
sp_result_field
==
NULL
);
if
(
!
(
m_sp
=
sp
_handler_function
.
sp_find_routine
(
thd
,
m_name
,
true
)
))
if
(
!
(
m_sp
=
sp
))
{
my_missing_function_error
(
m_name
->
m_name
,
ErrConvDQName
(
m_name
).
ptr
());
context
->
process_error
(
thd
);
...
...
@@ -6512,12 +6512,7 @@ Item_func_sp::sp_check_access(THD *thd)
{
DBUG_ENTER
(
"Item_func_sp::sp_check_access"
);
DBUG_ASSERT
(
m_sp
);
if
(
check_routine_access
(
thd
,
EXECUTE_ACL
,
m_sp
->
m_db
.
str
,
m_sp
->
m_name
.
str
,
&
sp_handler_function
,
false
))
DBUG_RETURN
(
TRUE
);
DBUG_RETURN
(
FALSE
);
DBUG_RETURN
(
m_sp
->
check_execute_access
(
thd
));
}
...
...
@@ -6527,6 +6522,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
bool
res
;
DBUG_ENTER
(
"Item_func_sp::fix_fields"
);
DBUG_ASSERT
(
fixed
==
0
);
sp_head
*
sp
=
sp_handler_function
.
sp_find_routine
(
thd
,
m_name
,
true
);
/*
Checking privileges to execute the function while creating view and
...
...
@@ -6539,9 +6535,14 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
if
(
context
->
security_ctx
)
thd
->
security_ctx
=
context
->
security_ctx
;
res
=
check_routine_access
(
thd
,
EXECUTE_ACL
,
m_name
->
m_db
.
str
,
m_name
->
m_name
.
str
,
&
sp_handler_function
,
false
);
/*
If the routine is not found, let's still check EXECUTE_ACL to decide
whether to return "Access denied" or "Routine does not exist".
*/
res
=
sp
?
sp
->
check_execute_access
(
thd
)
:
check_routine_access
(
thd
,
EXECUTE_ACL
,
m_name
->
m_db
.
str
,
m_name
->
m_name
.
str
,
&
sp_handler_function
,
false
);
thd
->
security_ctx
=
save_security_ctx
;
if
(
res
)
...
...
@@ -6556,7 +6557,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
to make m_sp and result_field members available to fix_length_and_dec(),
which is called from Item_func::fix_fields().
*/
res
=
init_result_field
(
thd
);
res
=
init_result_field
(
thd
,
sp
);
if
(
res
)
DBUG_RETURN
(
res
);
...
...
sql/item_func.h
View file @
4d50594d
...
...
@@ -2679,7 +2679,7 @@ class Item_func_sp :public Item_func
bool
execute
();
bool
execute_impl
(
THD
*
thd
);
bool
init_result_field
(
THD
*
thd
);
bool
init_result_field
(
THD
*
thd
,
sp_head
*
sp
);
protected:
bool
is_expensive_processor
(
void
*
arg
)
...
...
sql/sp_head.cc
View file @
4d50594d
...
...
@@ -1424,6 +1424,14 @@ set_routine_security_ctx(THD *thd, sp_head *sp, Security_context **save_ctx)
#endif // ! NO_EMBEDDED_ACCESS_CHECKS
bool
sp_head
::
check_execute_access
(
THD
*
thd
)
const
{
return
check_routine_access
(
thd
,
EXECUTE_ACL
,
m_db
.
str
,
m_name
.
str
,
m_handler
,
false
);
}
/**
Create rcontext using the routine security.
This is important for sql_mode=ORACLE to make sure that the invoker has
...
...
sql/sp_head.h
View file @
4d50594d
...
...
@@ -791,6 +791,8 @@ class sp_head :private Query_arena,
sp_pcontext
*
get_parse_context
()
{
return
m_pcont
;
}
bool
check_execute_access
(
THD
*
thd
)
const
;
private:
MEM_ROOT
*
m_thd_root
;
///< Temp. store for thd's mem_root
...
...
sql/sql_cmd.h
View file @
4d50594d
...
...
@@ -167,4 +167,33 @@ class Sql_cmd : public Sql_alloc
}
};
/**
Sql_cmd_call represents the CALL statement.
*/
class
Sql_cmd_call
:
public
Sql_cmd
{
public:
class
sp_name
*
m_name
;
Sql_cmd_call
(
class
sp_name
*
name
)
:
m_name
(
name
)
{}
virtual
~
Sql_cmd_call
()
{}
/**
Execute a CALL statement at runtime.
@param thd the current thread.
@return false on success.
*/
bool
execute
(
THD
*
thd
);
virtual
enum_sql_command
sql_command_code
()
const
{
return
SQLCOM_CALL
;
}
};
#endif // SQL_CMD_INCLUDED
sql/sql_lex.cc
View file @
4d50594d
...
...
@@ -7156,6 +7156,8 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
sql_command
=
SQLCOM_CALL
;
spname
=
name
;
value_list
.
empty
();
if
(
!
(
m_sql_cmd
=
new
(
thd
->
mem_root
)
Sql_cmd_call
(
name
)))
return
true
;
sp_handler_procedure
.
add_used_routine
(
this
,
thd
,
name
);
return
false
;
}
...
...
sql/sql_parse.cc
View file @
4d50594d
...
...
@@ -3074,6 +3074,69 @@ static bool prepare_db_action(THD *thd, ulong want_access, LEX_CSTRING *dbname)
return
check_access
(
thd
,
want_access
,
dbname
->
str
,
NULL
,
NULL
,
1
,
0
);
}
bool
Sql_cmd_call
::
execute
(
THD
*
thd
)
{
TABLE_LIST
*
all_tables
=
thd
->
lex
->
query_tables
;
sp_head
*
sp
;
/*
This will cache all SP and SF and open and lock all tables
required for execution.
*/
if
(
check_table_access
(
thd
,
SELECT_ACL
,
all_tables
,
FALSE
,
UINT_MAX
,
FALSE
)
||
open_and_lock_tables
(
thd
,
all_tables
,
TRUE
,
0
))
return
true
;
/*
By this moment all needed SPs should be in cache so no need to look
into DB.
*/
if
(
!
(
sp
=
sp_handler_procedure
.
sp_find_routine
(
thd
,
m_name
,
true
)))
{
/*
If the routine is not found, let's still check EXECUTE_ACL to decide
whether to return "Access denied" or "Routine does not exist".
*/
if
(
check_routine_access
(
thd
,
EXECUTE_ACL
,
m_name
->
m_db
.
str
,
m_name
->
m_name
.
str
,
&
sp_handler_procedure
,
false
))
return
true
;
/*
sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
Send message ER_SP_DOES_NOT_EXIST only if procedure is not found in
cache.
*/
if
(
!
sp_cache_lookup
(
&
thd
->
sp_proc_cache
,
m_name
))
my_error
(
ER_SP_DOES_NOT_EXIST
,
MYF
(
0
),
"PROCEDURE"
,
ErrConvDQName
(
m_name
).
ptr
());
return
true
;
}
else
{
if
(
sp
->
check_execute_access
(
thd
))
return
true
;
/*
Check that the stored procedure doesn't contain Dynamic SQL
and doesn't return result sets: such stored procedures can't
be called from a function or trigger.
*/
if
(
thd
->
in_sub_stmt
)
{
const
char
*
where
=
(
thd
->
in_sub_stmt
&
SUB_STMT_TRIGGER
?
"trigger"
:
"function"
);
if
(
sp
->
is_not_allowed_in_function
(
where
))
return
true
;
}
if
(
do_execute_sp
(
thd
,
sp
))
return
true
;
}
return
false
;
}
/**
Execute command saved in thd and lex->sql_command.
...
...
@@ -5748,60 +5811,6 @@ mysql_execute_command(THD *thd)
my_ok
(
thd
);
break
;
/* break super switch */
}
/* end case group bracket */
case
SQLCOM_CALL
:
{
sp_head
*
sp
;
/*
This will cache all SP and SF and open and lock all tables
required for execution.
*/
if
(
check_table_access
(
thd
,
SELECT_ACL
,
all_tables
,
FALSE
,
UINT_MAX
,
FALSE
)
||
open_and_lock_tables
(
thd
,
all_tables
,
TRUE
,
0
))
goto
error
;
if
(
check_routine_access
(
thd
,
EXECUTE_ACL
,
lex
->
spname
->
m_db
.
str
,
lex
->
spname
->
m_name
.
str
,
&
sp_handler_procedure
,
false
))
goto
error
;
/*
By this moment all needed SPs should be in cache so no need to look
into DB.
*/
if
(
!
(
sp
=
sp_handler_procedure
.
sp_find_routine
(
thd
,
lex
->
spname
,
true
)))
{
/*
sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
Send message ER_SP_DOES_NOT_EXIST only if procedure is not found in
cache.
*/
if
(
!
sp_cache_lookup
(
&
thd
->
sp_proc_cache
,
lex
->
spname
))
my_error
(
ER_SP_DOES_NOT_EXIST
,
MYF
(
0
),
"PROCEDURE"
,
ErrConvDQName
(
lex
->
spname
).
ptr
());
goto
error
;
}
else
{
/*
Check that the stored procedure doesn't contain Dynamic SQL
and doesn't return result sets: such stored procedures can't
be called from a function or trigger.
*/
if
(
thd
->
in_sub_stmt
)
{
const
char
*
where
=
(
thd
->
in_sub_stmt
&
SUB_STMT_TRIGGER
?
"trigger"
:
"function"
);
if
(
sp
->
is_not_allowed_in_function
(
where
))
goto
error
;
}
if
(
do_execute_sp
(
thd
,
sp
))
goto
error
;
}
break
;
}
case
SQLCOM_COMPOUND
:
DBUG_ASSERT
(
all_tables
==
0
);
DBUG_ASSERT
(
thd
->
in_sub_stmt
==
0
);
...
...
@@ -6196,6 +6205,7 @@ mysql_execute_command(THD *thd)
case
SQLCOM_SIGNAL
:
case
SQLCOM_RESIGNAL
:
case
SQLCOM_GET_DIAGNOSTICS
:
case
SQLCOM_CALL
:
DBUG_ASSERT
(
lex
->
m_sql_cmd
!=
NULL
);
res
=
lex
->
m_sql_cmd
->
execute
(
thd
);
break
;
...
...
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