diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2006-11-13 13:13:44 -0500 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2006-11-13 13:13:44 -0500 |
commit | 154c6e06775d6e644fd4e5f863104ab566fc4a68 (patch) | |
tree | 0ca8ebb00dc5407cb091951dbb2f6ce33551b95b /sql | |
parent | e948c64ff52fda43d2a7cb59bc631e53051adc05 (diff) | |
download | mariadb-git-154c6e06775d6e644fd4e5f863104ab566fc4a68.tar.gz |
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.
mysql-test/r/udf.result:
Verify that various arguments work.
---
Added test at Sergei's behest.
mysql-test/t/udf.test:
Verify that various arguments work.
---
Added test at Sergei's behest.
sql/item_func.cc:
For function-Items, test whether it is constant and set the struct members
for the UDF parameter appropriately.
Replace tabs with spaces in affected code.
sql/udf_example.c:
Include a simple function that is useful in testing.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 62 | ||||
-rw-r--r-- | sql/udf_example.c | 30 |
2 files changed, 65 insertions, 27 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index a294bbd7a71..8e6b4d82b1d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2683,39 +2683,47 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, char *to=num_buffer; 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.maybe_null[i]= (char) arguments[i]->maybe_null; f_args.attributes[i]= arguments[i]->name; f_args.attribute_lengths[i]= arguments[i]->name_length; - switch(arguments[i]->type()) { - case Item::STRING_ITEM: // Constant string ! + if (arguments[i]->const_item()) { - String *res=arguments[i]->val_str(&buffers[i]); - if (arguments[i]->null_value) - continue; - f_args.args[i]= (char*) res->ptr(); - break; - } - case Item::INT_ITEM: - *((longlong*) to) = arguments[i]->val_int(); - if (!arguments[i]->null_value) - { - f_args.args[i]=to; - to+= ALIGN_SIZE(sizeof(longlong)); - } - break; - case Item::REAL_ITEM: - *((double*) to)= arguments[i]->val_real(); - if (!arguments[i]->null_value) - { - f_args.args[i]=to; - to+= ALIGN_SIZE(sizeof(double)); - } - break; - default: // Skip these - break; + if (arguments[i]->null_value) + continue; + + switch (arguments[i]->result_type()) + { + case STRING_RESULT: + case DECIMAL_RESULT: + { + String *res= arguments[i]->val_str(&buffers[i]); + f_args.args[i]= (char*) res->ptr(); + break; + } + case INT_RESULT: + *((longlong*) to)= arguments[i]->val_int(); + f_args.args[i]= to; + to+= ALIGN_SIZE(sizeof(longlong)); + break; + case REAL_RESULT: + *((double*) to)= arguments[i]->val_real(); + f_args.args[i]= to; + to+= ALIGN_SIZE(sizeof(double)); + break; + case ROW_RESULT: + default: + // This case should never be chosen + DBUG_ASSERT(0); + break; + } } } thd->net.last_error[0]=0; diff --git a/sql/udf_example.c b/sql/udf_example.c index 2fa7474eb16..a4f7eddd302 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -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_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 ); +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; } + + +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 */ |