mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
Merge kpettersson@bk-internal:/home/bk/mysql-5.1-runtime
into naruto.:C:/cpp/mysql-5.1-runtime sql/item_func.cc: Auto merged mysql-test/r/sp.result: manual merge mysql-test/t/sp.test: manual merge
This commit is contained in:
commit
40a197ee9f
4 changed files with 322 additions and 189 deletions
|
@ -6061,4 +6061,92 @@ SUM(f2) bug25373(f1)
|
||||||
21.300000071526 NULL
|
21.300000071526 NULL
|
||||||
DROP FUNCTION bug25373|
|
DROP FUNCTION bug25373|
|
||||||
DROP TABLE t3|
|
DROP TABLE t3|
|
||||||
|
drop function if exists bug20777|
|
||||||
|
drop table if exists examplebug20777|
|
||||||
|
create function bug20777(f1 bigint unsigned) returns bigint unsigned
|
||||||
|
begin
|
||||||
|
set f1 = (f1 - 10); set f1 = (f1 + 10);
|
||||||
|
return f1;
|
||||||
|
end|
|
||||||
|
select bug20777(9223372036854775803) as '9223372036854775803 2**63-5';
|
||||||
|
9223372036854775803 2**63-5
|
||||||
|
9223372036854775803
|
||||||
|
select bug20777(9223372036854775804) as '9223372036854775804 2**63-4';
|
||||||
|
9223372036854775804 2**63-4
|
||||||
|
9223372036854775804
|
||||||
|
select bug20777(9223372036854775805) as '9223372036854775805 2**63-3';
|
||||||
|
9223372036854775805 2**63-3
|
||||||
|
9223372036854775805
|
||||||
|
select bug20777(9223372036854775806) as '9223372036854775806 2**63-2';
|
||||||
|
9223372036854775806 2**63-2
|
||||||
|
9223372036854775806
|
||||||
|
select bug20777(9223372036854775807) as '9223372036854775807 2**63-1';
|
||||||
|
9223372036854775807 2**63-1
|
||||||
|
9223372036854775807
|
||||||
|
select bug20777(9223372036854775808) as '9223372036854775808 2**63+0';
|
||||||
|
9223372036854775808 2**63+0
|
||||||
|
9223372036854775808
|
||||||
|
select bug20777(9223372036854775809) as '9223372036854775809 2**63+1';
|
||||||
|
9223372036854775809 2**63+1
|
||||||
|
9223372036854775809
|
||||||
|
select bug20777(9223372036854775810) as '9223372036854775810 2**63+2';
|
||||||
|
9223372036854775810 2**63+2
|
||||||
|
9223372036854775810
|
||||||
|
select bug20777(-9223372036854775808) as 'lower bounds signed bigint';
|
||||||
|
lower bounds signed bigint
|
||||||
|
0
|
||||||
|
select bug20777(9223372036854775807) as 'upper bounds signed bigint';
|
||||||
|
upper bounds signed bigint
|
||||||
|
9223372036854775807
|
||||||
|
select bug20777(0) as 'lower bounds unsigned bigint';
|
||||||
|
lower bounds unsigned bigint
|
||||||
|
0
|
||||||
|
select bug20777(18446744073709551615) as 'upper bounds unsigned bigint';
|
||||||
|
upper bounds unsigned bigint
|
||||||
|
18446744073709551615
|
||||||
|
select bug20777(18446744073709551616) as 'upper bounds unsigned bigint + 1';
|
||||||
|
upper bounds unsigned bigint + 1
|
||||||
|
18446744073709551615
|
||||||
|
select bug20777(-1) as 'lower bounds unsigned bigint - 1';
|
||||||
|
lower bounds unsigned bigint - 1
|
||||||
|
0
|
||||||
|
select bug20777(1.84e+19) as 'submitter value, 1.84e19';
|
||||||
|
submitter value, 1.84e19
|
||||||
|
9223372036854775808
|
||||||
|
create table examplebug20777 as select
|
||||||
|
0 as 'i',
|
||||||
|
bug20777(9223372036854775806) as '2**63-2',
|
||||||
|
bug20777(9223372036854775807) as '2**63-1',
|
||||||
|
bug20777(9223372036854775808) as '2**63',
|
||||||
|
bug20777(9223372036854775809) as '2**63+1',
|
||||||
|
bug20777(18446744073709551614) as '2**64-2',
|
||||||
|
bug20777(18446744073709551615) as '2**64-1',
|
||||||
|
bug20777(18446744073709551616) as '2**64',
|
||||||
|
bug20777(0) as '0',
|
||||||
|
bug20777(-1) as '-1';
|
||||||
|
insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616, 0, -1);
|
||||||
|
show create table examplebug20777;
|
||||||
|
Table Create Table
|
||||||
|
examplebug20777 CREATE TABLE `examplebug20777` (
|
||||||
|
`i` int(1) NOT NULL DEFAULT '0',
|
||||||
|
`2**63-2` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**63-1` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**63` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**63+1` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**64-2` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**64-1` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`2**64` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`0` bigint(20) unsigned DEFAULT NULL,
|
||||||
|
`-1` bigint(20) unsigned DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
select * from examplebug20777 order by i;
|
||||||
|
i 2**63-2 2**63-1 2**63 2**63+1 2**64-2 2**64-1 2**64 0 -1
|
||||||
|
0 9223372036854775806 9223372036854775807 9223372036854775808 9223372036854775809 18446744073709551614 18446744073709551615 18446744073709551615 0 0
|
||||||
|
1 9223372036854775806 9223372036854775807 223372036854775808 9223372036854775809 18446744073709551614 18446744073709551615 8446744073709551616 0 0
|
||||||
|
drop table examplebug20777;
|
||||||
|
select bug20777(18446744073709551613)+1;
|
||||||
|
bug20777(18446744073709551613)+1
|
||||||
|
18446744073709551614
|
||||||
|
drop function bug20777;
|
||||||
|
End of 5.0 tests.
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
|
@ -7018,9 +7018,55 @@ SELECT SUM(f2), bug25373(f1) FROM t3 GROUP BY bug25373(f1) WITH ROLLUP|
|
||||||
DROP FUNCTION bug25373|
|
DROP FUNCTION bug25373|
|
||||||
DROP TABLE t3|
|
DROP TABLE t3|
|
||||||
#
|
#
|
||||||
# NOTE: The delimiter is `|`, and not `;`. It is changed to `;`
|
# Bug#20777: Function w BIGINT UNSIGNED shows diff. behaviour --ps-protocol
|
||||||
# at the end of the file!
|
--disable_warnings
|
||||||
#
|
drop function if exists bug20777|
|
||||||
|
drop table if exists examplebug20777|
|
||||||
|
--enabled_warnings
|
||||||
|
create function bug20777(f1 bigint unsigned) returns bigint unsigned
|
||||||
|
begin
|
||||||
|
set f1 = (f1 - 10); set f1 = (f1 + 10);
|
||||||
|
return f1;
|
||||||
|
end|
|
||||||
|
delimiter ;|
|
||||||
|
select bug20777(9223372036854775803) as '9223372036854775803 2**63-5';
|
||||||
|
select bug20777(9223372036854775804) as '9223372036854775804 2**63-4';
|
||||||
|
select bug20777(9223372036854775805) as '9223372036854775805 2**63-3';
|
||||||
|
select bug20777(9223372036854775806) as '9223372036854775806 2**63-2';
|
||||||
|
select bug20777(9223372036854775807) as '9223372036854775807 2**63-1';
|
||||||
|
select bug20777(9223372036854775808) as '9223372036854775808 2**63+0';
|
||||||
|
select bug20777(9223372036854775809) as '9223372036854775809 2**63+1';
|
||||||
|
select bug20777(9223372036854775810) as '9223372036854775810 2**63+2';
|
||||||
|
select bug20777(-9223372036854775808) as 'lower bounds signed bigint';
|
||||||
|
select bug20777(9223372036854775807) as 'upper bounds signed bigint';
|
||||||
|
select bug20777(0) as 'lower bounds unsigned bigint';
|
||||||
|
select bug20777(18446744073709551615) as 'upper bounds unsigned bigint';
|
||||||
|
select bug20777(18446744073709551616) as 'upper bounds unsigned bigint + 1';
|
||||||
|
select bug20777(-1) as 'lower bounds unsigned bigint - 1';
|
||||||
|
select bug20777(1.84e+19) as 'submitter value, 1.84e19';
|
||||||
|
|
||||||
|
create table examplebug20777 as select
|
||||||
|
0 as 'i',
|
||||||
|
bug20777(9223372036854775806) as '2**63-2',
|
||||||
|
bug20777(9223372036854775807) as '2**63-1',
|
||||||
|
bug20777(9223372036854775808) as '2**63',
|
||||||
|
bug20777(9223372036854775809) as '2**63+1',
|
||||||
|
bug20777(18446744073709551614) as '2**64-2',
|
||||||
|
bug20777(18446744073709551615) as '2**64-1',
|
||||||
|
bug20777(18446744073709551616) as '2**64',
|
||||||
|
bug20777(0) as '0',
|
||||||
|
bug20777(-1) as '-1';
|
||||||
|
insert into examplebug20777 values (1, 9223372036854775806, 9223372036854775807, 223372036854775808, 9223372036854775809, 18446744073709551614, 18446744073709551615, 8446744073709551616, 0, -1);
|
||||||
|
show create table examplebug20777;
|
||||||
|
select * from examplebug20777 order by i;
|
||||||
|
|
||||||
|
drop table examplebug20777;
|
||||||
|
select bug20777(18446744073709551613)+1;
|
||||||
|
drop function bug20777;
|
||||||
|
delimiter |;
|
||||||
|
|
||||||
|
###
|
||||||
|
--echo End of 5.0 tests.
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#NNNN: New bug synopsis
|
# BUG#NNNN: New bug synopsis
|
||||||
|
@ -7029,8 +7075,13 @@ DROP TABLE t3|
|
||||||
#drop procedure if exists bugNNNN|
|
#drop procedure if exists bugNNNN|
|
||||||
#--enable_warnings
|
#--enable_warnings
|
||||||
#create procedure bugNNNN...
|
#create procedure bugNNNN...
|
||||||
|
#
|
||||||
# Add bugs above this line. Use existing tables t1 and t2 when
|
# Add bugs above this line. Use existing tables t1 and t2 when
|
||||||
# practical, or create table t3, t4 etc temporarily (and drop them).
|
# practical, or create table t3,t4 etc temporarily (and drop them).
|
||||||
|
# NOTE: The delimiter is `|`, and not `;`. It is changed to `;`
|
||||||
|
# at the end of the file!
|
||||||
|
#
|
||||||
|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
|
321
sql/item_func.cc
321
sql/item_func.cc
|
@ -4988,10 +4988,8 @@ longlong Item_func_row_count::val_int()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
|
||||||
sp_name *name_arg)
|
:Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
|
||||||
:Item_func(), context(context_arg), m_name(name_arg), m_sp(NULL),
|
|
||||||
result_field(NULL)
|
|
||||||
{
|
{
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
|
@ -5001,9 +4999,8 @@ Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
||||||
|
|
||||||
|
|
||||||
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
||||||
sp_name *name_arg, List<Item> &list)
|
sp_name *name, List<Item> &list)
|
||||||
:Item_func(list), context(context_arg), m_name(name_arg), m_sp(NULL),
|
:Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
|
||||||
result_field(NULL)
|
|
||||||
{
|
{
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
|
@ -5015,10 +5012,10 @@ Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
||||||
void
|
void
|
||||||
Item_func_sp::cleanup()
|
Item_func_sp::cleanup()
|
||||||
{
|
{
|
||||||
if (result_field)
|
if (sp_result_field)
|
||||||
{
|
{
|
||||||
delete result_field;
|
delete sp_result_field;
|
||||||
result_field= NULL;
|
sp_result_field= NULL;
|
||||||
}
|
}
|
||||||
m_sp= NULL;
|
m_sp= NULL;
|
||||||
dummy_table->alias= NULL;
|
dummy_table->alias= NULL;
|
||||||
|
@ -5047,81 +5044,118 @@ Item_func_sp::func_name() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Field *
|
|
||||||
Item_func_sp::sp_result_field(void) const
|
|
||||||
{
|
|
||||||
Field *field;
|
|
||||||
DBUG_ENTER("Item_func_sp::sp_result_field");
|
|
||||||
DBUG_PRINT("info", ("sp: %s, flags: %x, level: %lu",
|
|
||||||
(m_sp ? "YES" : "NO"),
|
|
||||||
(m_sp ? m_sp->m_flags : (uint)0),
|
|
||||||
(m_sp ? m_sp->m_recursion_level : (ulong)0)));
|
|
||||||
|
|
||||||
if (!m_sp)
|
/**
|
||||||
{
|
@brief Initialize the result field by creating a temporary dummy table
|
||||||
THD *thd= current_thd;
|
and assign it to a newly created field object. Meta data used to
|
||||||
|
create the field is fetched from the sp_head belonging to the stored
|
||||||
|
proceedure found in the stored procedure functon cache.
|
||||||
|
|
||||||
|
@note This function should be called from fix_fields to init the result
|
||||||
|
field. It is some what related to Item_field.
|
||||||
|
|
||||||
|
@see Item_field
|
||||||
|
|
||||||
|
@param thd A pointer to the session and thread context.
|
||||||
|
|
||||||
|
@return Function return error status.
|
||||||
|
@retval TRUE is returned on an error
|
||||||
|
@retval FALSE is returned on success.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
Item_func_sp::init_result_field(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_sp::init_result_field");
|
||||||
|
|
||||||
|
LEX_STRING empty_name= { STRING_WITH_LEN("") };
|
||||||
|
|
||||||
|
TABLE_SHARE *share;
|
||||||
|
|
||||||
|
DBUG_ASSERT(m_sp == NULL);
|
||||||
|
DBUG_ASSERT(sp_result_field == NULL);
|
||||||
|
|
||||||
if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
|
if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
|
||||||
&thd->sp_func_cache, TRUE)))
|
&thd->sp_func_cache, TRUE)))
|
||||||
{
|
{
|
||||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
||||||
DBUG_RETURN(0);
|
context->process_error(thd);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!dummy_table->alias)
|
|
||||||
{
|
|
||||||
char *empty_name= (char *) "";
|
|
||||||
dummy_table->alias= empty_name;
|
|
||||||
dummy_table->maybe_null= maybe_null;
|
|
||||||
dummy_table->in_use= current_thd;
|
|
||||||
dummy_table->copy_blobs= TRUE;
|
|
||||||
dummy_table->s->table_cache_key.str = empty_name;
|
|
||||||
dummy_table->s->table_name.str= empty_name;
|
|
||||||
dummy_table->s->db.str= empty_name;
|
|
||||||
}
|
|
||||||
if (!(field= m_sp->create_result_field(max_length, name, dummy_table)))
|
|
||||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
|
||||||
|
|
||||||
DBUG_RETURN(field);
|
/*
|
||||||
|
A Field need to be attached to a Table.
|
||||||
|
Below we "create" a dummy table by initializing
|
||||||
|
the needed pointers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
share= dummy_table->s;
|
||||||
|
dummy_table->alias = "";
|
||||||
|
dummy_table->maybe_null = maybe_null;
|
||||||
|
dummy_table->in_use= thd;
|
||||||
|
dummy_table->copy_blobs= TRUE;
|
||||||
|
share->table_cache_key = empty_name;
|
||||||
|
share->table_name = empty_name;
|
||||||
|
|
||||||
|
if (!(sp_result_field= m_sp->create_result_field(max_length, name, dummy_table)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp_result_field->pack_length() > sizeof(result_buf))
|
||||||
|
{
|
||||||
|
sp_result_field->move_field(sql_alloc(sp_result_field->pack_length()));
|
||||||
|
} else {
|
||||||
|
sp_result_field->move_field(result_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_result_field->null_ptr= (uchar *) &null_value;
|
||||||
|
sp_result_field->null_bit= 1;
|
||||||
|
|
||||||
|
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Initialize local members with values from the Field interface.
|
||||||
|
|
||||||
/*
|
@note called from Item::fix_fields.
|
||||||
Execute function & store value in field
|
*/
|
||||||
|
void Item_func_sp::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
|
||||||
|
|
||||||
RETURN
|
DBUG_ASSERT(sp_result_field);
|
||||||
0 value <> NULL
|
decimals= sp_result_field->decimals();
|
||||||
1 value = NULL or error
|
max_length= sp_result_field->field_length;
|
||||||
|
collation.set(sp_result_field->charset());
|
||||||
|
maybe_null= 1;
|
||||||
|
unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Execute function & store value in field.
|
||||||
|
|
||||||
|
@return Function returns error status.
|
||||||
|
@retval FALSE on success.
|
||||||
|
@retval TRUE if an error occurred.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_sp::execute(Field **flp)
|
Item_func_sp::execute()
|
||||||
{
|
{
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
Field *f;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get field in virtual tmp table to store result. Create the field if
|
Get field in virtual tmp table to store result. Create the field if
|
||||||
invoked first time.
|
invoked first time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(f= *flp))
|
|
||||||
{
|
|
||||||
if (!(*flp= f= sp_result_field()))
|
|
||||||
{
|
|
||||||
/* Error set by sp_result_field() */
|
|
||||||
null_value= 1;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->move_field((f->pack_length() > sizeof(result_buf)) ?
|
|
||||||
sql_alloc(f->pack_length()) : result_buf);
|
|
||||||
f->null_ptr= (uchar *)&null_value;
|
|
||||||
f->null_bit= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute function and store the return value in the field. */
|
/* Execute function and store the return value in the field. */
|
||||||
|
|
||||||
if (execute_impl(thd, f))
|
if (execute_impl(thd))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
context->process_error(thd);
|
context->process_error(thd);
|
||||||
|
@ -5130,14 +5164,24 @@ Item_func_sp::execute(Field **flp)
|
||||||
|
|
||||||
/* Check that the field (the value) is not NULL. */
|
/* Check that the field (the value) is not NULL. */
|
||||||
|
|
||||||
null_value= f->is_null();
|
null_value= sp_result_field->is_null();
|
||||||
|
|
||||||
return null_value;
|
return null_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Execute function and store the return value in the field.
|
||||||
|
|
||||||
|
@note This function was intended to be the concrete implementation of
|
||||||
|
the interface function execute. This was never realized.
|
||||||
|
|
||||||
|
@return The error state.
|
||||||
|
@retval FALSE on success
|
||||||
|
@retval TRUE if an error occurred.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
|
Item_func_sp::execute_impl(THD *thd)
|
||||||
{
|
{
|
||||||
bool err_status= TRUE;
|
bool err_status= TRUE;
|
||||||
Sub_statement_state statement_state;
|
Sub_statement_state statement_state;
|
||||||
|
@ -5154,7 +5198,7 @@ Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
|
||||||
thd->security_ctx= context->security_ctx;
|
thd->security_ctx= context->security_ctx;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (find_and_check_access(thd))
|
if (sp_check_access(thd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5175,7 +5219,7 @@ Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
|
||||||
function call into binlog.
|
function call into binlog.
|
||||||
*/
|
*/
|
||||||
thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
|
thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
|
||||||
err_status= m_sp->execute_function(thd, args, arg_count, return_value_fld);
|
err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field);
|
||||||
thd->restore_sub_statement_state(&statement_state);
|
thd->restore_sub_statement_state(&statement_state);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -5190,15 +5234,9 @@ error:
|
||||||
void
|
void
|
||||||
Item_func_sp::make_field(Send_field *tmp_field)
|
Item_func_sp::make_field(Send_field *tmp_field)
|
||||||
{
|
{
|
||||||
Field *field;
|
|
||||||
DBUG_ENTER("Item_func_sp::make_field");
|
DBUG_ENTER("Item_func_sp::make_field");
|
||||||
if ((field= sp_result_field()))
|
DBUG_ASSERT(sp_result_field);
|
||||||
{
|
sp_result_field->make_field(tmp_field);
|
||||||
field->make_field(tmp_field);
|
|
||||||
delete field;
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5206,67 +5244,20 @@ Item_func_sp::make_field(Send_field *tmp_field)
|
||||||
enum enum_field_types
|
enum enum_field_types
|
||||||
Item_func_sp::field_type() const
|
Item_func_sp::field_type() const
|
||||||
{
|
{
|
||||||
Field *field;
|
|
||||||
DBUG_ENTER("Item_func_sp::field_type");
|
DBUG_ENTER("Item_func_sp::field_type");
|
||||||
|
DBUG_ASSERT(sp_result_field);
|
||||||
if (result_field)
|
DBUG_RETURN(sp_result_field->type());
|
||||||
DBUG_RETURN(result_field->type());
|
|
||||||
if ((field= sp_result_field()))
|
|
||||||
{
|
|
||||||
enum_field_types result= field->type();
|
|
||||||
delete field;
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(MYSQL_TYPE_VARCHAR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_result
|
Item_result
|
||||||
Item_func_sp::result_type() const
|
Item_func_sp::result_type() const
|
||||||
{
|
{
|
||||||
Field *field;
|
|
||||||
DBUG_ENTER("Item_func_sp::result_type");
|
DBUG_ENTER("Item_func_sp::result_type");
|
||||||
DBUG_PRINT("info", ("m_sp: 0x%lx", (long) m_sp));
|
DBUG_PRINT("info", ("m_sp = %p", m_sp));
|
||||||
|
DBUG_ASSERT(sp_result_field);
|
||||||
if (result_field)
|
DBUG_RETURN(sp_result_field->result_type());
|
||||||
DBUG_RETURN(result_field->result_type());
|
|
||||||
if ((field= sp_result_field()))
|
|
||||||
{
|
|
||||||
Item_result result= field->result_type();
|
|
||||||
delete field;
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(STRING_RESULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Item_func_sp::fix_length_and_dec()
|
|
||||||
{
|
|
||||||
Field *field;
|
|
||||||
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
|
|
||||||
|
|
||||||
if (result_field)
|
|
||||||
{
|
|
||||||
decimals= result_field->decimals();
|
|
||||||
max_length= result_field->field_length;
|
|
||||||
collation.set(result_field->charset());
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(field= sp_result_field()))
|
|
||||||
{
|
|
||||||
context->process_error(current_thd);
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
decimals= field->decimals();
|
|
||||||
max_length= field->field_length;
|
|
||||||
collation.set(field->charset());
|
|
||||||
maybe_null= 1;
|
|
||||||
delete field;
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_found_rows::val_int()
|
longlong Item_func_found_rows::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
@ -5277,57 +5268,39 @@ longlong Item_func_found_rows::val_int()
|
||||||
Field *
|
Field *
|
||||||
Item_func_sp::tmp_table_field(TABLE *t_arg)
|
Item_func_sp::tmp_table_field(TABLE *t_arg)
|
||||||
{
|
{
|
||||||
Field *field= 0;
|
|
||||||
DBUG_ENTER("Item_func_sp::tmp_table_field");
|
DBUG_ENTER("Item_func_sp::tmp_table_field");
|
||||||
|
|
||||||
if (m_sp)
|
DBUG_ASSERT(sp_result_field);
|
||||||
field= m_sp->create_result_field(max_length, (const char*) name, t_arg);
|
DBUG_RETURN(sp_result_field);
|
||||||
|
|
||||||
if (!field)
|
|
||||||
field= Item_func::tmp_table_field(t_arg);
|
|
||||||
|
|
||||||
if (!field)
|
|
||||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
|
||||||
|
|
||||||
DBUG_RETURN(field);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Find the function and check access rights to the function
|
@brief Checks if requested access to function can be granted to user.
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
find_and_check_access()
|
|
||||||
thd thread handler
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
FALSE Access granted
|
|
||||||
TRUE Requested access can't be granted or function doesn't exists
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
Checks if requested access to function can be granted to user.
|
|
||||||
If function isn't found yet, it searches function first.
|
If function isn't found yet, it searches function first.
|
||||||
If function can't be found or user don't have requested access
|
If function can't be found or user don't have requested access
|
||||||
error is raised.
|
error is raised.
|
||||||
|
|
||||||
|
@param thd thread handler
|
||||||
|
|
||||||
|
@return Indication if the access was granted or not.
|
||||||
|
@retval FALSE Access is granted.
|
||||||
|
@retval TRUE Requested access can't be granted or function doesn't exists.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_sp::find_and_check_access(THD *thd)
|
Item_func_sp::sp_check_access(THD *thd)
|
||||||
{
|
{
|
||||||
if (! m_sp && ! (m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
|
DBUG_ENTER("Item_func_sp::sp_check_access");
|
||||||
&thd->sp_func_cache, TRUE)))
|
DBUG_ASSERT(m_sp);
|
||||||
{
|
|
||||||
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (check_routine_access(thd, EXECUTE_ACL,
|
if (check_routine_access(thd, EXECUTE_ACL,
|
||||||
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
||||||
return TRUE;
|
DBUG_RETURN(TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return FALSE;
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5335,9 +5308,25 @@ bool
|
||||||
Item_func_sp::fix_fields(THD *thd, Item **ref)
|
Item_func_sp::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
bool res;
|
bool res;
|
||||||
|
DBUG_ENTER("Item_func_sp::fix_fields");
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
We must call init_result_field before Item_func::fix_fields()
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
res= Item_func::fix_fields(thd, ref);
|
res= Item_func::fix_fields(thd, ref);
|
||||||
if (!res && thd->lex->view_prepare_mode)
|
|
||||||
|
if (res)
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
|
if (thd->lex->view_prepare_mode)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Here we check privileges of the stored routine only during view
|
Here we check privileges of the stored routine only during view
|
||||||
|
@ -5349,15 +5338,17 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
||||||
good idea especially if the view has SQL SECURITY DEFINER and
|
good idea especially if the view has SQL SECURITY DEFINER and
|
||||||
the used stored procedure has SQL SECURITY DEFINER.
|
the used stored procedure has SQL SECURITY DEFINER.
|
||||||
*/
|
*/
|
||||||
res= find_and_check_access(thd);
|
res= sp_check_access(thd);
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
/*
|
||||||
|
Try to set and restore the security context to see whether it's valid
|
||||||
|
*/
|
||||||
Security_context *save_secutiry_ctx;
|
Security_context *save_secutiry_ctx;
|
||||||
if (!res && !(res= set_routine_security_ctx(thd, m_sp, false,
|
res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
|
||||||
&save_secutiry_ctx)))
|
if (!res)
|
||||||
{
|
|
||||||
sp_restore_security_context(thd, save_secutiry_ctx);
|
sp_restore_security_context(thd, save_secutiry_ctx);
|
||||||
}
|
|
||||||
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
||||||
}
|
}
|
||||||
return res;
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1434,12 +1434,15 @@ private:
|
||||||
sp_name *m_name;
|
sp_name *m_name;
|
||||||
mutable sp_head *m_sp;
|
mutable sp_head *m_sp;
|
||||||
TABLE *dummy_table;
|
TABLE *dummy_table;
|
||||||
Field *result_field;
|
|
||||||
char result_buf[64];
|
char result_buf[64];
|
||||||
|
/*
|
||||||
|
The result field of the concrete stored function.
|
||||||
|
*/
|
||||||
|
Field *sp_result_field;
|
||||||
|
|
||||||
bool execute(Field **flp);
|
bool execute();
|
||||||
bool execute_impl(THD *thd, Field *return_value_fld);
|
bool execute_impl(THD *thd);
|
||||||
Field *sp_result_field(void) const;
|
bool init_result_field(THD *thd);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -1465,23 +1468,23 @@ public:
|
||||||
|
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
{
|
{
|
||||||
if (execute(&result_field))
|
if (execute())
|
||||||
return (longlong) 0;
|
return (longlong) 0;
|
||||||
return result_field->val_int();
|
return sp_result_field->val_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
double val_real()
|
double val_real()
|
||||||
{
|
{
|
||||||
if (execute(&result_field))
|
if (execute())
|
||||||
return 0.0;
|
return 0.0;
|
||||||
return result_field->val_real();
|
return sp_result_field->val_real();
|
||||||
}
|
}
|
||||||
|
|
||||||
my_decimal *val_decimal(my_decimal *dec_buf)
|
my_decimal *val_decimal(my_decimal *dec_buf)
|
||||||
{
|
{
|
||||||
if (execute(&result_field))
|
if (execute())
|
||||||
return NULL;
|
return NULL;
|
||||||
return result_field->val_decimal(dec_buf);
|
return sp_result_field->val_decimal(dec_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
String *val_str(String *str)
|
String *val_str(String *str)
|
||||||
|
@ -1490,7 +1493,7 @@ public:
|
||||||
char buff[20];
|
char buff[20];
|
||||||
buf.set(buff, 20, str->charset());
|
buf.set(buff, 20, str->charset());
|
||||||
buf.length(0);
|
buf.length(0);
|
||||||
if (execute(&result_field))
|
if (execute())
|
||||||
return NULL;
|
return NULL;
|
||||||
/*
|
/*
|
||||||
result_field will set buf pointing to internal buffer
|
result_field will set buf pointing to internal buffer
|
||||||
|
@ -1498,7 +1501,7 @@ public:
|
||||||
when SP is executed. In order to prevent occasional
|
when SP is executed. In order to prevent occasional
|
||||||
corruption of returned value, we make here a copy.
|
corruption of returned value, we make here a copy.
|
||||||
*/
|
*/
|
||||||
result_field->val_str(&buf);
|
sp_result_field->val_str(&buf);
|
||||||
str->copy(buf);
|
str->copy(buf);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -1506,11 +1509,11 @@ public:
|
||||||
virtual bool change_context_processor(byte *cntx)
|
virtual bool change_context_processor(byte *cntx)
|
||||||
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||||
|
|
||||||
void fix_length_and_dec();
|
bool sp_check_access(THD * thd);
|
||||||
bool find_and_check_access(THD * thd);
|
|
||||||
virtual enum Functype functype() const { return FUNC_SP; }
|
virtual enum Functype functype() const { return FUNC_SP; }
|
||||||
|
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
|
void fix_length_and_dec(void);
|
||||||
bool is_expensive() { return 1; }
|
bool is_expensive() { return 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue