Commit 489ad44a authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #32124: crash if prepared statements refer to variables in the where clause

                  
The code to get read the value of a system variable was extracting its value 
on PREPARE stage and was substituting the value (as a constant) into the parse tree.
Note that this must be a reversible transformation, i.e. it must be reversed before
each re-execution.
Unfortunately this cannot be reliably done using the current code, because there are
other non-reversible source tree transformations that can interfere with this
reversible transformation.
Fixed by not resolving the value at PREPARE, but at EXECUTE (as the rest of the 
functions operate). Added a cache of the value (so that it's constant throughout
the execution of the query). Note that the cache also caches NULL values.
Updated an obsolete related test suite (variables-big) and the code to test the 
result type of system variables (as per bug 74).
parent 7fa30b28
...@@ -442,8 +442,6 @@ SELECT f1(); ...@@ -442,8 +442,6 @@ SELECT f1();
INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()),
(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2());
INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2());
INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)),
(NULL, @@LAST_INSERT_ID);
# Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". # Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID".
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
UPDATE t1 SET j= -1 WHERE i IS NULL; UPDATE t1 SET j= -1 WHERE i IS NULL;
......
'#---------------------BS_STVARS_025_01----------------------#' '#---------------------BS_STVARS_025_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_data_home_dir); SELECT COUNT(@@GLOBAL.innodb_data_home_dir);
COUNT(@@GLOBAL.innodb_data_home_dir) COUNT(@@GLOBAL.innodb_data_home_dir)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_025_02----------------------#' '#---------------------BS_STVARS_025_02----------------------#'
SET @@GLOBAL.innodb_data_home_dir=1; SET @@GLOBAL.innodb_data_home_dir=1;
...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'innodb_data_home_dir' is a read only variable ...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'innodb_data_home_dir' is a read only variable
Expected error 'Read only variable' Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_data_home_dir); SELECT COUNT(@@GLOBAL.innodb_data_home_dir);
COUNT(@@GLOBAL.innodb_data_home_dir) COUNT(@@GLOBAL.innodb_data_home_dir)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_025_03----------------------#' '#---------------------BS_STVARS_025_03----------------------#'
SELECT @@GLOBAL.innodb_data_home_dir = VARIABLE_VALUE SELECT @@GLOBAL.innodb_data_home_dir = VARIABLE_VALUE
...@@ -20,7 +20,7 @@ NULL ...@@ -20,7 +20,7 @@ NULL
1 Expected 1 Expected
SELECT COUNT(@@GLOBAL.innodb_data_home_dir); SELECT COUNT(@@GLOBAL.innodb_data_home_dir);
COUNT(@@GLOBAL.innodb_data_home_dir) COUNT(@@GLOBAL.innodb_data_home_dir)
0 1
1 Expected 1 Expected
SELECT COUNT(VARIABLE_VALUE) SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
...@@ -36,7 +36,7 @@ NULL ...@@ -36,7 +36,7 @@ NULL
'#---------------------BS_STVARS_025_05----------------------#' '#---------------------BS_STVARS_025_05----------------------#'
SELECT COUNT(@@innodb_data_home_dir); SELECT COUNT(@@innodb_data_home_dir);
COUNT(@@innodb_data_home_dir) COUNT(@@innodb_data_home_dir)
0 1
1 Expected 1 Expected
SELECT COUNT(@@local.innodb_data_home_dir); SELECT COUNT(@@local.innodb_data_home_dir);
ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable
...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable ...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'innodb_data_home_dir' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable' Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_data_home_dir); SELECT COUNT(@@GLOBAL.innodb_data_home_dir);
COUNT(@@GLOBAL.innodb_data_home_dir) COUNT(@@GLOBAL.innodb_data_home_dir)
0 1
1 Expected 1 Expected
SELECT innodb_data_home_dir = @@SESSION.innodb_data_home_dir; SELECT innodb_data_home_dir = @@SESSION.innodb_data_home_dir;
ERROR 42S22: Unknown column 'innodb_data_home_dir' in 'field list' ERROR 42S22: Unknown column 'innodb_data_home_dir' in 'field list'
......
'#---------------------BS_STVARS_029_01----------------------#' '#---------------------BS_STVARS_029_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_flush_method); SELECT COUNT(@@GLOBAL.innodb_flush_method);
COUNT(@@GLOBAL.innodb_flush_method) COUNT(@@GLOBAL.innodb_flush_method)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_029_02----------------------#' '#---------------------BS_STVARS_029_02----------------------#'
SET @@GLOBAL.innodb_flush_method=1; SET @@GLOBAL.innodb_flush_method=1;
...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'innodb_flush_method' is a read only variable ...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'innodb_flush_method' is a read only variable
Expected error 'Read only variable' Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_flush_method); SELECT COUNT(@@GLOBAL.innodb_flush_method);
COUNT(@@GLOBAL.innodb_flush_method) COUNT(@@GLOBAL.innodb_flush_method)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_029_03----------------------#' '#---------------------BS_STVARS_029_03----------------------#'
SELECT @@GLOBAL.innodb_flush_method = VARIABLE_VALUE SELECT @@GLOBAL.innodb_flush_method = VARIABLE_VALUE
...@@ -20,7 +20,7 @@ NULL ...@@ -20,7 +20,7 @@ NULL
1 Expected 1 Expected
SELECT COUNT(@@GLOBAL.innodb_flush_method); SELECT COUNT(@@GLOBAL.innodb_flush_method);
COUNT(@@GLOBAL.innodb_flush_method) COUNT(@@GLOBAL.innodb_flush_method)
0 1
1 Expected 1 Expected
SELECT COUNT(VARIABLE_VALUE) SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
...@@ -36,7 +36,7 @@ NULL ...@@ -36,7 +36,7 @@ NULL
'#---------------------BS_STVARS_029_05----------------------#' '#---------------------BS_STVARS_029_05----------------------#'
SELECT COUNT(@@innodb_flush_method); SELECT COUNT(@@innodb_flush_method);
COUNT(@@innodb_flush_method) COUNT(@@innodb_flush_method)
0 1
1 Expected 1 Expected
SELECT COUNT(@@local.innodb_flush_method); SELECT COUNT(@@local.innodb_flush_method);
ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable
...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable ...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'innodb_flush_method' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable' Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_flush_method); SELECT COUNT(@@GLOBAL.innodb_flush_method);
COUNT(@@GLOBAL.innodb_flush_method) COUNT(@@GLOBAL.innodb_flush_method)
0 1
1 Expected 1 Expected
SELECT innodb_flush_method = @@SESSION.innodb_flush_method; SELECT innodb_flush_method = @@SESSION.innodb_flush_method;
ERROR 42S22: Unknown column 'innodb_flush_method' in 'field list' ERROR 42S22: Unknown column 'innodb_flush_method' in 'field list'
......
...@@ -162,4 +162,32 @@ a b ...@@ -162,4 +162,32 @@ a b
12 NULL 12 NULL
drop table t1; drop table t1;
drop table t2; drop table t2;
CREATE TABLE t1 (a INT);
PREPARE stmt FROM 'select 1 from `t1` where `a` = any (select (@@tmpdir))';
EXECUTE stmt;
1
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
CREATE TABLE t2 (a INT PRIMARY KEY);
INSERT INTO t2 VALUES (400000), (400001);
SET @@sort_buffer_size=400000;
CREATE FUNCTION p1(i INT) RETURNS INT
BEGIN
SET @@sort_buffer_size= i;
RETURN i + 1;
END|
SELECT * FROM t2 WHERE a = @@sort_buffer_size AND p1(@@sort_buffer_size + 1) > a - 1;
a
400000
DROP TABLE t2;
DROP FUNCTION p1;
SELECT CONCAT(@@sort_buffer_size);
CONCAT(@@sort_buffer_size)
400001
SELECT LEFT("12345", @@ft_boolean_syntax);
LEFT("12345", @@ft_boolean_syntax)
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '+ -><()~*:""&|'
SET @@sort_buffer_size=DEFAULT;
End of 5.0 tests. End of 5.0 tests.
'#---------------------BS_STVARS_046_01----------------------#' '#---------------------BS_STVARS_046_01----------------------#'
SELECT COUNT(@@GLOBAL.ssl_capath); SELECT COUNT(@@GLOBAL.ssl_capath);
COUNT(@@GLOBAL.ssl_capath) COUNT(@@GLOBAL.ssl_capath)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_046_02----------------------#' '#---------------------BS_STVARS_046_02----------------------#'
SET @@GLOBAL.ssl_capath=1; SET @@GLOBAL.ssl_capath=1;
...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'ssl_capath' is a read only variable ...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'ssl_capath' is a read only variable
Expected error 'Read only variable' Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.ssl_capath); SELECT COUNT(@@GLOBAL.ssl_capath);
COUNT(@@GLOBAL.ssl_capath) COUNT(@@GLOBAL.ssl_capath)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_046_03----------------------#' '#---------------------BS_STVARS_046_03----------------------#'
SELECT @@GLOBAL.ssl_capath = VARIABLE_VALUE SELECT @@GLOBAL.ssl_capath = VARIABLE_VALUE
...@@ -20,7 +20,7 @@ NULL ...@@ -20,7 +20,7 @@ NULL
1 Expected 1 Expected
SELECT COUNT(@@GLOBAL.ssl_capath); SELECT COUNT(@@GLOBAL.ssl_capath);
COUNT(@@GLOBAL.ssl_capath) COUNT(@@GLOBAL.ssl_capath)
0 1
1 Expected 1 Expected
SELECT COUNT(VARIABLE_VALUE) SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
...@@ -36,7 +36,7 @@ NULL ...@@ -36,7 +36,7 @@ NULL
'#---------------------BS_STVARS_046_05----------------------#' '#---------------------BS_STVARS_046_05----------------------#'
SELECT COUNT(@@ssl_capath); SELECT COUNT(@@ssl_capath);
COUNT(@@ssl_capath) COUNT(@@ssl_capath)
0 1
1 Expected 1 Expected
SELECT COUNT(@@local.ssl_capath); SELECT COUNT(@@local.ssl_capath);
ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable
...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable ...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'ssl_capath' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable' Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.ssl_capath); SELECT COUNT(@@GLOBAL.ssl_capath);
COUNT(@@GLOBAL.ssl_capath) COUNT(@@GLOBAL.ssl_capath)
0 1
1 Expected 1 Expected
SELECT ssl_capath = @@SESSION.ssl_capath; SELECT ssl_capath = @@SESSION.ssl_capath;
ERROR 42S22: Unknown column 'ssl_capath' in 'field list' ERROR 42S22: Unknown column 'ssl_capath' in 'field list'
......
'#---------------------BS_STVARS_048_01----------------------#' '#---------------------BS_STVARS_048_01----------------------#'
SELECT COUNT(@@GLOBAL.ssl_cipher); SELECT COUNT(@@GLOBAL.ssl_cipher);
COUNT(@@GLOBAL.ssl_cipher) COUNT(@@GLOBAL.ssl_cipher)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_048_02----------------------#' '#---------------------BS_STVARS_048_02----------------------#'
SET @@GLOBAL.ssl_cipher=1; SET @@GLOBAL.ssl_cipher=1;
...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'ssl_cipher' is a read only variable ...@@ -9,7 +9,7 @@ ERROR HY000: Variable 'ssl_cipher' is a read only variable
Expected error 'Read only variable' Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.ssl_cipher); SELECT COUNT(@@GLOBAL.ssl_cipher);
COUNT(@@GLOBAL.ssl_cipher) COUNT(@@GLOBAL.ssl_cipher)
0 1
1 Expected 1 Expected
'#---------------------BS_STVARS_048_03----------------------#' '#---------------------BS_STVARS_048_03----------------------#'
SELECT @@GLOBAL.ssl_cipher = VARIABLE_VALUE SELECT @@GLOBAL.ssl_cipher = VARIABLE_VALUE
...@@ -20,7 +20,7 @@ NULL ...@@ -20,7 +20,7 @@ NULL
1 Expected 1 Expected
SELECT COUNT(@@GLOBAL.ssl_cipher); SELECT COUNT(@@GLOBAL.ssl_cipher);
COUNT(@@GLOBAL.ssl_cipher) COUNT(@@GLOBAL.ssl_cipher)
0 1
1 Expected 1 Expected
SELECT COUNT(VARIABLE_VALUE) SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
...@@ -36,7 +36,7 @@ NULL ...@@ -36,7 +36,7 @@ NULL
'#---------------------BS_STVARS_048_05----------------------#' '#---------------------BS_STVARS_048_05----------------------#'
SELECT COUNT(@@ssl_cipher); SELECT COUNT(@@ssl_cipher);
COUNT(@@ssl_cipher) COUNT(@@ssl_cipher)
0 1
1 Expected 1 Expected
SELECT COUNT(@@local.ssl_cipher); SELECT COUNT(@@local.ssl_cipher);
ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable
...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable ...@@ -46,7 +46,7 @@ ERROR HY000: Variable 'ssl_cipher' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable' Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.ssl_cipher); SELECT COUNT(@@GLOBAL.ssl_cipher);
COUNT(@@GLOBAL.ssl_cipher) COUNT(@@GLOBAL.ssl_cipher)
0 1
1 Expected 1 Expected
SELECT ssl_cipher = @@SESSION.ssl_cipher; SELECT ssl_cipher = @@SESSION.ssl_cipher;
ERROR 42S22: Unknown column 'ssl_cipher' in 'field list' ERROR 42S22: Unknown column 'ssl_cipher' in 'field list'
......
...@@ -157,7 +157,7 @@ explain extended select @@IDENTITY,last_insert_id(), @@identity; ...@@ -157,7 +157,7 @@ explain extended select @@IDENTITY,last_insert_id(), @@identity;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1003 select 345 AS `@@IDENTITY`,last_insert_id() AS `last_insert_id()`,345 AS `@@identity` Note 1003 select @@IDENTITY AS `@@IDENTITY`,last_insert_id() AS `last_insert_id()`,@@identity AS `@@identity`
set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON"; set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON";
set global concurrent_insert=2; set global concurrent_insert=2;
show variables like 'concurrent_insert'; show variables like 'concurrent_insert';
......
...@@ -398,8 +398,6 @@ f1() ...@@ -398,8 +398,6 @@ f1()
INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()),
(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2());
INSERT INTO t1 VALUES (NULL, f2()); INSERT INTO t1 VALUES (NULL, f2());
INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)),
(NULL, @@LAST_INSERT_ID);
INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID());
UPDATE t1 SET j= -1 WHERE i IS NULL; UPDATE t1 SET j= -1 WHERE i IS NULL;
INSERT INTO t1 (i) VALUES (NULL); INSERT INTO t1 (i) VALUES (NULL);
...@@ -422,20 +420,17 @@ i j ...@@ -422,20 +420,17 @@ i j
11 3 11 3
12 3 12 3
13 8 13 8
14 13 14 -1
15 5 15 13
16 13 16 0
17 -1 17 0
18 14
19 0
20 0
SELECT * FROM t2 ORDER BY i; SELECT * FROM t2 ORDER BY i;
i i
2 2
3 3
5 5
6 6
19 16
SELECT * FROM t1; SELECT * FROM t1;
i j i j
1 -1 1 -1
...@@ -451,20 +446,17 @@ i j ...@@ -451,20 +446,17 @@ i j
11 3 11 3
12 3 12 3
13 8 13 8
14 13 14 -1
15 5 15 13
16 13 16 0
17 -1 17 0
18 14
19 0
20 0
SELECT * FROM t2; SELECT * FROM t2;
i i
2 2
3 3
5 5
6 6
19 16
DROP PROCEDURE p1; DROP PROCEDURE p1;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP FUNCTION f2; DROP FUNCTION f2;
......
...@@ -177,4 +177,41 @@ select * from t2; ...@@ -177,4 +177,41 @@ select * from t2;
drop table t1; drop table t1;
drop table t2; drop table t2;
#
# Bug #32124: crash if prepared statements refer to variables in the where
# clause
#
CREATE TABLE t1 (a INT);
PREPARE stmt FROM 'select 1 from `t1` where `a` = any (select (@@tmpdir))';
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
CREATE TABLE t2 (a INT PRIMARY KEY);
INSERT INTO t2 VALUES (400000), (400001);
SET @@sort_buffer_size=400000;
DELIMITER |;
CREATE FUNCTION p1(i INT) RETURNS INT
BEGIN
SET @@sort_buffer_size= i;
RETURN i + 1;
END|
DELIMITER ;|
SELECT * FROM t2 WHERE a = @@sort_buffer_size AND p1(@@sort_buffer_size + 1) > a - 1;
DROP TABLE t2;
DROP FUNCTION p1;
SELECT CONCAT(@@sort_buffer_size);
SELECT LEFT("12345", @@ft_boolean_syntax);
SET @@sort_buffer_size=DEFAULT;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -2380,17 +2380,15 @@ void Item_string::print(String *str, enum_query_type query_type) ...@@ -2380,17 +2380,15 @@ void Item_string::print(String *str, enum_query_type query_type)
} }
double Item_string::val_real() double
double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end)
{ {
DBUG_ASSERT(fixed == 1);
int error; int error;
char *end, *org_end; char *org_end;
double tmp; double tmp;
CHARSET_INFO *cs= str_value.charset();
org_end= (char*) str_value.ptr() + str_value.length(); org_end= end;
tmp= my_strntod(cs, (char*) str_value.ptr(), str_value.length(), &end, tmp= my_strntod(cs, (char*) cptr, end - cptr, &end, &error);
&error);
if (error || (end != org_end && !check_if_only_end_space(cs, end, org_end))) if (error || (end != org_end && !check_if_only_end_space(cs, end, org_end)))
{ {
/* /*
...@@ -2400,26 +2398,28 @@ double Item_string::val_real() ...@@ -2400,26 +2398,28 @@ double Item_string::val_real()
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE, ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE", ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE",
str_value.ptr()); cptr);
} }
return tmp; return tmp;
} }
/** double Item_string::val_real()
@todo
Give error if we wanted a signed integer and we got an unsigned one
*/
longlong Item_string::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
return double_from_string_with_check (str_value.charset(), str_value.ptr(),
(char *) str_value.ptr() + str_value.length());
}
longlong
longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end)
{
int err; int err;
longlong tmp; longlong tmp;
char *end= (char*) str_value.ptr()+ str_value.length();
char *org_end= end; char *org_end= end;
CHARSET_INFO *cs= str_value.charset();
tmp= (*(cs->cset->strtoll10))(cs, str_value.ptr(), &end, &err); tmp= (*(cs->cset->strtoll10))(cs, cptr, &end, &err);
/* /*
TODO: Give error if we wanted a signed integer and we got an unsigned TODO: Give error if we wanted a signed integer and we got an unsigned
one one
...@@ -2430,12 +2430,24 @@ longlong Item_string::val_int() ...@@ -2430,12 +2430,24 @@ longlong Item_string::val_int()
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE, ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER", ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
str_value.ptr()); cptr);
} }
return tmp; return tmp;
} }
/**
@todo
Give error if we wanted a signed integer and we got an unsigned one
*/
longlong Item_string::val_int()
{
DBUG_ASSERT(fixed == 1);
return longlong_from_string_with_check(str_value.charset(), str_value.ptr(),
(char *) str_value.ptr()+ str_value.length());
}
my_decimal *Item_string::val_decimal(my_decimal *decimal_value) my_decimal *Item_string::val_decimal(my_decimal *decimal_value)
{ {
return val_decimal_from_string(decimal_value); return val_decimal_from_string(decimal_value);
......
...@@ -1981,6 +1981,11 @@ class Item_string :public Item_basic_constant ...@@ -1981,6 +1981,11 @@ class Item_string :public Item_basic_constant
}; };
longlong
longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end);
double
double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end);
class Item_static_string_func :public Item_string class Item_static_string_func :public Item_string
{ {
const char *func_name; const char *func_name;
......
This diff is collapsed.
...@@ -55,7 +55,7 @@ class Item_func :public Item_result_field ...@@ -55,7 +55,7 @@ class Item_func :public Item_result_field
NOW_FUNC, TRIG_COND_FUNC, NOW_FUNC, TRIG_COND_FUNC,
SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
NEG_FUNC }; NEG_FUNC, GSYSVAR_FUNC };
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
OPTIMIZE_EQUAL }; OPTIMIZE_EQUAL };
enum Type type() const { return FUNC_ITEM; } enum Type type() const { return FUNC_ITEM; }
...@@ -1426,24 +1426,36 @@ class Item_user_var_as_out_param :public Item ...@@ -1426,24 +1426,36 @@ class Item_user_var_as_out_param :public Item
/* A system variable */ /* A system variable */
#define GET_SYS_VAR_CACHE_LONG 1
#define GET_SYS_VAR_CACHE_DOUBLE 2
#define GET_SYS_VAR_CACHE_STRING 4
class Item_func_get_system_var :public Item_func class Item_func_get_system_var :public Item_func
{ {
sys_var *var; sys_var *var;
enum_var_type var_type; enum_var_type var_type;
LEX_STRING component; LEX_STRING component;
longlong cached_llval;
double cached_dval;
String cached_strval;
my_bool cached_null_value;
query_id_t used_query_id;
uchar cache_present;
public: public:
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg, Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
LEX_STRING *component_arg, const char *name_arg, LEX_STRING *component_arg, const char *name_arg,
size_t name_len_arg); size_t name_len_arg);
bool fix_fields(THD *thd, Item **ref); enum Functype functype() const { return GSYSVAR_FUNC; }
/* void fix_length_and_dec();
Stubs for pure virtual methods. Should never be called: this void print(String *str, enum_query_type query_type);
item is always substituted with a constant in fix_fields(). bool const_item() const { return true; }
*/ table_map used_tables() const { return 0; }
double val_real() { DBUG_ASSERT(0); return 0.0; } enum Item_result result_type() const;
longlong val_int() { DBUG_ASSERT(0); return 0; } enum_field_types field_type() const;
String* val_str(String*) { DBUG_ASSERT(0); return 0; } double val_real();
void fix_length_and_dec() { DBUG_ASSERT(0); } longlong val_int();
String* val_str(String*);
/* TODO: fix to support views */ /* TODO: fix to support views */
const char *func_name() const { return "get_system_var"; } const char *func_name() const { return "get_system_var"; }
/** /**
...@@ -1455,6 +1467,7 @@ class Item_func_get_system_var :public Item_func ...@@ -1455,6 +1467,7 @@ class Item_func_get_system_var :public Item_func
@return true if the variable is written to the binlog, false otherwise. @return true if the variable is written to the binlog, false otherwise.
*/ */
bool is_written_to_binlog(); bool is_written_to_binlog();
bool eq(const Item *item, bool binary_cmp) const;
}; };
......
...@@ -1734,119 +1734,6 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) ...@@ -1734,119 +1734,6 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
} }
/**
Return an Item for a variable.
Used with @@[global.]variable_name.
If type is not given, return local value if exists, else global.
*/
Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
{
if (check_type(var_type))
{
if (var_type != OPT_DEFAULT)
{
my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
return 0;
}
/* As there was no local variable, return the global value */
var_type= OPT_GLOBAL;
}
switch (show_type()) {
case SHOW_INT:
{
uint value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(uint*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_uint((ulonglong) value);
}
case SHOW_LONG:
{
ulong value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(ulong*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_uint((ulonglong) value);
}
case SHOW_LONGLONG:
{
longlong value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(longlong*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_int(value);
}
case SHOW_DOUBLE:
{
double value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(double*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
/* 6, as this is for now only used with microseconds */
return new Item_float(value, 6);
}
case SHOW_HA_ROWS:
{
ha_rows value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(ha_rows*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_int((ulonglong) value);
}
case SHOW_MY_BOOL:
{
int32 value;
pthread_mutex_lock(&LOCK_global_system_variables);
value= *(my_bool*) value_ptr(thd, var_type, base);
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_int(value,1);
}
case SHOW_CHAR_PTR:
{
Item *tmp;
pthread_mutex_lock(&LOCK_global_system_variables);
char *str= *(char**) value_ptr(thd, var_type, base);
if (str)
{
uint length= strlen(str);
tmp= new Item_string(thd->strmake(str, length), length,
system_charset_info, DERIVATION_SYSCONST);
}
else
{
tmp= new Item_null();
tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
return tmp;
}
case SHOW_CHAR:
{
Item *tmp;
pthread_mutex_lock(&LOCK_global_system_variables);
char *str= (char*) value_ptr(thd, var_type, base);
if (str)
tmp= new Item_string(str, strlen(str),
system_charset_info, DERIVATION_SYSCONST);
else
{
tmp= new Item_null();
tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
return tmp;
}
default:
my_error(ER_VAR_CANT_BE_READ, MYF(0), name);
}
return 0;
}
bool sys_var_thd_enum::update(THD *thd, set_var *var) bool sys_var_thd_enum::update(THD *thd, set_var *var)
{ {
if (var->type == OPT_GLOBAL) if (var->type == OPT_GLOBAL)
......
...@@ -105,7 +105,6 @@ class sys_var ...@@ -105,7 +105,6 @@ class sys_var
{ return type != INT_RESULT; } /* Assume INT */ { return type != INT_RESULT; } /* Assume INT */
virtual bool check_default(enum_var_type type) virtual bool check_default(enum_var_type type)
{ return option_limits == 0; } { return option_limits == 0; }
Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
virtual bool is_struct() { return 0; } virtual bool is_struct() { return 0; }
virtual bool is_readonly() const { return 0; } virtual bool is_readonly() const { return 0; }
virtual sys_var_pluginvar *cast_pluginvar() { return 0; } virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
......
...@@ -7201,9 +7201,6 @@ static void test_field_misc() ...@@ -7201,9 +7201,6 @@ static void test_field_misc()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND my_bind[1];
char table_type[NAME_LEN];
ulong type_length;
int rc; int rc;
myheader("test_field_misc"); myheader("test_field_misc");
...@@ -7246,53 +7243,6 @@ static void test_field_misc() ...@@ -7246,53 +7243,6 @@ static void test_field_misc()
mysql_free_result(result); mysql_free_result(result);
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
stmt= mysql_simple_prepare(mysql, "SELECT @@table_type");
check_stmt(stmt);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bzero((char*) my_bind, sizeof(my_bind));
my_bind[0].buffer_type= MYSQL_TYPE_STRING;
my_bind[0].buffer= table_type;
my_bind[0].length= &type_length;
my_bind[0].buffer_length= NAME_LEN;
rc= mysql_stmt_bind_result(stmt, my_bind);
check_execute(stmt, rc);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
if (!opt_silent)
fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
stmt= mysql_simple_prepare(mysql, "SELECT @@table_type");
check_stmt(stmt);
result= mysql_stmt_result_metadata(stmt);
mytest(result);
DIE_UNLESS(mysql_stmt_field_count(stmt) == mysql_num_fields(result));
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
DIE_UNLESS(1 == my_process_stmt_result(stmt));
verify_prepare_field(result, 0,
"@@table_type", "", /* field and its org name */
mysql_get_server_version(mysql) <= 50000 ?
MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
"", "", /* table and its org name */
"", type_length, 0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
stmt= mysql_simple_prepare(mysql, "SELECT @@max_error_count"); stmt= mysql_simple_prepare(mysql, "SELECT @@max_error_count");
check_stmt(stmt); check_stmt(stmt);
...@@ -7309,7 +7259,8 @@ static void test_field_misc() ...@@ -7309,7 +7259,8 @@ static void test_field_misc()
"@@max_error_count", "", /* field and its org name */ "@@max_error_count", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */ MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */ "", "", /* table and its org name */
"", 10, 0); /* db name, length */ /* db name, length */
"", MY_INT64_NUM_DECIMAL_DIGITS , 0);
mysql_free_result(result); mysql_free_result(result);
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
...@@ -7329,7 +7280,8 @@ static void test_field_misc() ...@@ -7329,7 +7280,8 @@ static void test_field_misc()
"@@max_allowed_packet", "", /* field and its org name */ "@@max_allowed_packet", "", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */ MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */ "", "", /* table and its org name */
"", 10, 0); /* db name, length */ /* db name, length */
"", MY_INT64_NUM_DECIMAL_DIGITS, 0);
mysql_free_result(result); mysql_free_result(result);
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment