summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <malff/marcsql@weblab.(none)>2006-11-16 09:03:47 -0700
committerunknown <malff/marcsql@weblab.(none)>2006-11-16 09:03:47 -0700
commit2975d65cd86dea288d968c55fd0ffd177a92f390 (patch)
tree97166381743b2b830ba8d62a7acf0f37382a39ac /sql
parent12ed25e7e38c40c231b4752b918bcb5937d900bd (diff)
downloadmariadb-git-2975d65cd86dea288d968c55fd0ffd177a92f390.tar.gz
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could only accept a constant for some parameters. After this change, this restriction has been removed. An implication is that these functions can also be used in prepared statements. The change consist of changing the following classes: - Item_func_benchmark - Item_func_encode - Item_func_decode - Item_func_format to: - only accept Item* in the constructor, - and evaluate arguments during calls to val_xxx() which fits the general design of all the other functions. The 'TODO' items identified in item_create.cc during the work done for Bug 21114 are addressed by this fix, as a natural consequence of aligning the design. In the 'func_str' test, a single very long test line involving an explain extended select with many functions has been rewritten into multiple separate tests, to improve maintainability. The result of explain extended select decode(encode(...)) has changed, since the encode and decode functions now print all their parameters. mysql-test/r/func_str.result: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) mysql-test/r/parser.result: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) mysql-test/r/ps.result: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) mysql-test/t/func_str.test: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) mysql-test/t/parser.test: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) mysql-test/t/ps.test: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) sql/item_create.cc: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) sql/item_func.cc: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) sql/item_func.h: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) sql/item_strfunc.cc: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions) sql/item_strfunc.h: Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Diffstat (limited to 'sql')
-rw-r--r--sql/item_create.cc42
-rw-r--r--sql/item_func.cc26
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/item_strfunc.cc83
-rw-r--r--sql/item_strfunc.h18
5 files changed, 91 insertions, 83 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 7722ce28d4a..da8954910c8 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -2612,15 +2612,8 @@ Create_func_benchmark Create_func_benchmark::s_singleton;
Item*
Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2)
{
- /* TODO: Known limitation, see Bug#22684 */
- if ((arg1->type() != Item::INT_ITEM) || ! arg1->basic_const_item())
- {
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "BENCHMARK");
- return NULL;
- }
-
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- return new (thd->mem_root) Item_func_benchmark(arg1->val_int(), arg2);
+ return new (thd->mem_root) Item_func_benchmark(arg1, arg2);
}
@@ -2887,17 +2880,7 @@ Create_func_decode Create_func_decode::s_singleton;
Item*
Create_func_decode::create(THD *thd, Item *arg1, Item *arg2)
{
- /* TODO: Known limitation, see Bug#22684 */
- if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item())
- {
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "DECODE");
- return NULL;
- }
-
- String dummy;
- String *val = arg2->val_str(& dummy);
- DBUG_ASSERT(val);
- return new (thd->mem_root) Item_func_decode(arg1, val->c_ptr());
+ return new (thd->mem_root) Item_func_decode(arg1, arg2);
}
@@ -3033,17 +3016,7 @@ Create_func_encode Create_func_encode::s_singleton;
Item*
Create_func_encode::create(THD *thd, Item *arg1, Item *arg2)
{
- /* TODO: Known limitation, see Bug#22684 */
- if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item())
- {
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "ENCODE");
- return NULL;
- }
-
- String dummy;
- String *val = arg2->val_str(& dummy);
- DBUG_ASSERT(val);
- return new (thd->mem_root) Item_func_encode(arg1, val->c_ptr());
+ return new (thd->mem_root) Item_func_encode(arg1, arg2);
}
@@ -3235,14 +3208,7 @@ Create_func_format Create_func_format::s_singleton;
Item*
Create_func_format::create(THD *thd, Item *arg1, Item *arg2)
{
- /* TODO: Known limitation, see Bug#22684 */
- if ((arg2->type() != Item::INT_ITEM) || ! arg2->basic_const_item())
- {
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "FORMAT");
- return NULL;
- }
-
- return new (thd->mem_root) Item_func_format(arg1, arg2->val_int());
+ return new (thd->mem_root) Item_func_format(arg1, arg2);
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4a069e662f9..9721c5eab6a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3390,18 +3390,28 @@ longlong Item_func_benchmark::val_int()
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff), &my_charset_bin);
THD *thd=current_thd;
+ ulong loop_count;
+ loop_count= args[0]->val_int();
+
+ if (args[0]->null_value)
+ {
+ null_value= 1;
+ return 0;
+ }
+
+ null_value=0;
for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
{
- switch (args[0]->result_type()) {
+ switch (args[1]->result_type()) {
case REAL_RESULT:
- (void) args[0]->val_real();
+ (void) args[1]->val_real();
break;
case INT_RESULT:
- (void) args[0]->val_int();
+ (void) args[1]->val_int();
break;
case STRING_RESULT:
- (void) args[0]->val_str(&tmp);
+ (void) args[1]->val_str(&tmp);
break;
case ROW_RESULT:
default:
@@ -3417,13 +3427,9 @@ longlong Item_func_benchmark::val_int()
void Item_func_benchmark::print(String *str)
{
str->append(STRING_WITH_LEN("benchmark("));
- char buffer[20];
- // my_charset_bin is good enough for numbers
- String st(buffer, sizeof(buffer), &my_charset_bin);
- st.set((ulonglong)loop_count, &my_charset_bin);
- str->append(st);
- str->append(',');
args[0]->print(str);
+ str->append(',');
+ args[1]->print(str);
str->append(')');
}
diff --git a/sql/item_func.h b/sql/item_func.h
index f820a89b5b6..65a1686bf44 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -924,10 +924,9 @@ public:
class Item_func_benchmark :public Item_int_func
{
- ulong loop_count;
public:
- Item_func_benchmark(ulong loop_count_arg,Item *expr)
- :Item_int_func(expr), loop_count(loop_count_arg)
+ Item_func_benchmark(Item *count_expr, Item *expr)
+ :Item_int_func(count_expr, expr)
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index bf837f6720b..6f896eaee63 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1621,21 +1621,33 @@ String *Item_func_encrypt::val_str(String *str)
void Item_func_encode::fix_length_and_dec()
{
max_length=args[0]->max_length;
- maybe_null=args[0]->maybe_null;
+ maybe_null=args[0]->maybe_null || args[1]->maybe_null;
collation.set(&my_charset_bin);
}
String *Item_func_encode::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
String *res;
+ char pw_buff[80];
+ String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info);
+ String *password;
+ DBUG_ASSERT(fixed == 1);
+
if (!(res=args[0]->val_str(str)))
{
null_value=1; /* purecov: inspected */
return 0; /* purecov: inspected */
}
+
+ if (!(password=args[1]->val_str(& tmp_pw_value)))
+ {
+ null_value=1;
+ return 0;
+ }
+
null_value=0;
res=copy_if_not_alloced(str,res,res->length());
+ SQL_CRYPT sql_crypt(password->ptr());
sql_crypt.init();
sql_crypt.encode((char*) res->ptr(),res->length());
res->set_charset(&my_charset_bin);
@@ -1644,15 +1656,27 @@ String *Item_func_encode::val_str(String *str)
String *Item_func_decode::val_str(String *str)
{
- DBUG_ASSERT(fixed == 1);
String *res;
+ char pw_buff[80];
+ String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info);
+ String *password;
+ DBUG_ASSERT(fixed == 1);
+
if (!(res=args[0]->val_str(str)))
{
null_value=1; /* purecov: inspected */
return 0; /* purecov: inspected */
}
+
+ if (!(password=args[1]->val_str(& tmp_pw_value)))
+ {
+ null_value=1;
+ return 0;
+ }
+
null_value=0;
res=copy_if_not_alloced(str,res,res->length());
+ SQL_CRYPT sql_crypt(password->ptr());
sql_crypt.init();
sql_crypt.decode((char*) res->ptr(),res->length());
return res;
@@ -1822,9 +1846,19 @@ String *Item_func_soundex::val_str(String *str)
** This should be 'internationalized' sometimes.
*/
-Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
+const int FORMAT_MAX_DECIMALS= 30;
+
+Item_func_format::Item_func_format(Item *org, Item *dec)
+: Item_str_func(org, dec)
+{
+}
+
+void Item_func_format::fix_length_and_dec()
{
- decimals=(uint) set_zone(dec,0,30);
+ collation.set(default_charset());
+ uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
+ max_length= ((char_length + (char_length-args[0]->decimals)/3) *
+ collation.collation->mbmaxlen);
}
@@ -1835,10 +1869,25 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
String *Item_func_format::val_str(String *str)
{
- uint32 length, str_length ,dec;
+ uint32 length;
+ uint32 str_length;
+ /* Number of decimal digits */
+ int dec;
+ /* Number of characters used to represent the decimals, including '.' */
+ uint32 dec_length;
int diff;
DBUG_ASSERT(fixed == 1);
- dec= decimals ? decimals+1 : 0;
+
+ dec= args[1]->val_int();
+ if (args[1]->null_value)
+ {
+ null_value=1;
+ return NULL;
+ }
+
+ dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
+ dec_length= dec ? dec+1 : 0;
+ null_value=0;
if (args[0]->result_type() == DECIMAL_RESULT ||
args[0]->result_type() == INT_RESULT)
@@ -1847,7 +1896,7 @@ String *Item_func_format::val_str(String *str)
res= args[0]->val_decimal(&dec_val);
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- my_decimal_round(E_DEC_FATAL_ERROR, res, decimals, false, &rnd_dec);
+ my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
str_length= str->length();
if (rnd_dec.sign())
@@ -1858,9 +1907,9 @@ String *Item_func_format::val_str(String *str)
double nr= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- nr= my_double_round(nr, decimals, FALSE);
+ nr= my_double_round(nr, dec, FALSE);
/* Here default_charset() is right as this is not an automatic conversion */
- str->set_real(nr,decimals, default_charset());
+ str->set_real(nr, dec, default_charset());
if (isnan(nr))
return str;
str_length=str->length();
@@ -1868,13 +1917,13 @@ String *Item_func_format::val_str(String *str)
str_length--; // Don't count sign
}
/* We need this test to handle 'nan' values */
- if (str_length >= dec+4)
+ if (str_length >= dec_length+4)
{
char *tmp,*pos;
- length= str->length()+(diff=((int)(str_length- dec-1))/3);
+ length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
str= copy_if_not_alloced(&tmp_str,str,length);
str->length(length);
- tmp= (char*) str->ptr()+length - dec-1;
+ tmp= (char*) str->ptr()+length - dec_length-1;
for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
pos[0]= pos[-diff];
while (diff)
@@ -1898,12 +1947,8 @@ void Item_func_format::print(String *str)
{
str->append(STRING_WITH_LEN("format("));
args[0]->print(str);
- str->append(',');
- // my_charset_bin is good enough for numbers
- char buffer[20];
- String st(buffer, sizeof(buffer), &my_charset_bin);
- st.set((ulonglong)decimals, &my_charset_bin);
- str->append(st);
+ str->append(',');
+ args[1]->print(str);
str->append(')');
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 2adccd212b3..423baae371b 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -360,11 +360,9 @@ public:
class Item_func_encode :public Item_str_func
{
- protected:
- SQL_CRYPT sql_crypt;
public:
- Item_func_encode(Item *a, char *seed):
- Item_str_func(a),sql_crypt(seed) {}
+ Item_func_encode(Item *a, Item *seed):
+ Item_str_func(a, seed) {}
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "encode"; }
@@ -374,7 +372,7 @@ public:
class Item_func_decode :public Item_func_encode
{
public:
- Item_func_decode(Item *a, char *seed): Item_func_encode(a,seed) {}
+ Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {}
String *val_str(String *);
const char *func_name() const { return "decode"; }
};
@@ -507,15 +505,9 @@ class Item_func_format :public Item_str_func
{
String tmp_str;
public:
- Item_func_format(Item *org,int dec);
+ Item_func_format(Item *org, Item *dec);
String *val_str(String *);
- void fix_length_and_dec()
- {
- collation.set(default_charset());
- uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
- max_length= ((char_length + (char_length-args[0]->decimals)/3) *
- collation.collation->mbmaxlen);
- }
+ void fix_length_and_dec();
const char *func_name() const { return "format"; }
void print(String *);
};