List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:November 4 2006 2:24pm
Subject:bk commit into 5.0 tree (cmiller:1.2333) BUG#18761
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of cmiller. When cmiller does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-11-04 08:23:56-05:00, cmiller@stripped +5 -0
  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 neglected 
  to take into account some things that could be parameters to a function, 
  namely some kinds of numbers and results of other functions (including the
  implicit ones of Sum for  K0+K1, e.g.).
  
  Added those and inserted a warning to go to the debug log, in case we add 
  more types and such in the future and neglect to account for them.  (I'm 
  wary of ASSERTing this to be true.)
  
  Also, try out Doxygen for the new UDF functions.

  BitKeeper/etc/collapsed@stripped, 2006-11-04 07:43:21-05:00, cmiller@stripped +2
-0

  mysql-test/r/udf.result@stripped, 2006-11-04 08:23:54-05:00, cmiller@stripped +31
-0
    Verify that various arguments work.

  mysql-test/t/udf.test@stripped, 2006-11-04 08:23:54-05:00, cmiller@stripped +32 -0
    Verify that various arguments work.

  sql/item_func.cc@stripped, 2006-11-04 08:23:54-05:00, cmiller@stripped +26 -6
    For function-Items, test whether it is constant and set the struct members 
    for the UDF parameter appropriately.

  sql/udf_example.c@stripped, 2006-11-04 08:23:54-05:00, cmiller@stripped +48 -1
    Include a simple function that is useful in testing.
    
    Try out Doxygen.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	cmiller
# Host:	zippy.cornsilk.net
# Root:	/home/cmiller/work/mysql/bug18761/my50-bug18761

--- 1.309/sql/item_func.cc	2006-11-04 08:24:00 -05:00
+++ 1.310/sql/item_func.cc	2006-11-04 08:24:00 -05:00
@@ -2683,13 +2683,19 @@ udf_handler::fix_fields(THD *thd, Item_r
     char *to=num_buffer;
     for (uint i=0; i < arg_count; i++)
     {
-      f_args.args[i]=0;
+      Item::Type argument_type= arguments[i]->type();
+      /*
+       For a constant argument i, args->args[i] points to the argument value. 
+       For a non-constant argument, args->args[i] is 0.
+      */
+      f_args.args[i]= 0;         /* 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()) {
+      switch (argument_type) {
       case Item::STRING_ITEM:			// Constant string !
       {
 	String *res=arguments[i]->val_str(&buffers[i]);
@@ -2698,6 +2704,16 @@ udf_handler::fix_fields(THD *thd, Item_r
 	f_args.args[i]=    (char*) res->ptr();
 	break;
       }
+      case Item::FUNC_ITEM:  /* storing as string */
+      case Item::DECIMAL_ITEM:    /* storing as string */
+      {
+	String *res=arguments[i]->val_str(&buffers[i]);
+	if (arguments[i]->null_value)
+	  continue;
+        if (arguments[i]->const_item())
+          f_args.args[i]= (char*) res->ptr();
+	break;
+      }
       case Item::INT_ITEM:
 	*((longlong*) to) = arguments[i]->val_int();
 	if (!arguments[i]->null_value)
@@ -2715,6 +2731,10 @@ udf_handler::fix_fields(THD *thd, Item_r
 	}
 	break;
       default:					// Skip these
+        if (arguments[i]->const_item() != 0)
+        {
+          DBUG_PRINT("warning", ("Item with Type %d is const, yet we don't set the
\"args\" to its value"));
+        }
 	break;
       }
     }

--- 1.30/sql/udf_example.c	2006-11-04 08:24:00 -05:00
+++ 1.31/sql/udf_example.c	2006-11-04 08:24:00 -05:00
@@ -165,6 +165,8 @@ void avgcost_reset( UDF_INIT* initid, UD
 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);
 
 
 /*************************************************************************
@@ -1048,7 +1050,7 @@ my_bool myfunc_argument_name_init(UDF_IN
 {
   if (args->arg_count != 1)
   {
-    strmov(message,"myfunc_argument_name_init accepts only one argument");
+    strmov(message,"MYFUNC_ARGUMENT_NAME accepts only one argument");
     return 1;
   }
   initid->max_length= args->attribute_lengths[0];
@@ -1074,5 +1076,50 @@ char *myfunc_argument_name(UDF_INIT *ini
   result[*length]= 0;
   return result;
 }
+
+
+/**
+ * Initialize the values for a run of IS_CONST.  Like all UDF init functions,
+ * this one is run for each column at the top of a result set.  This in 
+ * particular sets the available "ptr" member of a struct, which is unique to 
+ * this column of the result set, and we'll use the "ptr" member later.
+ * The args point to a constant value for a result set, and if it's NULL then
+ * the argument for the function in this column is not constant.
+ *
+ * @param initid  Data carried with this column for the duration of the 
+ * result set
+ * @param args  Information about the call of this function.
+ * @param message[out]  A description in case of an error in the arguments.
+ *
+ * @see is_const()
+ */
+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;
+}
+
+/**
+ * Use the previously-set "ptr" member to fill the result.
+ *
+ * @see is_const_init()
+ */
+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 */

--- 1.10/BitKeeper/etc/collapsed	2006-11-04 08:24:00 -05:00
+++ 1.11/BitKeeper/etc/collapsed	2006-11-04 08:24:00 -05:00
@@ -15,3 +15,5 @@
 45214442pBGT9KuZEGixBH71jTzbOA
 45214a07hVsIGwvwa-WrO-jpeaSwVw
 452a92d0-31-8wSzSfZi165fcGcXPA
+454bb488ijVLOUK_GFjcoISE0GxPUA
+454bb9a8AwlGRC_wWLS2sNMoRBMRGw

--- 1.7/mysql-test/r/udf.result	2006-11-04 08:24:00 -05:00
+++ 1.8/mysql-test/r/udf.result	2006-11-04 08:24:00 -05:00
@@ -115,3 +115,34 @@ DROP FUNCTION sequence;
 DROP FUNCTION lookup;
 DROP FUNCTION reverse_lookup;
 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   '
+from
+bug18761;
+const	const	const	const	nc  2+n  	nc sin(n)	const	const	nc rand()	nc   n   
+const	const	const	const	not const	not const	const	const	not const	not const
+const	const	const	const	not const	not const	const	const	not const	not const
+drop table bug18761;
+drop function if exists is_const;

--- 1.8/mysql-test/t/udf.test	2006-11-04 08:24:00 -05:00
+++ 1.9/mysql-test/t/udf.test	2006-11-04 08:24:00 -05:00
@@ -143,4 +143,36 @@ DROP FUNCTION lookup;
 DROP FUNCTION reverse_lookup;
 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   '
+from
+  bug18761;
+drop table bug18761;
+
+drop function if exists is_const;
Thread
bk commit into 5.0 tree (cmiller:1.2333) BUG#18761Chad MILLER4 Nov