mirror of
https://github.com/MariaDB/server.git
synced 2025-03-24 07:58:39 +01:00

Resize the types and widths of SHOW REPLICA STATUS (technically `INFORMATION_SCHEMA.SLAVE_STATUS`) columns to better match their possible values In case of intentionally but absurdly long lists, text columns that list an uncapped number of elements have expanded to accept as many bytes as we could support. Particularly, the first-gen `Replicate_` filters were incorrectly typed as singlular `Name()`s during MDEV-33526. Under `Name`s’ 64-char limit, they could overflow (read: truncate) even before their lengths got absurd. In response to `‘MAX_SLAVE_ERRMSG’ was not declared in this scope` in Embedded builds, a new `#ifdef HAVE_REPLICATION` guard wraps `slave_status_info` to skip this unused data in Replication-less builds. For testing, this commit forward-ports a modified cherry-pick of #3795 (the latter targets our oldest maintained LTS as part of MDEV-35948). > Assert that 1st-gen `replicate_*` filter variables display > their input – including long but reasonable lists – > correctly (without truncation) in > * direct SELECT > * [semi-new] INFORMATION_SCHEMA.GLOBAL_VARIABLES.VARIABLE_VALUE > * [new] SHOW REPLICA STATUS Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
354 lines
8.5 KiB
C++
354 lines
8.5 KiB
C++
#ifndef SQL_I_S_INCLUDED
|
|
#define SQL_I_S_INCLUDED
|
|
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
|
Copyright (c) 2009, 2019, MariaDB
|
|
|
|
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 */
|
|
|
|
#include "sql_const.h" // MAX_FIELD_VARCHARLENGTH
|
|
#include "sql_basic_types.h" // enum_nullability
|
|
#include "sql_string.h" // strlen, MY_CS_CHARACTER_SET_NAME_SIZE
|
|
#include "lex_string.h" // LEX_CSTRING
|
|
#include "mysql_com.h" // enum_field_types
|
|
#include "my_time.h" // TIME_SECOND_PART_DIGITS
|
|
#include "sql_type.h" // Type_handler_xxx
|
|
|
|
struct TABLE_LIST;
|
|
struct TABLE;
|
|
typedef class Item COND;
|
|
|
|
#ifdef MYSQL_CLIENT
|
|
#error MYSQL_CLIENT must not be defined
|
|
#endif // MYSQL_CLIENT
|
|
|
|
|
|
bool schema_table_store_record(THD *thd, TABLE *table);
|
|
COND *make_cond_for_info_schema(THD *thd, COND *cond, TABLE_LIST *table);
|
|
|
|
|
|
enum enum_show_open_table
|
|
{
|
|
SKIP_OPEN_TABLE= 0U, // do not open table
|
|
OPEN_FRM_ONLY= 1U, // open FRM file only
|
|
OPEN_FULL_TABLE= 2U // open FRM,MYD, MYI files
|
|
};
|
|
|
|
|
|
namespace Show {
|
|
class Type
|
|
{
|
|
/**
|
|
This denotes data type for the column. For the most part, there seems to
|
|
be one entry in the enum for each SQL data type, although there seem to
|
|
be a number of additional entries in the enum.
|
|
*/
|
|
const Type_handler *m_type_handler;
|
|
/**
|
|
For string-type columns, this is the maximum number of
|
|
characters. Otherwise, it is the 'display-length' for the column.
|
|
*/
|
|
uint m_char_length;
|
|
uint m_unsigned_flag;
|
|
const Typelib *m_typelib;
|
|
public:
|
|
Type(const Type_handler *th, uint length, uint unsigned_flag,
|
|
const Typelib *typelib= NULL)
|
|
:m_type_handler(th), m_char_length(length), m_unsigned_flag(unsigned_flag),
|
|
m_typelib(typelib)
|
|
{ }
|
|
const Type_handler *type_handler() const { return m_type_handler; }
|
|
uint char_length() const { return m_char_length; }
|
|
decimal_digits_t decimal_precision() const
|
|
{ return (decimal_digits_t) ((m_char_length / 100) % 100); }
|
|
decimal_digits_t decimal_scale() const
|
|
{ return (decimal_digits_t) (m_char_length % 10); }
|
|
uint fsp() const
|
|
{
|
|
DBUG_ASSERT(m_char_length <= TIME_SECOND_PART_DIGITS);
|
|
return m_char_length;
|
|
}
|
|
uint unsigned_flag() const { return m_unsigned_flag; }
|
|
const Typelib *typelib() const { return m_typelib; }
|
|
};
|
|
} // namespace Show
|
|
|
|
|
|
|
|
class ST_FIELD_INFO: public Show::Type
|
|
{
|
|
protected:
|
|
Lex_ident_column m_name; // I_S column name
|
|
enum_nullability m_nullability; // NULLABLE or NOT NULL
|
|
Lex_ident_column m_old_name; // SHOW column name
|
|
enum_show_open_table m_open_method;
|
|
public:
|
|
ST_FIELD_INFO(const Lex_ident_column &name, const Type &type,
|
|
enum_nullability nullability,
|
|
const Lex_ident_column &old_name,
|
|
enum_show_open_table open_method)
|
|
:Type(type), m_name(name),
|
|
m_nullability(nullability),
|
|
m_old_name(old_name),
|
|
m_open_method(open_method)
|
|
{ }
|
|
ST_FIELD_INFO(const char *name, const Type &type,
|
|
enum_nullability nullability,
|
|
const char *old_name,
|
|
enum_show_open_table open_method)
|
|
:Type(type), m_name(Lex_cstring_strlen(name)),
|
|
m_nullability(nullability),
|
|
m_old_name(Lex_cstring_strlen(old_name)),
|
|
m_open_method(open_method)
|
|
{ }
|
|
const Lex_ident_column &name() const { return m_name; }
|
|
bool nullable() const { return m_nullability == NULLABLE; }
|
|
const Lex_ident_column &old_name() const { return m_old_name; }
|
|
enum_show_open_table open_method() const { return m_open_method; }
|
|
bool end_marker() const { return m_name.str == NULL; }
|
|
};
|
|
|
|
|
|
namespace Show
|
|
{
|
|
|
|
|
|
class Enum: public Type
|
|
{
|
|
public:
|
|
Enum(const Typelib *typelib) :Type(&type_handler_enum, 0, false, typelib) { }
|
|
};
|
|
|
|
|
|
class Blob: public Type
|
|
{
|
|
public:
|
|
Blob(uint length) :Type(&type_handler_blob, length, false) { }
|
|
};
|
|
|
|
|
|
class Varchar: public Type
|
|
{
|
|
public:
|
|
Varchar(uint length) :Type(&type_handler_varchar, length, false)
|
|
{
|
|
// utf8mb3 Varchars longer than MAX_FIELD_VARCHARLENGTH/3 become Longtexts
|
|
DBUG_ASSERT(length * 3 <= MAX_FIELD_VARCHARLENGTH);
|
|
}
|
|
Varchar(): Type(&type_handler_varchar, MAX_FIELD_VARCHARLENGTH/3, false) {}
|
|
};
|
|
|
|
|
|
class Longtext: public Type
|
|
{
|
|
public:
|
|
Longtext(uint length) :Type(&type_handler_varchar, length, false) { }
|
|
};
|
|
|
|
|
|
class Yes_or_empty: public Varchar
|
|
{
|
|
public:
|
|
Yes_or_empty(): Varchar(3) { }
|
|
static LEX_CSTRING value(bool val)
|
|
{
|
|
return val ? Lex_cstring(STRING_WITH_LEN("Yes")) :
|
|
Lex_cstring();
|
|
}
|
|
};
|
|
|
|
|
|
class Catalog: public Varchar
|
|
{
|
|
public:
|
|
Catalog(): Varchar(FN_REFLEN) { }
|
|
};
|
|
|
|
|
|
class Name: public Varchar
|
|
{
|
|
public:
|
|
Name(): Varchar(NAME_CHAR_LEN) { }
|
|
};
|
|
|
|
|
|
class Definer: public Varchar
|
|
{
|
|
public:
|
|
Definer(): Varchar(DEFINER_CHAR_LENGTH) { }
|
|
};
|
|
|
|
|
|
class Userhost: public Varchar
|
|
{
|
|
public:
|
|
Userhost(): Varchar(USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 2) { }
|
|
};
|
|
|
|
|
|
class CSName: public Varchar
|
|
{
|
|
public:
|
|
CSName(): Varchar(MY_CS_CHARACTER_SET_NAME_SIZE) { }
|
|
};
|
|
|
|
|
|
class CLName: public Varchar
|
|
{
|
|
public:
|
|
CLName(): Varchar(MY_CS_COLLATION_NAME_SIZE) { }
|
|
};
|
|
|
|
|
|
class SQLMode: public Varchar
|
|
{
|
|
public:
|
|
SQLMode(): Varchar(32*256) { }
|
|
};
|
|
|
|
|
|
class Datetime: public Type
|
|
{
|
|
public:
|
|
Datetime(uint dec) :Type(&type_handler_datetime2, dec, false) { }
|
|
};
|
|
|
|
|
|
class Decimal: public Type
|
|
{
|
|
public:
|
|
Decimal(uint length) :Type(&type_handler_newdecimal, length, false) { }
|
|
};
|
|
|
|
|
|
class ULonglong: public Type
|
|
{
|
|
public:
|
|
ULonglong(uint length) :Type(&type_handler_ulonglong, length, true) { }
|
|
ULonglong() :ULonglong(MY_INT64_NUM_DECIMAL_DIGITS) { }
|
|
};
|
|
|
|
|
|
class ULong: public Type
|
|
{
|
|
public:
|
|
ULong(uint length) :Type(&type_handler_ulong, length, true) { }
|
|
ULong() :ULong(MY_INT32_NUM_DECIMAL_DIGITS) { }
|
|
};
|
|
|
|
|
|
class UShort: public Type
|
|
{
|
|
public:
|
|
UShort(uint length): Type(&type_handler_ushort, length, true) {}
|
|
};
|
|
|
|
|
|
class SLonglong: public Type
|
|
{
|
|
public:
|
|
SLonglong(uint length) :Type(&type_handler_slonglong, length, false) { }
|
|
SLonglong() :SLonglong(MY_INT64_NUM_DECIMAL_DIGITS) { }
|
|
};
|
|
|
|
|
|
class SLong: public Type
|
|
{
|
|
public:
|
|
SLong(uint length) :Type(&type_handler_slong, length, false) { }
|
|
SLong() :SLong(MY_INT32_NUM_DECIMAL_DIGITS) { }
|
|
};
|
|
|
|
|
|
class SShort: public Type
|
|
{
|
|
public:
|
|
SShort(uint length) :Type(&type_handler_sshort, length, false) { }
|
|
};
|
|
|
|
|
|
class STiny: public Type
|
|
{
|
|
public:
|
|
STiny(uint length) :Type(&type_handler_stiny, length, false) { }
|
|
};
|
|
|
|
|
|
class Double: public Type
|
|
{
|
|
public:
|
|
Double(uint length) :Type(&type_handler_double, length, false) { }
|
|
};
|
|
|
|
|
|
class Float: public Type
|
|
{
|
|
public:
|
|
Float(uint length) :Type(&type_handler_float, length, false) { }
|
|
};
|
|
|
|
|
|
|
|
class Column: public ST_FIELD_INFO
|
|
{
|
|
public:
|
|
Column(const char *name, const Type &type,
|
|
enum_nullability nullability,
|
|
const char *old_name,
|
|
enum_show_open_table open_method= SKIP_OPEN_TABLE)
|
|
:ST_FIELD_INFO(name, type, nullability,
|
|
old_name, open_method)
|
|
{ }
|
|
Column(const char *name, const Type &type,
|
|
enum_nullability nullability,
|
|
enum_show_open_table open_method= SKIP_OPEN_TABLE)
|
|
:ST_FIELD_INFO(name, type, nullability,
|
|
NullS, open_method)
|
|
{ }
|
|
};
|
|
|
|
|
|
// End marker
|
|
class CEnd: public Column
|
|
{
|
|
public:
|
|
CEnd() :Column(NullS, Varchar(0), NOT_NULL, NullS, SKIP_OPEN_TABLE) { }
|
|
};
|
|
|
|
|
|
} // namespace Show
|
|
|
|
|
|
struct TABLE_LIST;
|
|
typedef class Item COND;
|
|
|
|
typedef struct st_schema_table
|
|
{
|
|
Lex_ident_i_s_table table_name;
|
|
ST_FIELD_INFO *fields_info;
|
|
/* for FLUSH table_name */
|
|
int (*reset_table) ();
|
|
/* Fill table with data */
|
|
int (*fill_table) (THD *thd, TABLE_LIST *tables, COND *cond);
|
|
/* Handle fileds for old SHOW */
|
|
int (*old_format) (THD *thd, struct st_schema_table *schema_table);
|
|
int (*process_table) (THD *thd, TABLE_LIST *tables, TABLE *table,
|
|
bool res, const LEX_CSTRING *db_name,
|
|
const LEX_CSTRING *table_name);
|
|
int idx_field1, idx_field2;
|
|
bool hidden;
|
|
uint i_s_requested_object; /* the object we need to open(TABLE | VIEW) */
|
|
} ST_SCHEMA_TABLE;
|
|
|
|
|
|
#endif // SQL_I_S_INCLUDED
|