Bug#18761: constant expression as UDF parameters not passed in as constant
The code that set up data to be passed to user-defined functions was very old and analyzed the "Type" of the data that was passed into the UDF, when it really should analyze the "return_type", which is hard-coded for simple Items and works correctly for complex ones like functions. --- Added test at Sergei's behest.
This commit is contained in:
parent
e8c7f19179
commit
8471897fbc
@ -15,3 +15,11 @@
|
|||||||
45214442pBGT9KuZEGixBH71jTzbOA
|
45214442pBGT9KuZEGixBH71jTzbOA
|
||||||
45214a07hVsIGwvwa-WrO-jpeaSwVw
|
45214a07hVsIGwvwa-WrO-jpeaSwVw
|
||||||
452a92d0-31-8wSzSfZi165fcGcXPA
|
452a92d0-31-8wSzSfZi165fcGcXPA
|
||||||
|
454bb488ijVLOUK_GFjcoISE0GxPUA
|
||||||
|
454bb9a8AwlGRC_wWLS2sNMoRBMRGw
|
||||||
|
454c946ciQoR4dfTBZ0RTBmGJKp6lw
|
||||||
|
454f6e7eAnfLD9OCbGr5X9KiKvfKcQ
|
||||||
|
454f704bJiJy0_Nx2drY9P5kK3uOzg
|
||||||
|
454fa71cxshxszXJQYa9jbo0-_hAHw
|
||||||
|
4550b0ceIcozdgQhWFUTAtWkN196lA
|
||||||
|
4558b3d73Cxjlb7Wv1oytdSTthxDfw
|
||||||
|
@ -115,3 +115,38 @@ DROP FUNCTION sequence;
|
|||||||
DROP FUNCTION lookup;
|
DROP FUNCTION lookup;
|
||||||
DROP FUNCTION reverse_lookup;
|
DROP FUNCTION reverse_lookup;
|
||||||
DROP FUNCTION avgcost;
|
DROP FUNCTION avgcost;
|
||||||
|
CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
|
||||||
|
select
|
||||||
|
is_const(3) as const,
|
||||||
|
is_const(3.14) as const,
|
||||||
|
is_const('fnord') as const,
|
||||||
|
is_const(2+3) as const,
|
||||||
|
is_const(rand()) as 'nc rand()',
|
||||||
|
is_const(sin(3.14)) as const,
|
||||||
|
is_const(upper('test')) as const;
|
||||||
|
const const const const nc rand() const const
|
||||||
|
const const const const not const const const
|
||||||
|
create table bug18761 (n int);
|
||||||
|
insert into bug18761 values (null),(2);
|
||||||
|
select
|
||||||
|
is_const(3) as const,
|
||||||
|
is_const(3.14) as const,
|
||||||
|
is_const('fnord') as const,
|
||||||
|
is_const(2+3) as const,
|
||||||
|
is_const(2+n) as 'nc 2+n ',
|
||||||
|
is_const(sin(n)) as 'nc sin(n)',
|
||||||
|
is_const(sin(3.14)) as const,
|
||||||
|
is_const(upper('test')) as const,
|
||||||
|
is_const(rand()) as 'nc rand()',
|
||||||
|
is_const(n) as 'nc n ',
|
||||||
|
is_const(is_const(n)) as 'nc ic?(n)',
|
||||||
|
is_const(is_const('c')) as const
|
||||||
|
from
|
||||||
|
bug18761;
|
||||||
|
const const const const nc 2+n nc sin(n) const const nc rand() nc n nc ic?(n) const
|
||||||
|
const const const const not const not const const const not const not const not const const
|
||||||
|
const const const const not const not const const const not const not const not const const
|
||||||
|
drop table bug18761;
|
||||||
|
select is_const((1,2,3));
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
drop function if exists is_const;
|
||||||
|
@ -143,4 +143,41 @@ DROP FUNCTION lookup;
|
|||||||
DROP FUNCTION reverse_lookup;
|
DROP FUNCTION reverse_lookup;
|
||||||
DROP FUNCTION avgcost;
|
DROP FUNCTION avgcost;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#18761: constant expression as UDF parameters not passed in as constant
|
||||||
|
#
|
||||||
|
--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
|
||||||
|
eval CREATE FUNCTION is_const RETURNS STRING SONAME "$UDF_EXAMPLE_LIB";
|
||||||
|
|
||||||
|
select
|
||||||
|
is_const(3) as const,
|
||||||
|
is_const(3.14) as const,
|
||||||
|
is_const('fnord') as const,
|
||||||
|
is_const(2+3) as const,
|
||||||
|
is_const(rand()) as 'nc rand()',
|
||||||
|
is_const(sin(3.14)) as const,
|
||||||
|
is_const(upper('test')) as const;
|
||||||
|
|
||||||
|
create table bug18761 (n int);
|
||||||
|
insert into bug18761 values (null),(2);
|
||||||
|
select
|
||||||
|
is_const(3) as const,
|
||||||
|
is_const(3.14) as const,
|
||||||
|
is_const('fnord') as const,
|
||||||
|
is_const(2+3) as const,
|
||||||
|
is_const(2+n) as 'nc 2+n ',
|
||||||
|
is_const(sin(n)) as 'nc sin(n)',
|
||||||
|
is_const(sin(3.14)) as const,
|
||||||
|
is_const(upper('test')) as const,
|
||||||
|
is_const(rand()) as 'nc rand()',
|
||||||
|
is_const(n) as 'nc n ',
|
||||||
|
is_const(is_const(n)) as 'nc ic?(n)',
|
||||||
|
is_const(is_const('c')) as const
|
||||||
|
from
|
||||||
|
bug18761;
|
||||||
|
drop table bug18761;
|
||||||
|
|
||||||
|
--error 1241
|
||||||
|
select is_const((1,2,3));
|
||||||
|
|
||||||
|
drop function if exists is_const;
|
||||||
|
@ -2683,39 +2683,47 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
|||||||
char *to=num_buffer;
|
char *to=num_buffer;
|
||||||
for (uint i=0; i < arg_count; i++)
|
for (uint i=0; i < arg_count; i++)
|
||||||
{
|
{
|
||||||
f_args.args[i]=0;
|
/*
|
||||||
|
For a constant argument i, args->args[i] points to the argument value.
|
||||||
|
For non-constant, args->args[i] is NULL.
|
||||||
|
*/
|
||||||
|
f_args.args[i]= NULL; /* Non-const unless updated below. */
|
||||||
|
|
||||||
f_args.lengths[i]= arguments[i]->max_length;
|
f_args.lengths[i]= arguments[i]->max_length;
|
||||||
f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
|
f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
|
||||||
f_args.attributes[i]= arguments[i]->name;
|
f_args.attributes[i]= arguments[i]->name;
|
||||||
f_args.attribute_lengths[i]= arguments[i]->name_length;
|
f_args.attribute_lengths[i]= arguments[i]->name_length;
|
||||||
|
|
||||||
switch(arguments[i]->type()) {
|
if (arguments[i]->const_item())
|
||||||
case Item::STRING_ITEM: // Constant string !
|
|
||||||
{
|
{
|
||||||
String *res=arguments[i]->val_str(&buffers[i]);
|
if (arguments[i]->null_value)
|
||||||
if (arguments[i]->null_value)
|
continue;
|
||||||
continue;
|
|
||||||
f_args.args[i]= (char*) res->ptr();
|
switch (arguments[i]->result_type())
|
||||||
break;
|
{
|
||||||
}
|
case STRING_RESULT:
|
||||||
case Item::INT_ITEM:
|
case DECIMAL_RESULT:
|
||||||
*((longlong*) to) = arguments[i]->val_int();
|
{
|
||||||
if (!arguments[i]->null_value)
|
String *res= arguments[i]->val_str(&buffers[i]);
|
||||||
{
|
f_args.args[i]= (char*) res->ptr();
|
||||||
f_args.args[i]=to;
|
break;
|
||||||
to+= ALIGN_SIZE(sizeof(longlong));
|
}
|
||||||
}
|
case INT_RESULT:
|
||||||
break;
|
*((longlong*) to)= arguments[i]->val_int();
|
||||||
case Item::REAL_ITEM:
|
f_args.args[i]= to;
|
||||||
*((double*) to)= arguments[i]->val_real();
|
to+= ALIGN_SIZE(sizeof(longlong));
|
||||||
if (!arguments[i]->null_value)
|
break;
|
||||||
{
|
case REAL_RESULT:
|
||||||
f_args.args[i]=to;
|
*((double*) to)= arguments[i]->val_real();
|
||||||
to+= ALIGN_SIZE(sizeof(double));
|
f_args.args[i]= to;
|
||||||
}
|
to+= ALIGN_SIZE(sizeof(double));
|
||||||
break;
|
break;
|
||||||
default: // Skip these
|
case ROW_RESULT:
|
||||||
break;
|
default:
|
||||||
|
// This case should never be chosen
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thd->net.last_error[0]=0;
|
thd->net.last_error[0]=0;
|
||||||
|
@ -165,6 +165,9 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error
|
|||||||
void avgcost_clear( UDF_INIT* initid, char* is_null, char *error );
|
void avgcost_clear( UDF_INIT* initid, char* is_null, char *error );
|
||||||
void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
|
void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
|
||||||
double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
|
double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
|
||||||
|
my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
|
||||||
|
char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long
|
||||||
|
*length, char *is_null, char *error);
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -1075,4 +1078,31 @@ char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)),
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
|
||||||
|
{
|
||||||
|
if (args->arg_count != 1)
|
||||||
|
{
|
||||||
|
strmov(message, "IS_CONST accepts only one argument");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
initid->ptr= (args->args[0] != NULL) ? 1 : 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long
|
||||||
|
*length, char *is_null, char *error)
|
||||||
|
{
|
||||||
|
if (initid->ptr != 0) {
|
||||||
|
sprintf(result, "const");
|
||||||
|
} else {
|
||||||
|
sprintf(result, "not const");
|
||||||
|
}
|
||||||
|
*is_null= 0;
|
||||||
|
*length= strlen(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_DLOPEN */
|
#endif /* HAVE_DLOPEN */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user