mariadb/sql/sql_i_s.h
Alexander Barkov fd247cc21f MDEV-31340 Remove MY_COLLATION_HANDLER::strcasecmp()
This patch also fixes:
  MDEV-33050 Build-in schemas like oracle_schema are accent insensitive
  MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0
  MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0
  MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0
  MDEV-33088 Cannot create triggers in the database `MYSQL`
  MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0
  MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0
  MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0
  MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS
  MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0

- Removing the virtual function strnncoll() from MY_COLLATION_HANDLER

- Adding a wrapper function CHARSET_INFO::streq(), to compare
  two strings for equality. For now it calls strnncoll() internally.
  In the future it will turn into a virtual function.

- Adding new accent sensitive case insensitive collations:
    - utf8mb4_general1400_as_ci
    - utf8mb3_general1400_as_ci
  They implement accent sensitive case insensitive comparison.
  The weight of a character is equal to the code point of its
  upper case variant. These collations use Unicode-14.0.0 casefolding data.

  The result of
     my_charset_utf8mb3_general1400_as_ci.strcoll()
  is very close to the former
     my_charset_utf8mb3_general_ci.strcasecmp()

  There is only a difference in a couple dozen rare characters, because:
    - the switch from "tolower" to "toupper" comparison, to make
      utf8mb3_general1400_as_ci closer to utf8mb3_general_ci
    - the switch from Unicode-3.0.0 to Unicode-14.0.0
  This difference should be tolarable. See the list of affected
  characters in the MDEV description.

  Note, utf8mb4_general1400_as_ci correctly handles non-BMP characters!
  Unlike utf8mb4_general_ci, it does not treat all BMP characters
  as equal.

- Adding classes representing names of the file based database objects:

    Lex_ident_db
    Lex_ident_table
    Lex_ident_trigger

  Their comparison collation depends on the underlying
  file system case sensitivity and on --lower-case-table-names
  and can be either my_charset_bin or my_charset_utf8mb3_general1400_as_ci.

- Adding classes representing names of other database objects,
  whose names have case insensitive comparison style,
  using my_charset_utf8mb3_general1400_as_ci:

  Lex_ident_column
  Lex_ident_sys_var
  Lex_ident_user_var
  Lex_ident_sp_var
  Lex_ident_ps
  Lex_ident_i_s_table
  Lex_ident_window
  Lex_ident_func
  Lex_ident_partition
  Lex_ident_with_element
  Lex_ident_rpl_filter
  Lex_ident_master_info
  Lex_ident_host
  Lex_ident_locale
  Lex_ident_plugin
  Lex_ident_engine
  Lex_ident_server
  Lex_ident_savepoint
  Lex_ident_charset
  engine_option_value::Name

- All the mentioned Lex_ident_xxx classes implement a method streq():

  if (ident1.streq(ident2))
     do_equal();

  This method works as a wrapper for CHARSET_INFO::streq().

- Changing a lot of "LEX_CSTRING name" to "Lex_ident_xxx name"
  in class members and in function/method parameters.

- Replacing all calls like
    system_charset_info->coll->strcasecmp(ident1, ident2)
  to
    ident1.streq(ident2)

- Taking advantage of the c++11 user defined literal operator
  for LEX_CSTRING (see m_strings.h) and Lex_ident_xxx (see lex_ident.h)
  data types. Use example:

  const Lex_ident_column primary_key_name= "PRIMARY"_Lex_ident_column;

  is now a shorter version of:

  const Lex_ident_column primary_key_name=
    Lex_ident_column({STRING_WITH_LEN("PRIMARY")});
2024-04-18 15:22:10 +04:00

345 lines
8.3 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)
{
DBUG_ASSERT(length * 3 <= MAX_FIELD_VARCHARLENGTH);
}
};
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 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