summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2006-11-13 13:13:44 -0500
committerunknown <cmiller@zippy.cornsilk.net>2006-11-13 13:13:44 -0500
commit154c6e06775d6e644fd4e5f863104ab566fc4a68 (patch)
tree0ca8ebb00dc5407cb091951dbb2f6ce33551b95b /sql
parente948c64ff52fda43d2a7cb59bc631e53051adc05 (diff)
downloadmariadb-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.cc62
-rw-r--r--sql/udf_example.c30
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 */