summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2021-09-06 09:37:33 +0200
committerSergei Golubchik <serg@mariadb.org>2021-09-06 10:07:33 +0200
commit3866c8a541a8068c01b5369fdae9c2be961f4b53 (patch)
tree29f425cad917432e478938e92b0f8b62b7e8230f
parent2edc313837b9d35be2837756bb74d1e827e49319 (diff)
downloadmariadb-git-bb-10.7-MDEV-25015-sformat.tar.gz
cannot allocate a new String[] in the ::val_str() methodbb-10.7-MDEV-25015-sformat
String inherits from Sql_alloc, so it's allocated on the thd's memroot, this cannot be done per row. Moved String[] allocation into the Item_func_sformat constructor (not fix_fields(), because we want it on the same memroot where the item is).
-rw-r--r--mysql-test/main/func_sformat.result12
-rw-r--r--mysql-test/main/func_sformat.test8
-rw-r--r--sql/item_strfunc.cc23
-rw-r--r--sql/item_strfunc.h5
4 files changed, 36 insertions, 12 deletions
diff --git a/mysql-test/main/func_sformat.result b/mysql-test/main/func_sformat.result
index f2631c32d65..fb8f89f8b4c 100644
--- a/mysql-test/main/func_sformat.result
+++ b/mysql-test/main/func_sformat.result
@@ -437,3 +437,15 @@ t1 CREATE TABLE `t1` (
`x` varchar(8) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+#
+# ps parameters
+#
+prepare s from 'select sformat("={:d}=", ?)';
+execute s using 100;
+sformat("={:d}=", ?)
+=100=
+execute s using 'abc';
+sformat("={:d}=", ?)
+NULL
+Warnings:
+Warning 4183 SFORMAT error: invalid type specifier
diff --git a/mysql-test/main/func_sformat.test b/mysql-test/main/func_sformat.test
index 9775810148b..1c6e539f8a9 100644
--- a/mysql-test/main/func_sformat.test
+++ b/mysql-test/main/func_sformat.test
@@ -199,3 +199,11 @@ select hex(sformat(_ucs2 x'003D007B007D003D', _ucs2 x'0442043504410442'));
create table t1 as select sformat(_ucs2 x'003D007B007D003D', _ucs2 x'0442043504410442') as x;
show create table t1;
drop table t1;
+
+
+echo #;
+echo # ps parameters;
+echo #;
+prepare s from 'select sformat("={:d}=", ?)';
+execute s using 100;
+execute s using 'abc';
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index fd5e2609e0c..0d174af61d1 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1306,9 +1306,22 @@ bool Item_func_replace::fix_length_and_dec()
return FALSE;
}
+/*
+ this is done in the constructor to be in the same memroot as
+ the item itself
+*/
+Item_func_sformat::Item_func_sformat(THD *thd, List<Item> &list)
+ : Item_str_func(thd, list)
+{
+ val_arg= new (thd->mem_root) String[arg_count];
+}
+
bool Item_func_sformat::fix_length_and_dec()
{
+ if (!val_arg)
+ return TRUE;
+
ulonglong char_length= 0;
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
@@ -1361,7 +1374,6 @@ String *Item_func_sformat::val_str(String *res)
using ctx= fmt::format_context;
String *fmt_arg= NULL;
String *parg= NULL;
- String *val_arg= NULL;
fmt::format_args::format_arg *vargs= NULL;
null_value= true;
@@ -1371,12 +1383,6 @@ String *Item_func_sformat::val_str(String *res)
if (!(vargs= new fmt::format_args::format_arg[arg_count - 1]))
return NULL;
- if (!(val_arg= new String[arg_count - 1]))
- {
- delete [] vargs;
- return NULL;
- }
-
/* Creates the array of arguments for vformat */
for (uint carg= 1; carg < arg_count; carg++)
{
@@ -1393,7 +1399,6 @@ String *Item_func_sformat::val_str(String *res)
if (!(parg= args[carg]->val_str(&val_arg[carg-1])))
{
delete [] vargs;
- delete [] val_arg;
return NULL;
}
if (parg->length() == 1)
@@ -1406,7 +1411,6 @@ String *Item_func_sformat::val_str(String *res)
default:
DBUG_ASSERT(0);
delete [] vargs;
- delete [] val_arg;
return NULL;
}
}
@@ -1430,7 +1434,6 @@ String *Item_func_sformat::val_str(String *res)
null_value= true;
}
delete [] vargs;
- delete [] val_arg;
return null_value ? NULL : res;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index d06f07d8c34..f28ad0f8f9f 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -588,9 +588,10 @@ public:
class Item_func_sformat :public Item_str_func
{
+ String *val_arg;
public:
- Item_func_sformat(THD *thd, List<Item> &list):
- Item_str_func(thd, list) { }
+ Item_func_sformat(THD *thd, List<Item> &list);
+ ~Item_func_sformat() { delete val_arg; }
String *val_str(String*) override;
bool fix_length_and_dec() override;
LEX_CSTRING func_name_cstring() const override