mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug#3788
Crashes with stored procedure return non-string values Also fixes Bug#2773 mysql-test/r/information_schema.result: Bug#3788 Fix results for bugfix mysql-test/r/sp.result: Bug#3788 Tests for Bug Fix results for bugfix mysql-test/t/sp.test: Bug#3788 New tests for bug sql/item.cc: Fix unrelated crash in view test with --ps-protocol. sql/item_func.cc: Bug#3788 Alter how SP function result types are handled. sql/item_func.h: Bug#3788 Alter how SP function result types are handled. sql/mysql_priv.h: Bug#3788 Prototypes for new global functions sql/sp.cc: Bug#3788 Alter how function return type is reported sql/sp_head.cc: Bug#3788 Change how function return types are stored for SPs sql/sp_head.h: Bug#3788 Change how function return types are stored for SPs sql/sql_parse.cc: Bug#3788 Split out field construction into its own function sql/sql_table.cc: Bug#3788 Split out field preparation code into its own function sql/sql_yacc.yy: Bug#3788 Change how function return types are stored for SPs sql/unireg.cc: Bug#3788 Add assertion check
This commit is contained in:
314
sql/sql_table.cc
314
sql/sql_table.cc
@ -424,6 +424,173 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Prepare a create_table instance for packing
|
||||
|
||||
SYNOPSIS
|
||||
prepare_create_field()
|
||||
sql_field field to prepare for packing
|
||||
blob_columns count for BLOBs
|
||||
timestamps count for timestamps
|
||||
table_flags table flags
|
||||
|
||||
DESCRIPTION
|
||||
This function prepares a create_field instance.
|
||||
Fields such as pack_flag are valid after this call.
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 Error
|
||||
*/
|
||||
|
||||
int prepare_create_field(create_field *sql_field,
|
||||
uint &blob_columns,
|
||||
int ×tamps, int ×tamps_with_niladic,
|
||||
uint table_flags)
|
||||
{
|
||||
DBUG_ENTER("prepare_field");
|
||||
{
|
||||
/* This code came from mysql_prepare_table.
|
||||
Indent preserved to make patching easier */
|
||||
DBUG_ASSERT(sql_field->charset);
|
||||
|
||||
switch (sql_field->sql_type) {
|
||||
case FIELD_TYPE_BLOB:
|
||||
case FIELD_TYPE_MEDIUM_BLOB:
|
||||
case FIELD_TYPE_TINY_BLOB:
|
||||
case FIELD_TYPE_LONG_BLOB:
|
||||
sql_field->pack_flag=FIELDFLAG_BLOB |
|
||||
pack_length_to_packflag(sql_field->pack_length -
|
||||
portable_sizeof_char_ptr);
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->length=8; // Unireg field length
|
||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||
blob_columns++;
|
||||
break;
|
||||
case FIELD_TYPE_GEOMETRY:
|
||||
#ifdef HAVE_SPATIAL
|
||||
if (!(table_flags & HA_CAN_GEOMETRY))
|
||||
{
|
||||
my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
|
||||
MYF(0), "GEOMETRY");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
sql_field->pack_flag=FIELDFLAG_GEOM |
|
||||
pack_length_to_packflag(sql_field->pack_length -
|
||||
portable_sizeof_char_ptr);
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->length=8; // Unireg field length
|
||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||
blob_columns++;
|
||||
break;
|
||||
#else
|
||||
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
|
||||
sym_group_geom.name, sym_group_geom.needed_define);
|
||||
DBUG_RETURN(1);
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
|
||||
if (table_flags & HA_NO_VARCHAR)
|
||||
{
|
||||
/* convert VARCHAR to CHAR because handler is not yet up to date */
|
||||
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
|
||||
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
|
||||
(uint) sql_field->length);
|
||||
if ((sql_field->length / sql_field->charset->mbmaxlen) >
|
||||
MAX_FIELD_CHARLENGTH)
|
||||
{
|
||||
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
|
||||
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* fall through */
|
||||
case FIELD_TYPE_STRING:
|
||||
sql_field->pack_flag=0;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
break;
|
||||
case FIELD_TYPE_ENUM:
|
||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||
FIELDFLAG_INTERVAL;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::INTERVAL_FIELD;
|
||||
check_duplicates_in_interval("ENUM",sql_field->field_name,
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_SET:
|
||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||
FIELDFLAG_BITFIELD;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::BIT_FIELD;
|
||||
check_duplicates_in_interval("SET",sql_field->field_name,
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_DATE: // Rest of string types
|
||||
case FIELD_TYPE_NEWDATE:
|
||||
case FIELD_TYPE_TIME:
|
||||
case FIELD_TYPE_DATETIME:
|
||||
case FIELD_TYPE_NULL:
|
||||
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
||||
break;
|
||||
case FIELD_TYPE_BIT:
|
||||
if (!(table_flags & HA_CAN_BIT_FIELD))
|
||||
{
|
||||
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
sql_field->pack_flag= FIELDFLAG_NUMBER;
|
||||
break;
|
||||
case FIELD_TYPE_NEWDECIMAL:
|
||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||
FIELDFLAG_DECIMAL) |
|
||||
(sql_field->flags & ZEROFILL_FLAG ?
|
||||
FIELDFLAG_ZEROFILL : 0) |
|
||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||
break;
|
||||
case FIELD_TYPE_TIMESTAMP:
|
||||
/* We should replace old TIMESTAMP fields with their newer analogs */
|
||||
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
|
||||
{
|
||||
if (!timestamps)
|
||||
{
|
||||
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
||||
timestamps_with_niladic++;
|
||||
}
|
||||
else
|
||||
sql_field->unireg_check= Field::NONE;
|
||||
}
|
||||
else if (sql_field->unireg_check != Field::NONE)
|
||||
timestamps_with_niladic++;
|
||||
|
||||
timestamps++;
|
||||
/* fall-through */
|
||||
default:
|
||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||
FIELDFLAG_DECIMAL) |
|
||||
(sql_field->flags & ZEROFILL_FLAG ?
|
||||
FIELDFLAG_ZEROFILL : 0) |
|
||||
f_settype((uint) sql_field->sql_type) |
|
||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||
break;
|
||||
}
|
||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
|
||||
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
|
||||
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Preparation for table creation
|
||||
|
||||
@ -683,142 +850,17 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
{
|
||||
DBUG_ASSERT(sql_field->charset);
|
||||
|
||||
switch (sql_field->sql_type) {
|
||||
case FIELD_TYPE_BLOB:
|
||||
case FIELD_TYPE_MEDIUM_BLOB:
|
||||
case FIELD_TYPE_TINY_BLOB:
|
||||
case FIELD_TYPE_LONG_BLOB:
|
||||
sql_field->pack_flag=FIELDFLAG_BLOB |
|
||||
pack_length_to_packflag(sql_field->pack_length -
|
||||
portable_sizeof_char_ptr);
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->length=8; // Unireg field length
|
||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||
blob_columns++;
|
||||
create_info->varchar= 1;
|
||||
break;
|
||||
case FIELD_TYPE_GEOMETRY:
|
||||
#ifdef HAVE_SPATIAL
|
||||
if (!(file->table_flags() & HA_CAN_GEOMETRY))
|
||||
{
|
||||
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
sql_field->pack_flag=FIELDFLAG_GEOM |
|
||||
pack_length_to_packflag(sql_field->pack_length -
|
||||
portable_sizeof_char_ptr);
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->length=8; // Unireg field length
|
||||
sql_field->unireg_check=Field::BLOB_FIELD;
|
||||
blob_columns++;
|
||||
create_info->varchar= 1;
|
||||
break;
|
||||
#else
|
||||
my_error(ER_FEATURE_DISABLED, MYF(0),
|
||||
sym_group_geom.name, sym_group_geom.needed_define);
|
||||
if (prepare_create_field(sql_field, blob_columns,
|
||||
timestamps, timestamps_with_niladic,
|
||||
file->table_flags()))
|
||||
DBUG_RETURN(-1);
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
|
||||
if (file->table_flags() & HA_NO_VARCHAR)
|
||||
{
|
||||
/* convert VARCHAR to CHAR because handler is not yet up to date */
|
||||
sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
|
||||
sql_field->pack_length= calc_pack_length(sql_field->sql_type,
|
||||
(uint) sql_field->length);
|
||||
if ((sql_field->length / sql_field->charset->mbmaxlen) >
|
||||
MAX_FIELD_CHARLENGTH)
|
||||
{
|
||||
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
|
||||
MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
create_info->varchar= 1;
|
||||
/* fall through */
|
||||
case MYSQL_TYPE_STRING:
|
||||
sql_field->pack_flag=0;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|= FIELDFLAG_BINARY;
|
||||
break;
|
||||
case FIELD_TYPE_ENUM:
|
||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||
FIELDFLAG_INTERVAL;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::INTERVAL_FIELD;
|
||||
check_duplicates_in_interval("ENUM",sql_field->field_name,
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_SET:
|
||||
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
|
||||
FIELDFLAG_BITFIELD;
|
||||
if (sql_field->charset->state & MY_CS_BINSORT)
|
||||
sql_field->pack_flag|=FIELDFLAG_BINARY;
|
||||
sql_field->unireg_check=Field::BIT_FIELD;
|
||||
check_duplicates_in_interval("SET",sql_field->field_name,
|
||||
sql_field->interval,
|
||||
sql_field->charset);
|
||||
break;
|
||||
case FIELD_TYPE_DATE: // Rest of string types
|
||||
case FIELD_TYPE_NEWDATE:
|
||||
case FIELD_TYPE_TIME:
|
||||
case FIELD_TYPE_DATETIME:
|
||||
case FIELD_TYPE_NULL:
|
||||
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
||||
break;
|
||||
case FIELD_TYPE_BIT:
|
||||
if (!(file->table_flags() & HA_CAN_BIT_FIELD))
|
||||
{
|
||||
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
sql_field->pack_flag= FIELDFLAG_NUMBER;
|
||||
break;
|
||||
case FIELD_TYPE_NEWDECIMAL:
|
||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||
FIELDFLAG_DECIMAL) |
|
||||
(sql_field->flags & ZEROFILL_FLAG ?
|
||||
FIELDFLAG_ZEROFILL : 0) |
|
||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||
break;
|
||||
case FIELD_TYPE_TIMESTAMP:
|
||||
/* We should replace old TIMESTAMP fields with their newer analogs */
|
||||
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
|
||||
{
|
||||
if (!timestamps)
|
||||
{
|
||||
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
||||
timestamps_with_niladic++;
|
||||
}
|
||||
else
|
||||
sql_field->unireg_check= Field::NONE;
|
||||
}
|
||||
else if (sql_field->unireg_check != Field::NONE)
|
||||
timestamps_with_niladic++;
|
||||
|
||||
timestamps++;
|
||||
/* fall-through */
|
||||
default:
|
||||
sql_field->pack_flag=(FIELDFLAG_NUMBER |
|
||||
(sql_field->flags & UNSIGNED_FLAG ? 0 :
|
||||
FIELDFLAG_DECIMAL) |
|
||||
(sql_field->flags & ZEROFILL_FLAG ?
|
||||
FIELDFLAG_ZEROFILL : 0) |
|
||||
f_settype((uint) sql_field->sql_type) |
|
||||
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
|
||||
break;
|
||||
}
|
||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
|
||||
if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
|
||||
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
|
||||
if (sql_field->sql_type == FIELD_TYPE_BLOB ||
|
||||
sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB ||
|
||||
sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
|
||||
sql_field->sql_type == FIELD_TYPE_LONG_BLOB ||
|
||||
sql_field->sql_type == FIELD_TYPE_GEOMETRY ||
|
||||
sql_field->sql_type == MYSQL_TYPE_VARCHAR)
|
||||
create_info->varchar= 1;
|
||||
sql_field->offset= pos;
|
||||
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
|
||||
auto_increment++;
|
||||
@ -1585,6 +1627,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
((Item_field *)item)->field :
|
||||
(Field*) 0))))
|
||||
DBUG_RETURN(0);
|
||||
if (item->maybe_null)
|
||||
cr_field->flags &= ~NOT_NULL_FLAG;
|
||||
extra_fields->push_back(cr_field);
|
||||
}
|
||||
/*
|
||||
|
Reference in New Issue
Block a user