mirror of
https://github.com/MariaDB/server.git
synced 2025-04-18 21:44:20 +03:00
MDEV-27666 User variable not parsed as geometry variable in geometry function
Adding GEOMETRY type user variables.
This commit is contained in:
parent
caad34df54
commit
fa3171df08
@ -5328,5 +5328,112 @@ SELECT BIT_XOR(a) FROM t1;
|
||||
ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor('
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-27666 User variable not parsed as geometry variable in geometry function.
|
||||
#
|
||||
set @g= point(1, 1);
|
||||
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||
ST_AsWKT(GeometryCollection(Point(44, 6), @g))
|
||||
GEOMETRYCOLLECTION(POINT(44 6),POINT(1 1))
|
||||
set @g= "just a string";
|
||||
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||
ERROR HY000: Illegal parameter data type longblob for operation 'geometrycollection'
|
||||
SET @g= LineString(Point(0,0), Point(0,1));
|
||||
SELECT AsText(PointN(@g, 1));
|
||||
AsText(PointN(@g, 1))
|
||||
POINT(0 0)
|
||||
SELECT AsText(PointN(@g, 2));
|
||||
AsText(PointN(@g, 2))
|
||||
POINT(0 1)
|
||||
SET @g= Point(1, 1);
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` point DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
POINT(1 1)
|
||||
DROP TABLE t1;
|
||||
SET @g= MultiPoint(Point(1, 1), Point(-1,-1));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` multipoint DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
MULTIPOINT(1 1,-1 -1)
|
||||
DROP TABLE t1;
|
||||
SET @g= LineString(Point(1, 1), Point(2,2));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` linestring DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
LINESTRING(1 1,2 2)
|
||||
DROP TABLE t1;
|
||||
SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)),
|
||||
LineString(Point(-1, -1), Point(-2,-2)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` multilinestring DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
MULTILINESTRING((1 1,2 2),(-1 -1,-2 -2))
|
||||
DROP TABLE t1;
|
||||
SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` polygon DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
POLYGON((0 0,30 0,30 30,0 0))
|
||||
DROP TABLE t1;
|
||||
SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3),
|
||||
Point(3, 0), Point(0, 3))));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` multipolygon DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
|
||||
DROP TABLE t1;
|
||||
SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` geometrycollection DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
|
||||
DROP TABLE t1;
|
||||
SET @g= GeometryFromText('POINT(1 1)');
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`g` geometry DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT AsText(g) FROM t1;
|
||||
AsText(g)
|
||||
POINT(1 1)
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
@ -3374,6 +3374,69 @@ SELECT BIT_OR(a) FROM t1;
|
||||
SELECT BIT_XOR(a) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27666 User variable not parsed as geometry variable in geometry function.
|
||||
--echo #
|
||||
|
||||
set @g= point(1, 1);
|
||||
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||
set @g= "just a string";
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
select ST_AsWKT(GeometryCollection(Point(44, 6), @g));
|
||||
|
||||
SET @g= LineString(Point(0,0), Point(0,1));
|
||||
SELECT AsText(PointN(@g, 1));
|
||||
SELECT AsText(PointN(@g, 2));
|
||||
|
||||
SET @g= Point(1, 1);
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= MultiPoint(Point(1, 1), Point(-1,-1));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= LineString(Point(1, 1), Point(2,2));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)),
|
||||
LineString(Point(-1, -1), Point(-2,-2)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3),
|
||||
Point(3, 0), Point(0, 3))));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)));
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
SET @g= GeometryFromText('POINT(1 1)');
|
||||
CREATE TABLE t1 AS SELECT @g AS g;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT AsText(g) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
|
12
mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result
Normal file
12
mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result
Normal file
@ -0,0 +1,12 @@
|
||||
SET @g0= POINT(1,1);
|
||||
SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||
CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1;
|
||||
DROP TABLE t1;
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # User var # # @`g0`=/*point*/_binary X'000000000101000000000000000000F03F000000000000F03F' COLLATE binary
|
||||
master-bin.000001 # User var # # @`g1`=/*polygon*/_binary X'0000000001030000000100000004000000000000000000000000000000000000000000000000003E4000000000000000000000000000003E400000000000003E4000000000000000000000000000000000' COLLATE binary
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
15
mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test
Normal file
15
mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test
Normal file
@ -0,0 +1,15 @@
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_binlog_format_statement.inc
|
||||
--source include/have_geometry.inc
|
||||
|
||||
--disable_query_log
|
||||
reset master; # get rid of previous tests binlog
|
||||
--enable_query_log
|
||||
|
||||
SET @g0= POINT(1,1);
|
||||
SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)));
|
||||
CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--let $binlog_file = LAST
|
||||
source include/show_binlog_events.inc;
|
21
mysql-test/suite/rpl/r/rpl_gis_user_var.result
Normal file
21
mysql-test/suite/rpl/r/rpl_gis_user_var.result
Normal file
@ -0,0 +1,21 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
#
|
||||
#
|
||||
#
|
||||
connection master;
|
||||
SET @p=POINT(1,1);
|
||||
CREATE TABLE t1 AS SELECT @p AS p;
|
||||
connection slave;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`p` point DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
SELECT ST_AsWKT(p) FROM t1;
|
||||
ST_AsWKT(p)
|
||||
POINT(1 1)
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
connection slave;
|
||||
include/rpl_end.inc
|
18
mysql-test/suite/rpl/t/rpl_gis_user_var.test
Normal file
18
mysql-test/suite/rpl/t/rpl_gis_user_var.test
Normal file
@ -0,0 +1,18 @@
|
||||
--source include/have_geometry.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--echo #
|
||||
--echo #
|
||||
--echo #
|
||||
|
||||
connection master;
|
||||
SET @p=POINT(1,1);
|
||||
CREATE TABLE t1 AS SELECT @p AS p;
|
||||
sync_slave_with_master;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT ST_AsWKT(p) FROM t1;
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
sync_slave_with_master;
|
||||
|
||||
--source include/rpl_end.inc
|
@ -79,9 +79,9 @@ static int user_variables_fill(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
else
|
||||
return 1;
|
||||
|
||||
const LEX_CSTRING *tmp= var->unsigned_flag ?
|
||||
&unsigned_result_types[var->type] :
|
||||
&result_types[var->type];
|
||||
const LEX_CSTRING *tmp= var->type_handler()->is_unsigned() ?
|
||||
&unsigned_result_types[var->type_handler()->result_type()] :
|
||||
&result_types[var->type_handler()->result_type()];
|
||||
field[2]->store(tmp->str, tmp->length, system_charset_info);
|
||||
|
||||
if (var->charset())
|
||||
|
@ -4658,7 +4658,6 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
|
||||
entry->length=0;
|
||||
entry->update_query_id=0;
|
||||
entry->set_charset(NULL);
|
||||
entry->unsigned_flag= 0;
|
||||
/*
|
||||
If we are here, we were called from a SET or a query which sets a
|
||||
variable. Imagine it is this:
|
||||
@ -4670,7 +4669,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
|
||||
by Item_func_get_user_var (because that's not necessary).
|
||||
*/
|
||||
entry->used_query_id=current_thd->query_id;
|
||||
entry->type=STRING_RESULT;
|
||||
entry->set_handler(&type_handler_long_blob);
|
||||
memcpy((char*) entry->name.str, name->str, name->length+1);
|
||||
if (my_hash_insert(hash,(uchar*) entry))
|
||||
{
|
||||
@ -4746,9 +4745,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
||||
switch (args[0]->result_type()) {
|
||||
case STRING_RESULT:
|
||||
case TIME_RESULT:
|
||||
set_handler(type_handler_long_blob.
|
||||
type_handler_adjusted_to_max_octet_length(max_length,
|
||||
collation.collation));
|
||||
if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY)
|
||||
set_handler(args[0]->type_handler());
|
||||
else
|
||||
set_handler(type_handler_long_blob.
|
||||
type_handler_adjusted_to_max_octet_length(max_length,
|
||||
collation.collation));
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
set_handler(&type_handler_double);
|
||||
@ -4873,9 +4875,9 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg)
|
||||
|
||||
bool
|
||||
update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
Item_result type, CHARSET_INFO *cs,
|
||||
bool unsigned_arg)
|
||||
const Type_handler *th, CHARSET_INFO *cs)
|
||||
{
|
||||
entry->set_handler(th);
|
||||
if (set_null)
|
||||
{
|
||||
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
||||
@ -4886,7 +4888,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type == STRING_RESULT)
|
||||
if (th->result_type() == STRING_RESULT)
|
||||
length++; // Store strings with end \0
|
||||
if (length <= extra_size)
|
||||
{
|
||||
@ -4915,20 +4917,18 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (type == STRING_RESULT)
|
||||
if (th->result_type() == STRING_RESULT)
|
||||
{
|
||||
length--; // Fix length change above
|
||||
entry->value[length]= 0; // Store end \0
|
||||
}
|
||||
if (length)
|
||||
memmove(entry->value, ptr, length);
|
||||
if (type == DECIMAL_RESULT)
|
||||
if (th->result_type() == DECIMAL_RESULT)
|
||||
((my_decimal*)entry->value)->fix_buffer_pointer();
|
||||
entry->length= length;
|
||||
entry->set_charset(cs);
|
||||
entry->unsigned_flag= unsigned_arg;
|
||||
}
|
||||
entry->type=type;
|
||||
#ifdef USER_VAR_TRACKING
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
THD *thd= current_thd;
|
||||
@ -4941,9 +4941,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
|
||||
bool
|
||||
Item_func_set_user_var::update_hash(void *ptr, size_t length,
|
||||
Item_result res_type,
|
||||
CHARSET_INFO *cs,
|
||||
bool unsigned_arg)
|
||||
const Type_handler *th,
|
||||
CHARSET_INFO *cs)
|
||||
{
|
||||
/*
|
||||
If we set a variable explicitly to NULL then keep the old
|
||||
@ -4957,9 +4956,8 @@ Item_func_set_user_var::update_hash(void *ptr, size_t length,
|
||||
else
|
||||
null_value= args[0]->null_value;
|
||||
if (null_value && null_item)
|
||||
res_type= m_var_entry->type; // Don't change type of item
|
||||
if (::update_hash(m_var_entry, null_value,
|
||||
ptr, length, res_type, cs, unsigned_arg))
|
||||
th= m_var_entry->type_handler(); // Don't change type of item
|
||||
if (::update_hash(m_var_entry, null_value, ptr, length, th, cs))
|
||||
{
|
||||
null_value= 1;
|
||||
return 1;
|
||||
@ -4975,7 +4973,7 @@ double user_var_entry::val_real(bool *null_value)
|
||||
if ((*null_value= (value == 0)))
|
||||
return 0.0;
|
||||
|
||||
switch (type) {
|
||||
switch (type_handler()->result_type()) {
|
||||
case REAL_RESULT:
|
||||
return *(double*) value;
|
||||
case INT_RESULT:
|
||||
@ -5000,7 +4998,7 @@ longlong user_var_entry::val_int(bool *null_value) const
|
||||
if ((*null_value= (value == 0)))
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
switch (type_handler()->result_type()) {
|
||||
case REAL_RESULT:
|
||||
return (longlong) *(double*) value;
|
||||
case INT_RESULT:
|
||||
@ -5029,12 +5027,12 @@ String *user_var_entry::val_str(bool *null_value, String *str,
|
||||
if ((*null_value= (value == 0)))
|
||||
return (String*) 0;
|
||||
|
||||
switch (type) {
|
||||
switch (type_handler()->result_type()) {
|
||||
case REAL_RESULT:
|
||||
str->set_real(*(double*) value, decimals, charset());
|
||||
break;
|
||||
case INT_RESULT:
|
||||
if (!unsigned_flag)
|
||||
if (!type_handler()->is_unsigned())
|
||||
str->set(*(longlong*) value, charset());
|
||||
else
|
||||
str->set(*(ulonglong*) value, charset());
|
||||
@ -5061,7 +5059,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
|
||||
if ((*null_value= (value == 0)))
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
switch (type_handler()->result_type()) {
|
||||
case REAL_RESULT:
|
||||
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
|
||||
break;
|
||||
@ -5200,33 +5198,37 @@ Item_func_set_user_var::update()
|
||||
case REAL_RESULT:
|
||||
{
|
||||
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
|
||||
REAL_RESULT, &my_charset_numeric, 0);
|
||||
&type_handler_double, &my_charset_numeric);
|
||||
break;
|
||||
}
|
||||
case INT_RESULT:
|
||||
{
|
||||
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
|
||||
INT_RESULT, &my_charset_numeric, unsigned_flag);
|
||||
unsigned_flag ? (Type_handler *) &type_handler_ulonglong :
|
||||
(Type_handler *) &type_handler_slonglong,
|
||||
&my_charset_numeric);
|
||||
break;
|
||||
}
|
||||
case STRING_RESULT:
|
||||
{
|
||||
if (!save_result.vstr) // Null value
|
||||
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, 0);
|
||||
res= update_hash((void*) 0, 0, &type_handler_long_blob, &my_charset_bin);
|
||||
else
|
||||
res= update_hash((void*) save_result.vstr->ptr(),
|
||||
save_result.vstr->length(), STRING_RESULT,
|
||||
save_result.vstr->charset(), 0);
|
||||
save_result.vstr->length(),
|
||||
field_type() == MYSQL_TYPE_GEOMETRY ?
|
||||
type_handler() : &type_handler_long_blob,
|
||||
save_result.vstr->charset());
|
||||
break;
|
||||
}
|
||||
case DECIMAL_RESULT:
|
||||
{
|
||||
if (!save_result.vdec) // Null value
|
||||
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, 0);
|
||||
res= update_hash((void*) 0, 0, &type_handler_newdecimal, &my_charset_bin);
|
||||
else
|
||||
res= update_hash((void*) save_result.vdec,
|
||||
sizeof(my_decimal), DECIMAL_RESULT,
|
||||
&my_charset_numeric, 0);
|
||||
sizeof(my_decimal), &type_handler_newdecimal,
|
||||
&my_charset_numeric);
|
||||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
@ -5618,9 +5620,8 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
||||
user_var_event->value= (char*) user_var_event +
|
||||
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
||||
user_var_event->user_var_event= var_entry;
|
||||
user_var_event->type= var_entry->type;
|
||||
user_var_event->th= var_entry->type_handler();
|
||||
user_var_event->charset_number= var_entry->charset()->number;
|
||||
user_var_event->unsigned_flag= var_entry->unsigned_flag;
|
||||
if (!var_entry->value)
|
||||
{
|
||||
/* NULL value*/
|
||||
@ -5663,9 +5664,9 @@ bool Item_func_get_user_var::fix_length_and_dec()
|
||||
*/
|
||||
if (likely(!error && m_var_entry))
|
||||
{
|
||||
unsigned_flag= m_var_entry->unsigned_flag;
|
||||
unsigned_flag= m_var_entry->type_handler()->is_unsigned();
|
||||
max_length= (uint32)m_var_entry->length;
|
||||
switch (m_var_entry->type) {
|
||||
switch (m_var_entry->type_handler()->result_type()) {
|
||||
case REAL_RESULT:
|
||||
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
||||
fix_char_length(DBL_DIG + 8);
|
||||
@ -5684,6 +5685,8 @@ bool Item_func_get_user_var::fix_length_and_dec()
|
||||
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
|
||||
max_length= MAX_BLOB_WIDTH - 1;
|
||||
set_handler(&type_handler_long_blob);
|
||||
if (m_var_entry->type_handler()->field_type() == MYSQL_TYPE_GEOMETRY)
|
||||
set_handler(m_var_entry->type_handler());
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
collation.set(&my_charset_numeric, DERIVATION_NUMERIC);
|
||||
@ -5756,7 +5759,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||
DBUG_ASSERT(thd->lex->exchange);
|
||||
if (!(entry= get_variable(&thd->user_vars, &org_name, 1)))
|
||||
return TRUE;
|
||||
entry->type= STRING_RESULT;
|
||||
entry->set_handler(&type_handler_long_blob);
|
||||
/*
|
||||
Let us set the same collation which is used for loading
|
||||
of fields in LOAD DATA INFILE.
|
||||
@ -5772,15 +5775,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||
|
||||
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
|
||||
{
|
||||
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */);
|
||||
::update_hash(entry, TRUE, 0, 0, &type_handler_long_blob, cs);
|
||||
}
|
||||
|
||||
|
||||
void Item_user_var_as_out_param::set_value(const char *str, uint length,
|
||||
CHARSET_INFO* cs)
|
||||
{
|
||||
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
|
||||
0 /* unsigned_arg */);
|
||||
::update_hash(entry, FALSE, (void*)str, length, &type_handler_long_blob, cs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3066,8 +3066,8 @@ public:
|
||||
String *str_result(String *str);
|
||||
my_decimal *val_decimal_result(my_decimal *);
|
||||
bool is_null_result();
|
||||
bool update_hash(void *ptr, size_t length, enum Item_result type,
|
||||
CHARSET_INFO *cs, bool unsigned_arg);
|
||||
bool update_hash(void *ptr, size_t length, const Type_handler *th,
|
||||
CHARSET_INFO *cs);
|
||||
bool send(Protocol *protocol, st_value *buffer);
|
||||
void make_send_field(THD *thd, Send_field *tmp_field);
|
||||
bool check(bool use_result_field);
|
||||
@ -3825,7 +3825,6 @@ double my_double_round(double value, longlong dec, bool dec_unsigned,
|
||||
extern bool volatile mqh_used;
|
||||
|
||||
bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
|
||||
Item_result type, CHARSET_INFO *cs,
|
||||
bool unsigned_arg);
|
||||
const Type_handler *th, CHARSET_INFO *cs);
|
||||
|
||||
#endif /* ITEM_FUNC_INCLUDED */
|
||||
|
10
sql/log.cc
10
sql/log.cc
@ -6794,18 +6794,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
|
||||
BINLOG_USER_VAR_EVENT *user_var_event;
|
||||
get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i);
|
||||
|
||||
/* setting flags for user var log event */
|
||||
uchar flags= User_var_log_event::UNDEF_F;
|
||||
if (user_var_event->unsigned_flag)
|
||||
flags|= User_var_log_event::UNSIGNED_F;
|
||||
|
||||
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
|
||||
user_var_event->user_var_event->name.length,
|
||||
user_var_event->value,
|
||||
user_var_event->length,
|
||||
user_var_event->type,
|
||||
user_var_event->charset_number,
|
||||
flags,
|
||||
user_var_event->th->user_var_log_event_data_type(
|
||||
user_var_event->charset_number),
|
||||
using_trans,
|
||||
direct);
|
||||
if (write_event(&e, cache_data, file))
|
||||
|
@ -2880,6 +2880,41 @@ XA_prepare_log_event(const char* buf,
|
||||
User_var_log_event methods
|
||||
**************************************************************************/
|
||||
|
||||
bool Log_event_data_type::unpack_optional_attributes(const char *pos,
|
||||
const char *end)
|
||||
|
||||
{
|
||||
for ( ; pos < end; )
|
||||
{
|
||||
switch (*pos) {
|
||||
case CHUNK_SIGNED:
|
||||
m_is_unsigned= false;
|
||||
pos++;
|
||||
continue;
|
||||
case CHUNK_UNSIGNED:
|
||||
m_is_unsigned= true;
|
||||
pos++;
|
||||
continue;
|
||||
case CHUNK_DATA_TYPE_NAME:
|
||||
{
|
||||
pos++;
|
||||
if (pos >= end)
|
||||
return true;
|
||||
uint length= (uchar) *pos++;
|
||||
if (pos + length > end)
|
||||
return true;
|
||||
m_data_type_name= {pos, length};
|
||||
pos+= length;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
break; // Unknown chunk
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
User_var_log_event::
|
||||
User_var_log_event(const char* buf, uint event_len,
|
||||
const Format_description_log_event* description_event)
|
||||
@ -2917,11 +2952,8 @@ User_var_log_event(const char* buf, uint event_len,
|
||||
|
||||
buf+= UV_NAME_LEN_SIZE + name_len;
|
||||
is_null= (bool) *buf;
|
||||
flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F
|
||||
if (is_null)
|
||||
{
|
||||
type= STRING_RESULT;
|
||||
charset_number= my_charset_bin.number;
|
||||
val_len= 0;
|
||||
val= 0;
|
||||
}
|
||||
@ -2936,8 +2968,8 @@ User_var_log_event(const char* buf, uint event_len,
|
||||
goto err;
|
||||
}
|
||||
|
||||
type= (Item_result) buf[UV_VAL_IS_NULL];
|
||||
charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
|
||||
m_type= (Item_result) buf[UV_VAL_IS_NULL];
|
||||
m_charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
|
||||
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||
UV_CHARSET_NUMBER_SIZE);
|
||||
|
||||
@ -2950,20 +2982,14 @@ User_var_log_event(const char* buf, uint event_len,
|
||||
the flags value.
|
||||
|
||||
Old events will not have this extra byte, thence,
|
||||
we keep the flags set to UNDEF_F.
|
||||
we keep m_is_unsigned==false.
|
||||
*/
|
||||
size_t bytes_read= (val + val_len) - buf_start;
|
||||
if (bytes_read > event_len)
|
||||
const char *pos= val + val_len;
|
||||
if (pos > buf_end || unpack_optional_attributes(pos, buf_end))
|
||||
{
|
||||
error= true;
|
||||
goto err;
|
||||
}
|
||||
if ((data_written - bytes_read) > 0)
|
||||
{
|
||||
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
|
||||
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE +
|
||||
val_len);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
|
@ -57,6 +57,8 @@
|
||||
|
||||
#include "rpl_gtid.h"
|
||||
|
||||
#include "log_event_data_type.h"
|
||||
|
||||
/* Forward declarations */
|
||||
#ifndef MYSQL_CLIENT
|
||||
class String;
|
||||
@ -3269,32 +3271,27 @@ private:
|
||||
@section User_var_log_event_binary_format Binary Format
|
||||
*/
|
||||
|
||||
class User_var_log_event: public Log_event
|
||||
|
||||
class User_var_log_event: public Log_event, public Log_event_data_type
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
UNDEF_F= 0,
|
||||
UNSIGNED_F= 1
|
||||
};
|
||||
const char *name;
|
||||
size_t name_len;
|
||||
const char *val;
|
||||
size_t val_len;
|
||||
Item_result type;
|
||||
uint charset_number;
|
||||
bool is_null;
|
||||
uchar flags;
|
||||
#ifdef MYSQL_SERVER
|
||||
bool deferred;
|
||||
query_id_t query_id;
|
||||
User_var_log_event(THD* thd_arg, const char *name_arg, size_t name_len_arg,
|
||||
const char *val_arg, size_t val_len_arg, Item_result type_arg,
|
||||
uint charset_number_arg, uchar flags_arg,
|
||||
const char *val_arg, size_t val_len_arg,
|
||||
const Log_event_data_type &data_type,
|
||||
bool using_trans, bool direct)
|
||||
:Log_event(thd_arg, 0, using_trans),
|
||||
Log_event_data_type(data_type),
|
||||
name(name_arg), name_len(name_len_arg), val(val_arg),
|
||||
val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
|
||||
flags(flags_arg), deferred(false)
|
||||
val_len(val_len_arg),
|
||||
deferred(false)
|
||||
{
|
||||
is_null= !val;
|
||||
if (direct)
|
||||
|
@ -2435,7 +2435,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
switch (m_type) {
|
||||
case REAL_RESULT:
|
||||
double real_val;
|
||||
char real_buf[FMT_G_BUFSIZE(14)];
|
||||
@ -2447,8 +2447,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||
break;
|
||||
case INT_RESULT:
|
||||
char int_buf[22];
|
||||
longlong10_to_str(uint8korr(val), int_buf,
|
||||
((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
|
||||
longlong10_to_str(uint8korr(val), int_buf, is_unsigned() ? 10 : -10);
|
||||
if (my_b_printf(&cache, ":=%s%s\n", int_buf,
|
||||
print_event_info->delimiter))
|
||||
goto err;
|
||||
@ -2503,7 +2502,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||
people want to mysqlbinlog|mysql into another server not supporting the
|
||||
character set. But there's not much to do about this and it's unlikely.
|
||||
*/
|
||||
if (!(cs= get_charset(charset_number, MYF(0))))
|
||||
if (!(cs= get_charset(m_charset_number, MYF(0))))
|
||||
{ /*
|
||||
Generate an unusable command (=> syntax error) is probably the best
|
||||
thing we can do here.
|
||||
|
74
sql/log_event_data_type.h
Normal file
74
sql/log_event_data_type.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright (c) 2024, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef LOG_EVENT_DATA_TYPE_H
|
||||
#define LOG_EVENT_DATA_TYPE_H
|
||||
|
||||
class Log_event_data_type
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
CHUNK_SIGNED= 0,
|
||||
CHUNK_UNSIGNED= 1,
|
||||
CHUNK_DATA_TYPE_NAME= 2
|
||||
};
|
||||
|
||||
protected:
|
||||
LEX_CSTRING m_data_type_name;
|
||||
Item_result m_type;
|
||||
uint m_charset_number;
|
||||
bool m_is_unsigned;
|
||||
|
||||
public:
|
||||
|
||||
Log_event_data_type()
|
||||
:m_data_type_name({NULL,0}),
|
||||
m_type(STRING_RESULT),
|
||||
m_charset_number(my_charset_bin.number),
|
||||
m_is_unsigned(false)
|
||||
{ }
|
||||
|
||||
Log_event_data_type(const LEX_CSTRING &data_type_name_arg,
|
||||
Item_result type_arg,
|
||||
uint charset_number_arg,
|
||||
bool is_unsigned_arg)
|
||||
:m_data_type_name(data_type_name_arg),
|
||||
m_type(type_arg),
|
||||
m_charset_number(charset_number_arg),
|
||||
m_is_unsigned(is_unsigned_arg)
|
||||
{ }
|
||||
|
||||
const LEX_CSTRING & data_type_name() const
|
||||
{
|
||||
return m_data_type_name;
|
||||
}
|
||||
Item_result type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
uint charset_number() const
|
||||
{
|
||||
return m_charset_number;
|
||||
}
|
||||
bool is_unsigned() const
|
||||
{
|
||||
return m_is_unsigned;
|
||||
}
|
||||
|
||||
bool unpack_optional_attributes(const char *str, const char *end);
|
||||
};
|
||||
|
||||
#endif // LOG_EVENT_DATA_TYPE_H
|
@ -4170,11 +4170,16 @@ bool XA_prepare_log_event::write()
|
||||
#if defined(HAVE_REPLICATION)
|
||||
static bool
|
||||
user_var_append_name_part(THD *thd, String *buf,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len,
|
||||
const LEX_CSTRING &data_type_name)
|
||||
{
|
||||
return buf->append("@") ||
|
||||
append_identifier(thd, buf, name, name_len) ||
|
||||
buf->append("=");
|
||||
buf->append("=") ||
|
||||
(data_type_name.length &&
|
||||
(buf->append("/*") ||
|
||||
buf->append(data_type_name.str, data_type_name.length) ||
|
||||
buf->append("*/")));
|
||||
}
|
||||
|
||||
void User_var_log_event::pack_info(Protocol* protocol)
|
||||
@ -4184,14 +4189,15 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
char buf_mem[FN_REFLEN+7];
|
||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||
buf.length(0);
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||
m_data_type_name) ||
|
||||
buf.append("NULL"))
|
||||
return;
|
||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
switch (m_type) {
|
||||
case REAL_RESULT:
|
||||
{
|
||||
double real_val;
|
||||
@ -4200,7 +4206,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||
float8get(real_val, val);
|
||||
buf.length(0);
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||
m_data_type_name) ||
|
||||
buf.append(buf2, my_gcvt(real_val, MY_GCVT_ARG_DOUBLE,
|
||||
MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL)))
|
||||
return;
|
||||
@ -4213,10 +4220,11 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
char buf_mem[FN_REFLEN + 22];
|
||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||
buf.length(0);
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||
m_data_type_name) ||
|
||||
buf.append(buf2,
|
||||
longlong10_to_str(uint8korr(val), buf2,
|
||||
((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10))-buf2))
|
||||
(is_unsigned() ? 10 : -10))-buf2))
|
||||
return;
|
||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||
break;
|
||||
@ -4229,7 +4237,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
String str(buf2, sizeof(buf2), &my_charset_bin);
|
||||
buf.length(0);
|
||||
my_decimal((const uchar *) (val + 2), val[0], val[1]).to_string(&str);
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||
m_data_type_name) ||
|
||||
buf.append(buf2))
|
||||
return;
|
||||
protocol->store(buf.ptr(), buf.length(), &my_charset_bin);
|
||||
@ -4242,7 +4251,7 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
String buf(buf_mem, sizeof(buf_mem), system_charset_info);
|
||||
CHARSET_INFO *cs;
|
||||
buf.length(0);
|
||||
if (!(cs= get_charset(charset_number, MYF(0))))
|
||||
if (!(cs= get_charset(m_charset_number, MYF(0))))
|
||||
{
|
||||
if (buf.append("???"))
|
||||
return;
|
||||
@ -4251,7 +4260,8 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
||||
{
|
||||
size_t old_len;
|
||||
char *beg, *end;
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len) ||
|
||||
if (user_var_append_name_part(protocol->thd, &buf, name, name_len,
|
||||
m_data_type_name) ||
|
||||
buf.append("_") ||
|
||||
buf.append(cs->csname) ||
|
||||
buf.append(" "))
|
||||
@ -4299,10 +4309,10 @@ bool User_var_log_event::write()
|
||||
}
|
||||
else
|
||||
{
|
||||
buf1[1]= type;
|
||||
int4store(buf1 + 2, charset_number);
|
||||
buf1[1]= m_type;
|
||||
int4store(buf1 + 2, m_charset_number);
|
||||
|
||||
switch (type) {
|
||||
switch (m_type) {
|
||||
case REAL_RESULT:
|
||||
float8store(buf2, *(double*) val);
|
||||
break;
|
||||
@ -4332,15 +4342,28 @@ bool User_var_log_event::write()
|
||||
buf1_length= 10;
|
||||
}
|
||||
|
||||
/* Length of the whole event */
|
||||
event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len;
|
||||
uchar data_type_name_chunk_signature= (uchar) CHUNK_DATA_TYPE_NAME;
|
||||
uint data_type_name_chunk_signature_length= m_data_type_name.length ? 1 : 0;
|
||||
uchar data_type_name_length_length= m_data_type_name.length ? 1 : 0;
|
||||
|
||||
/* Length of the whole event */
|
||||
event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len +
|
||||
data_type_name_chunk_signature_length +
|
||||
data_type_name_length_length +
|
||||
(uint) m_data_type_name.length;
|
||||
|
||||
uchar unsig= m_is_unsigned ? CHUNK_UNSIGNED : CHUNK_SIGNED;
|
||||
uchar data_type_name_length= (uchar) m_data_type_name.length;
|
||||
return write_header(event_length) ||
|
||||
write_data(buf, sizeof(buf)) ||
|
||||
write_data(name, name_len) ||
|
||||
write_data(buf1, buf1_length) ||
|
||||
write_data(pos, val_len) ||
|
||||
write_data(&flags, unsigned_len) ||
|
||||
write_data(&unsig, unsigned_len) ||
|
||||
write_data(&data_type_name_chunk_signature,
|
||||
data_type_name_chunk_signature_length) ||
|
||||
write_data(&data_type_name_length, data_type_name_length_length) ||
|
||||
write_data(m_data_type_name.str, (uint) m_data_type_name.length) ||
|
||||
write_footer();
|
||||
}
|
||||
|
||||
@ -4364,7 +4387,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
current_thd->query_id= query_id; /* recreating original time context */
|
||||
}
|
||||
|
||||
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
|
||||
if (!(charset= get_charset(m_charset_number, MYF(MY_WME))))
|
||||
{
|
||||
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
|
||||
ER_THD(thd, ER_SLAVE_FATAL_ERROR),
|
||||
@ -4383,7 +4406,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type) {
|
||||
switch (m_type) {
|
||||
case REAL_RESULT:
|
||||
if (val_len != 8)
|
||||
{
|
||||
@ -4447,13 +4470,10 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
if (e->fix_fields(thd, 0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
A variable can just be considered as a table with
|
||||
a single record and with a single column. Thus, like
|
||||
a column value, it could always have IMPLICIT derivation.
|
||||
*/
|
||||
e->update_hash((void*) val, val_len, type, charset,
|
||||
(flags & User_var_log_event::UNSIGNED_F));
|
||||
const Type_handler *th= Type_handler::handler_by_log_event_data_type(thd,
|
||||
*this);
|
||||
e->update_hash((void*) val, val_len, th, charset);
|
||||
|
||||
if (!is_deferred())
|
||||
free_root(thd->mem_root, 0);
|
||||
else
|
||||
|
@ -134,7 +134,7 @@ int binlog_defragment(THD *thd)
|
||||
entry[k]=
|
||||
(user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str,
|
||||
name[k].length);
|
||||
if (!entry[k] || entry[k]->type != STRING_RESULT)
|
||||
if (!entry[k] || entry[k]->type_handler()->result_type() != STRING_RESULT)
|
||||
{
|
||||
my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), name[k].str);
|
||||
return -1;
|
||||
@ -159,7 +159,8 @@ int binlog_defragment(THD *thd)
|
||||
gathered_length += entry[k]->length;
|
||||
}
|
||||
for (uint k=0; k < 2; k++)
|
||||
update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0);
|
||||
update_hash(entry[k], true, NULL, 0,
|
||||
&type_handler_long_blob, &my_charset_bin);
|
||||
|
||||
DBUG_ASSERT(gathered_length == thd->lex->comment.length);
|
||||
|
||||
|
@ -275,9 +275,8 @@ typedef struct st_user_var_events
|
||||
user_var_entry *user_var_event;
|
||||
char *value;
|
||||
size_t length;
|
||||
Item_result type;
|
||||
const Type_handler *th;
|
||||
uint charset_number;
|
||||
bool unsigned_flag;
|
||||
} BINLOG_USER_VAR_EVENT;
|
||||
|
||||
/*
|
||||
@ -6808,7 +6807,7 @@ public:
|
||||
|
||||
|
||||
// this is needed for user_vars hash
|
||||
class user_var_entry
|
||||
class user_var_entry: public Type_handler_hybrid_field_type
|
||||
{
|
||||
CHARSET_INFO *m_charset;
|
||||
public:
|
||||
@ -6817,8 +6816,6 @@ class user_var_entry
|
||||
char *value;
|
||||
size_t length;
|
||||
query_id_t update_query_id, used_query_id;
|
||||
Item_result type;
|
||||
bool unsigned_flag;
|
||||
|
||||
double val_real(bool *null_value);
|
||||
longlong val_int(bool *null_value) const;
|
||||
|
@ -510,7 +510,7 @@ static enum enum_binlog_checksum_alg get_binlog_checksum_value_at_connect(THD *
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(entry->type == STRING_RESULT);
|
||||
DBUG_ASSERT(entry->type_handler()->result_type() == STRING_RESULT);
|
||||
String str;
|
||||
uint dummy_errors;
|
||||
str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin,
|
||||
|
@ -2248,6 +2248,34 @@ Type_handler::get_handler_by_real_type(enum_field_types type)
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *
|
||||
Type_handler::handler_by_log_event_data_type(THD *thd,
|
||||
const Log_event_data_type &type)
|
||||
{
|
||||
if (type.data_type_name().length)
|
||||
{
|
||||
const Type_handler *th= handler_by_name(thd, type.data_type_name());
|
||||
if (th)
|
||||
return th;
|
||||
}
|
||||
switch (type.type()) {
|
||||
case STRING_RESULT:
|
||||
case ROW_RESULT:
|
||||
case TIME_RESULT:
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
return &type_handler_double;
|
||||
case INT_RESULT:
|
||||
if (type.is_unsigned())
|
||||
return &type_handler_ulonglong;
|
||||
return &type_handler_slonglong;
|
||||
case DECIMAL_RESULT:
|
||||
return &type_handler_newdecimal;
|
||||
}
|
||||
return &type_handler_long_blob;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a DOUBLE field by default.
|
||||
*/
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "sql_type_string.h"
|
||||
#include "sql_type_real.h"
|
||||
#include "compat56.h"
|
||||
#include "log_event_data_type.h"
|
||||
|
||||
C_MODE_START
|
||||
#include <ma_dyncol.h>
|
||||
C_MODE_END
|
||||
@ -3652,6 +3654,9 @@ public:
|
||||
static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name);
|
||||
static const Type_handler *handler_by_name_or_error(THD *thd,
|
||||
const LEX_CSTRING &name);
|
||||
static const Type_handler *handler_by_log_event_data_type(
|
||||
THD *thd,
|
||||
const Log_event_data_type &type);
|
||||
static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str);
|
||||
static const Type_handler *blob_type_handler(uint max_octet_length);
|
||||
static const Type_handler *string_type_handler(uint max_octet_length);
|
||||
@ -3936,6 +3941,12 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Log_event_data_type user_var_log_event_data_type(uint charset_nr) const
|
||||
{
|
||||
return Log_event_data_type({NULL,0}/*data type name*/, result_type(),
|
||||
charset_nr, is_unsigned());
|
||||
}
|
||||
virtual uint Column_definition_gis_options_image(uchar *buff,
|
||||
const Column_definition &def)
|
||||
const
|
||||
|
@ -81,6 +81,13 @@ public:
|
||||
Field *make_conversion_table_field(MEM_ROOT *root,
|
||||
TABLE *table, uint metadata,
|
||||
const Field *target) const override;
|
||||
Log_event_data_type user_var_log_event_data_type(uint charset_nr)
|
||||
const override
|
||||
{
|
||||
return Log_event_data_type(name().lex_cstring(), result_type(),
|
||||
charset_nr, false/*unsigned*/);
|
||||
}
|
||||
|
||||
uint Column_definition_gis_options_image(uchar *buff,
|
||||
const Column_definition &def)
|
||||
const override;
|
||||
|
@ -1886,7 +1886,7 @@ int spider_conn_queue_loop_check(
|
||||
loop_check_buf[lex_str.length] = '\0';
|
||||
DBUG_PRINT("info", ("spider param name=%s", lex_str.str));
|
||||
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
||||
if (!loop_check || loop_check->type != STRING_RESULT)
|
||||
if (!loop_check || loop_check->type_handler()->result_type() != STRING_RESULT)
|
||||
{
|
||||
DBUG_PRINT("info", ("spider client is not Spider"));
|
||||
lex_str.str = "";
|
||||
|
@ -4742,7 +4742,7 @@ SPIDER_SHARE *spider_get_share(
|
||||
((char *) lex_str.str)[lex_str.length] = '\0';
|
||||
DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str));
|
||||
loop_check = get_variable(&thd->user_vars, &lex_str, FALSE);
|
||||
if (loop_check && loop_check->type == STRING_RESULT)
|
||||
if (loop_check && loop_check->type_handler()->result_type() == STRING_RESULT)
|
||||
{
|
||||
lex_str.length = top_share->path.length + spider_unique_id.length + 1;
|
||||
lex_str.str = loop_check_buf + buf_sz - top_share->path.length -
|
||||
|
Loading…
x
Reference in New Issue
Block a user