mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Uninitialized Column_definition::pack_flag for ROW-type SP variables and their fields
Fixed that the Column_definition::pack_flag member corresponding to ROW-type SP variables and their fields was not properly initialized. This lead to sporadic test failures. Valgrind complained about jumps depending on uninitialized value in VALGRIND builds. This patch makes sure that sp_head::fill_spvar_definition() is always called for ROW variables and their fields. Additionally, fixed that a function with a scalar parameter erroneously acceptes ROWs with one fields. Now an error is returned.
This commit is contained in:
@ -274,8 +274,7 @@ SELECT f1(a);
|
|||||||
END;
|
END;
|
||||||
$$
|
$$
|
||||||
CALL p1();
|
CALL p1();
|
||||||
f1(a)
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
NULL
|
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
#
|
#
|
||||||
|
@ -351,7 +351,7 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$$
|
$$
|
||||||
DELIMITER ;$$
|
DELIMITER ;$$
|
||||||
#--error ER_OPERAND_COLUMNS
|
--error ER_OPERAND_COLUMNS
|
||||||
CALL p1();
|
CALL p1();
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP FUNCTION f1;
|
DROP FUNCTION f1;
|
||||||
|
@ -10583,6 +10583,7 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
|
|||||||
default_value= orig_field ? orig_field->default_value : 0;
|
default_value= orig_field ? orig_field->default_value : 0;
|
||||||
check_constraint= orig_field ? orig_field->check_constraint : 0;
|
check_constraint= orig_field ? orig_field->check_constraint : 0;
|
||||||
option_list= old_field->option_list;
|
option_list= old_field->option_list;
|
||||||
|
pack_flag= 0;
|
||||||
|
|
||||||
switch (sql_type) {
|
switch (sql_type) {
|
||||||
case MYSQL_TYPE_BLOB:
|
case MYSQL_TYPE_BLOB:
|
||||||
|
@ -3844,7 +3844,7 @@ public:
|
|||||||
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
|
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
|
||||||
interval(0), charset(&my_charset_bin),
|
interval(0), charset(&my_charset_bin),
|
||||||
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
||||||
option_list(NULL),
|
option_list(NULL), pack_flag(0),
|
||||||
vcol_info(0), default_value(0), check_constraint(0)
|
vcol_info(0), default_value(0), check_constraint(0)
|
||||||
{
|
{
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
@ -3857,7 +3857,7 @@ public:
|
|||||||
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
|
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
|
||||||
interval(0), charset(&my_charset_bin),
|
interval(0), charset(&my_charset_bin),
|
||||||
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
||||||
option_list(NULL),
|
option_list(NULL), pack_flag(0),
|
||||||
vcol_info(0), default_value(0), check_constraint(0)
|
vcol_info(0), default_value(0), check_constraint(0)
|
||||||
{
|
{
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
|
@ -398,7 +398,8 @@ sp_eval_expr(THD *thd, Item *result_item, Field *result_field,
|
|||||||
expr_item is now fixed, it's safe to call cmp_type()
|
expr_item is now fixed, it's safe to call cmp_type()
|
||||||
If result_item is NULL, then we're setting the RETURN value.
|
If result_item is NULL, then we're setting the RETURN value.
|
||||||
*/
|
*/
|
||||||
if (!result_item && expr_item->cmp_type() == ROW_RESULT)
|
if ((!result_item || result_item->cmp_type() != ROW_RESULT) &&
|
||||||
|
expr_item->cmp_type() == ROW_RESULT)
|
||||||
{
|
{
|
||||||
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -632,6 +632,21 @@ public:
|
|||||||
return field_def->check(thd) ||
|
return field_def->check(thd) ||
|
||||||
field_def->sp_prepare_create_field(thd, mem_root);
|
field_def->sp_prepare_create_field(thd, mem_root);
|
||||||
}
|
}
|
||||||
|
bool row_fill_field_definitions(THD *thd, Row_definition_list *row)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Prepare all row fields. This will (among other things)
|
||||||
|
- convert VARCHAR lengths from character length to octet length
|
||||||
|
- calculate interval lengths for SET and ENUM
|
||||||
|
*/
|
||||||
|
List_iterator<Spvar_definition> it(*row);
|
||||||
|
for (Spvar_definition *def= it++; def; def= it++)
|
||||||
|
{
|
||||||
|
if (fill_spvar_definition(thd, def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Check and prepare a Column_definition for a variable or a parameter.
|
Check and prepare a Column_definition for a variable or a parameter.
|
||||||
*/
|
*/
|
||||||
|
@ -5233,30 +5233,20 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
|
|||||||
!(dflt_value_item= new (thd->mem_root) Item_null(thd)))
|
!(dflt_value_item= new (thd->mem_root) Item_null(thd)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (row)
|
/*
|
||||||
{
|
Prepare all row fields.
|
||||||
/*
|
Note, we do it only one time outside of the below loop.
|
||||||
Prepare all row fields. This will (among other things)
|
The converted list in "row" is further reused by all variable
|
||||||
- convert VARCHAR lengths from character length to octet length
|
declarations processed by the current call.
|
||||||
- calculate interval lengths for SET and ENUM
|
Example:
|
||||||
Note, we do it only one time outside of the below loop.
|
DECLARE
|
||||||
The converted list in "row" is further reused by all variable
|
a, b, c ROW(x VARCHAR(10) CHARACTER SET utf8);
|
||||||
declarations processed by the current call.
|
BEGIN
|
||||||
Example:
|
...
|
||||||
DECLARE
|
END;
|
||||||
a, b, c ROW(x VARCHAR(10) CHARACTER SET utf8);
|
*/
|
||||||
BEGIN
|
if (row && sphead->row_fill_field_definitions(thd, row))
|
||||||
...
|
return true;
|
||||||
END;
|
|
||||||
*/
|
|
||||||
List_iterator<Spvar_definition> it(*row);
|
|
||||||
for (Spvar_definition *def= it++; def; def= it++)
|
|
||||||
{
|
|
||||||
def->pack_flag|= FIELDFLAG_MAYBE_NULL;
|
|
||||||
if (sphead->fill_field_definition(thd, def))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint i= num_vars - nvars ; i < num_vars ; i++)
|
for (uint i= num_vars - nvars ; i < num_vars ; i++)
|
||||||
{
|
{
|
||||||
@ -5273,9 +5263,9 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
|
|||||||
{
|
{
|
||||||
if (!last)
|
if (!last)
|
||||||
spvar->field_def.set_column_definition(cdef);
|
spvar->field_def.set_column_definition(cdef);
|
||||||
if (sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str))
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str))
|
||||||
|
return true;
|
||||||
spvar->field_def.set_row_field_definitions(row);
|
spvar->field_def.set_row_field_definitions(row);
|
||||||
|
|
||||||
/* The last instruction is responsible for freeing LEX. */
|
/* The last instruction is responsible for freeing LEX. */
|
||||||
@ -5345,7 +5335,7 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
|
|||||||
return true;
|
return true;
|
||||||
spvar->field_def.set_table_rowtype_ref(table_ref);
|
spvar->field_def.set_table_rowtype_ref(table_ref);
|
||||||
}
|
}
|
||||||
spvar->field_def.field_name= spvar->name.str;
|
sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str);
|
||||||
spvar->default_value= def;
|
spvar->default_value= def;
|
||||||
/* The last instruction is responsible for freeing LEX. */
|
/* The last instruction is responsible for freeing LEX. */
|
||||||
sp_instr_set *is= new (this->thd->mem_root)
|
sp_instr_set *is= new (this->thd->mem_root)
|
||||||
@ -5442,7 +5432,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd,
|
|||||||
{
|
{
|
||||||
sp_variable *spvar= spcont->add_variable(thd, name);
|
sp_variable *spvar= spcont->add_variable(thd, name);
|
||||||
spcont->declare_var_boundary(1);
|
spcont->declare_var_boundary(1);
|
||||||
spvar->field_def.field_name= spvar->name.str;
|
sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str);
|
||||||
spvar->default_value= new (thd->mem_root) Item_null(thd);
|
spvar->default_value= new (thd->mem_root) Item_null(thd);
|
||||||
|
|
||||||
Cursor_rowtype *ref;
|
Cursor_rowtype *ref;
|
||||||
|
@ -2859,6 +2859,8 @@ sp_param_name_and_type:
|
|||||||
{
|
{
|
||||||
$$= $1;
|
$$= $1;
|
||||||
$$->field_def.field_name= $$->name.str;
|
$$->field_def.field_name= $$->name.str;
|
||||||
|
Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
|
||||||
|
Lex->sphead->row_fill_field_definitions(thd, $2);
|
||||||
$$->field_def.set_row_field_definitions($2);
|
$$->field_def.set_row_field_definitions($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -2339,6 +2339,8 @@ sp_param_name_and_type:
|
|||||||
{
|
{
|
||||||
$$= $1;
|
$$= $1;
|
||||||
$$->field_def.field_name= $$->name.str;
|
$$->field_def.field_name= $$->name.str;
|
||||||
|
Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
|
||||||
|
Lex->sphead->row_fill_field_definitions(thd, $2);
|
||||||
$$->field_def.set_row_field_definitions($2);
|
$$->field_def.set_row_field_definitions($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -2369,6 +2371,8 @@ sp_pdparam:
|
|||||||
{
|
{
|
||||||
$1->mode= $2;
|
$1->mode= $2;
|
||||||
$1->field_def.field_name= $1->name.str;
|
$1->field_def.field_name= $1->name.str;
|
||||||
|
Lex->sphead->fill_spvar_definition(thd, &$1->field_def);
|
||||||
|
Lex->sphead->row_fill_field_definitions(thd, $3);
|
||||||
$1->field_def.set_row_field_definitions($3);
|
$1->field_def.set_row_field_definitions($3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
Reference in New Issue
Block a user