MDEV-12668 SRID is not preserved in UNION, VIEW, MIN, MAX

Fixing the problem that an operation involving a mix of
two or more GEOMETRY operands did not preserve their SRIDs.
Now SRIDs are preserved by hybrid functions, subqueries, TVCs, UNIONs, VIEWs.

Incompatible change:
  An attempt to mix two different SRIDs now raises an error.

Details:

- Adding a new class Type_extra_attributes. It's a generic
  container which can store very specific data type attributes.
  For now it can store one uint32 and one const pointer attribute
  (for GEOMETRY's SRID and for ENUM/SET TYPELIB respectively).
  In the future it can grow as needed.

  Type_extra_attributes will also be reused soon to store "const Type_zone*"
  pointers for the TIMESTAMP's "WITH TIME ZONE 'tz'" attribute
  (a timestamp data type with a fixed time zone independent from @@time_zone).
  The time zone attribute will be stored in exactly the same way like
  a TYPELIB pointer is stored by ENUM/SET.

- Removing Column_definition_attributes members "interval" and "srid".
  Deriving Column_definition_attributes from the generic attribute container
  Type_extra_attributes instead.

- Adding a new class Type_typelib_attributes, to store
  the TYPELIB of the ENUM and SET data types. Deriving Field_enum from it.
  Removing the member Field_enum::typelib.

- Adding a new class Type_geom_attributes, to store
  the GEOMETRY related attributes. Deriving Field_geom from it.
  Removing the member Field_geom::srid.

- Removing virtual methods:
    Field::get_typelib()
    Type_all_attributes::get_typelib() and
    Type_all_attributes::set_typelib()
  They were very specific to TYPELIB.
  Adding more generic virtual methods instead:
  * Field::type_extra_attributes() - to get extra attributes
  * Type_all_attributes::type_extra_attributes() - to get extra attributes
  * Type_all_attributes::type_extra_attributes_addr() - to set extra attributes

- Removing Item_type_holder::enum_set_typelib. Deriving Item_type_holder
  from the generic attribute container Type_extra_attributes instead.
  This makes it possible for UNION to preserve SRID
  (in addition to preserving TYPELIB).

- Deriving Item_hybrid_func from Type_extra_attributes.
  This makes it possible for hybrid functions (e.g. CASE, COALESCE,
  LEAST, GREATEST etc) to preserve SRID.

- Deriving Item_singlerow_subselect from Type_extra_attributes and
  overriding methods:
  * Item_cache::type_extra_attributes()
  * subselect_single_select_engine::fix_length_and_dec()
  * Item_singlerow_subselect::type_extra_attributes()
  * Item_singlerow_subselect::type_extra_attributes_addr()
  This is needed to preserve SRID in subqueries and TVCs

- Cleanup: fixing the data type of members
  * Binlog_type_info::m_enum_typelib
  * Binlog_type_info::m_set_typelib
  from "TYPELIB *" to "const TYPELIB *"
This commit is contained in:
Alexander Barkov 2024-04-23 12:57:36 +04:00
parent 486d42d812
commit 001f93df2b
21 changed files with 502 additions and 153 deletions

View File

@ -5437,3 +5437,69 @@ DROP TABLE t1;
#
# End of 10.5 tests
#
#
# Start of 11.5 tests
#
#
# MDEV-12668 SRID is not preserved in UNION, VIEW, MIN, MAX
#
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=0, b POINT REF_SYSTEM_ID=102);
SELECT a FROM t1 UNION SELECT b FROM t1;
ERROR HY000: Illegal parameter data types `point ref_system_id=0` and `point ref_system_id=102` for operation 'UNION'
DROP TABLE t1;
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=102);
SELECT a FROM t1 UNION SELECT b FROM t1;
ERROR HY000: Illegal parameter data types `point ref_system_id=101` and `point ref_system_id=102` for operation 'UNION'
DROP TABLE t1;
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=101);
CREATE TABLE t2 AS SELECT a, b FROM t1;
CREATE VIEW v2 AS SELECT a, b FROM t1;
CREATE TABLE t3 AS SELECT a FROM t1 UNION SELECT b FROM t1;
CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1;
CREATE TABLE t4 AS SELECT COALESCE(a,b) AS a FROM t1;
CREATE VIEW v4 AS SELECT COALESCE(a,b) AS a FROM t1;
CREATE TABLE t5 AS SELECT LEAST(a,b) AS a FROM t1;
CREATE VIEW v5 AS SELECT LEAST(a,b) AS a FROM t1;
CREATE TABLE t6 AS SELECT MIN(a) AS a FROM t1;
CREATE VIEW v6 AS SELECT MIN(a) AS a FROM t1;
CREATE TABLE t7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2;
CREATE VIEW v7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2;
CREATE TABLE t8 AS SELECT (SELECT a FROM t1) AS a;
CREATE VIEW v8 AS SELECT (SELECT a FROM t1) AS a;
CREATE TABLE t9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1)));
CREATE VIEW v9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1)));
SELECT
G_TABLE_NAME, G_GEOMETRY_COLUMN, SRID
FROM
INFORMATION_SCHEMA.GEOMETRY_COLUMNS
WHERE
F_TABLE_SCHEMA='test'
ORDER
BY G_TABLE_NAME, G_GEOMETRY_COLUMN;
G_TABLE_NAME G_GEOMETRY_COLUMN SRID
t1 a 101
t1 b 101
t2 a 101
t2 b 101
t3 a 101
t4 a 101
t5 a 101
t6 a 101
t7 a 101
t8 a 101
t9 (SELECT MAX(a) FROM t1) 101
v2 a 101
v2 b 101
v3 a 101
v4 a 101
v5 a 101
v6 a 101
v7 a 101
v8 a 101
v9 (select max(`test`.`t1`.`a`) from `test`.`t1`) 101
DROP TABLE t2,t3,t4,t5,t6,t7,t8,t9;
DROP VIEW v2,v3,v4,v5,v6,v7,v8,v9;
DROP TABLE t1;
#
# End of 11.5 tests
#

View File

@ -3441,3 +3441,64 @@ DROP TABLE t1;
--echo #
--echo # End of 10.5 tests
--echo #
--echo #
--echo # Start of 11.5 tests
--echo #
--echo #
--echo # MDEV-12668 SRID is not preserved in UNION, VIEW, MIN, MAX
--echo #
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=0, b POINT REF_SYSTEM_ID=102);
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT a FROM t1 UNION SELECT b FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=102);
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT a FROM t1 UNION SELECT b FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a POINT REF_SYSTEM_ID=101, b POINT REF_SYSTEM_ID=101);
CREATE TABLE t2 AS SELECT a, b FROM t1;
CREATE VIEW v2 AS SELECT a, b FROM t1;
CREATE TABLE t3 AS SELECT a FROM t1 UNION SELECT b FROM t1;
CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1;
CREATE TABLE t4 AS SELECT COALESCE(a,b) AS a FROM t1;
CREATE VIEW v4 AS SELECT COALESCE(a,b) AS a FROM t1;
CREATE TABLE t5 AS SELECT LEAST(a,b) AS a FROM t1;
CREATE VIEW v5 AS SELECT LEAST(a,b) AS a FROM t1;
CREATE TABLE t6 AS SELECT MIN(a) AS a FROM t1;
CREATE VIEW v6 AS SELECT MIN(a) AS a FROM t1;
CREATE TABLE t7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2;
CREATE VIEW v7 AS SELECT MIN(a) AS a FROM t1 UNION SELECT b FROM v2;
CREATE TABLE t8 AS SELECT (SELECT a FROM t1) AS a;
CREATE VIEW v8 AS SELECT (SELECT a FROM t1) AS a;
CREATE TABLE t9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1)));
CREATE VIEW v9 AS VALUES ((SELECT MAX(a) FROM t1)),(((SELECT MIN(b) FROM t1)));
SELECT
G_TABLE_NAME, G_GEOMETRY_COLUMN, SRID
FROM
INFORMATION_SCHEMA.GEOMETRY_COLUMNS
WHERE
F_TABLE_SCHEMA='test'
ORDER
BY G_TABLE_NAME, G_GEOMETRY_COLUMN;
DROP TABLE t2,t3,t4,t5,t6,t7,t8,t9;
DROP VIEW v2,v3,v4,v5,v6,v7,v8,v9;
DROP TABLE t1;
--echo #
--echo # End of 11.5 tests
--echo #

View File

@ -9341,7 +9341,7 @@ int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs)
/* Remove end space */
length= (uint) field_charset()->lengthsp(from, length);
uint tmp=find_type2(typelib, from, length, field_charset());
uint tmp=find_type2(m_typelib, from, length, field_charset());
if (!tmp)
{
if (length < 6) // Can't be more than 99999 enums
@ -9349,7 +9349,7 @@ int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs)
/* This is for reading numbers with LOAD DATA INFILE */
char *end;
tmp=(uint) cs->strntoul(from,length,10,&end,&err);
if (err || end != from+length || tmp > typelib->count)
if (err || end != from + length || tmp > m_typelib->count)
{
tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1);
@ -9379,7 +9379,7 @@ int Field_enum::store(longlong nr, bool unsigned_val)
{
DBUG_ASSERT(marked_for_write_or_computed());
int error= 0;
if ((ulonglong) nr > typelib->count || nr == 0)
if ((ulonglong) nr > m_typelib->count || nr == 0)
{
set_warning(WARN_DATA_TRUNCATED, 1);
if (nr != 0 || get_thd()->count_cuted_fields > CHECK_FIELD_EXPRESSION)
@ -9425,7 +9425,7 @@ Binlog_type_info Field_enum::binlog_type_info() const
{
DBUG_ASSERT(Field_enum::type() == binlog_type());
return Binlog_type_info(Field_enum::type(), real_type() + (pack_length() << 8),
2, charset(), (TYPELIB *)get_typelib(), NULL);
2, charset(), m_typelib, NULL);
}
@ -9433,11 +9433,11 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
uint tmp=(uint) Field_enum::val_int();
if (!tmp || tmp > typelib->count)
if (!tmp || tmp > m_typelib->count)
val_ptr->set("", 0, field_charset());
else
val_ptr->set((const char*) typelib->type_names[tmp-1],
typelib->type_lengths[tmp-1],
val_ptr->set((const char*) m_typelib->type_names[tmp - 1],
m_typelib->type_lengths[tmp - 1],
field_charset());
return val_ptr;
}
@ -9470,8 +9470,8 @@ void Field_enum::sql_type(String &res) const
res.append(STRING_WITH_LEN("enum("));
bool flag=0;
uint *len= typelib->type_lengths;
for (const char **pos= typelib->type_names; *pos; pos++, len++)
uint *len= m_typelib->type_lengths;
for (const char **pos= m_typelib->type_names; *pos; pos++, len++)
{
uint dummy_errors;
if (flag)
@ -9491,7 +9491,7 @@ Field *Field_enum::make_new_field(MEM_ROOT *root, TABLE *new_table,
Field_enum *res= (Field_enum*) Field::make_new_field(root, new_table,
keep_type);
if (res)
res->typelib= copy_typelib(root, typelib);
res->m_typelib= copy_typelib(root, m_typelib);
return res;
}
@ -9524,7 +9524,7 @@ int Field_set::store(const char *from,size_t length,CHARSET_INFO *cs)
from= tmpstr.ptr();
length= tmpstr.length();
}
ulonglong tmp= find_set(typelib, from, length, field_charset(),
ulonglong tmp= find_set(m_typelib, from, length, field_charset(),
&not_used, &not_used2, &got_warning);
if (!tmp && length && length < 22)
{
@ -9552,10 +9552,10 @@ int Field_set::store(longlong nr, bool unsigned_val)
int error= 0;
ulonglong max_nr;
if (sizeof(ulonglong)*8 <= typelib->count)
if (sizeof(ulonglong) * 8 <= m_typelib->count)
max_nr= ULONGLONG_MAX;
else
max_nr= (1ULL << typelib->count) - 1;
max_nr= (1ULL << m_typelib->count) - 1;
if ((ulonglong) nr > max_nr)
{
@ -9577,13 +9577,13 @@ String *Field_set::val_str(String *val_buffer,
val_buffer->set_charset(field_charset());
val_buffer->length(0);
while (tmp && bitnr < (uint) typelib->count)
while (tmp && bitnr < (uint) m_typelib->count)
{
if (tmp & 1)
{
if (val_buffer->length())
val_buffer->append(&field_separator, 1, &my_charset_latin1);
String str(typelib->type_names[bitnr], typelib->type_lengths[bitnr],
String str(m_typelib->type_names[bitnr], m_typelib->type_lengths[bitnr],
field_charset());
val_buffer->append(str);
}
@ -9603,8 +9603,8 @@ void Field_set::sql_type(String &res) const
res.append(STRING_WITH_LEN("set("));
bool flag=0;
uint *len= typelib->type_lengths;
for (const char **pos= typelib->type_names; *pos; pos++, len++)
uint *len= m_typelib->type_lengths;
for (const char **pos= m_typelib->type_names; *pos; pos++, len++)
{
uint dummy_errors;
if (flag)
@ -9621,7 +9621,7 @@ Binlog_type_info Field_set::binlog_type_info() const
{
DBUG_ASSERT(Field_set::type() == binlog_type());
return Binlog_type_info(Field_set::type(), real_type()
+ (pack_length() << 8), 2, charset(), NULL, (TYPELIB *)get_typelib());
+ (pack_length() << 8), 2, charset(), NULL, m_typelib);
}
/**
@ -9668,13 +9668,13 @@ bool Field_enum::eq_def(const Field *field) const
if (!Field::eq_def(field))
return FALSE;
values= ((Field_enum*) field)->typelib;
values= ((Field_enum*) field)->m_typelib;
/* Definition must be strictly equal. */
if (typelib->count != values->count)
if (m_typelib->count != values->count)
return FALSE;
return compare_type_names(field_charset(), typelib, values);
return compare_type_names(field_charset(), m_typelib, values);
}
@ -9689,8 +9689,6 @@ bool Field_enum::eq_def(const Field *field) const
bool Field_enum::is_equal(const Column_definition &new_field) const
{
const TYPELIB *values= new_field.interval;
/*
The fields are compatible if they have the same flags,
type, charset and have the same underlying length.
@ -9705,11 +9703,11 @@ bool Field_enum::is_equal(const Column_definition &new_field) const
enumeration or set members to the end of the list of valid member
values only alters table metadata and not table data.
*/
if (typelib->count > values->count)
if (m_typelib->count > new_field.typelib()->count)
return false;
/* Check whether there are modification before the end. */
if (! compare_type_names(field_charset(), typelib, new_field.interval))
if (! compare_type_names(field_charset(), m_typelib, new_field.typelib()))
return false;
return true;
@ -10405,9 +10403,10 @@ bool Column_definition::create_interval_from_interval_list(MEM_ROOT *mem_root,
bool reuse_interval_list_values)
{
DBUG_ENTER("Column_definition::create_interval_from_interval_list");
DBUG_ASSERT(!interval);
DBUG_ASSERT(!typelib());
TYPELIB *tmpint;
if (!(interval= tmpint= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB))))
if (!set_typelib(tmpint= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB))).
typelib())
DBUG_RETURN(true); // EOM
List_iterator<String> it(interval_list);
@ -10476,7 +10475,8 @@ bool Column_definition::create_interval_from_interval_list(MEM_ROOT *mem_root,
interval_list.empty(); // Don't need interval_list anymore
DBUG_RETURN(false);
err:
interval= NULL; // Avoid having both non-empty interval_list and interval
// Avoid having both non-empty interval_list and the typelib attribute
set_typelib(NULL);
DBUG_RETURN(true);
}
@ -10504,7 +10504,7 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root,
as the parser requires at least one element, so for a ENUM or SET field it
should never happen that both internal_list.elements and interval are 0.
*/
DBUG_ASSERT((interval == NULL) == (interval_list.elements > 0));
DBUG_ASSERT((typelib() == NULL) == (interval_list.elements > 0));
/*
Create typelib from interval_list, and if necessary
@ -10527,8 +10527,8 @@ bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root,
as the original field can be freed before the end of the life
cycle of "this".
*/
DBUG_ASSERT(interval);
if (!(interval= copy_typelib(mem_root, interval)))
DBUG_ASSERT(typelib());
if (!set_typelib(copy_typelib(mem_root, typelib())).typelib())
DBUG_RETURN(true);
}
prepare_interval_field_calc_length();
@ -10886,7 +10886,7 @@ Field *Column_definition_attributes::make_field(TABLE_SHARE *share,
{
DBUG_ASSERT(length <= UINT_MAX32);
DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
handler->name().ptr(), (uint) length, interval,
handler->name().ptr(), (uint) length, typelib(),
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
@ -10915,9 +10915,7 @@ bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item)
Column_definition_attributes::Column_definition_attributes(const Field *field)
:length(field->character_octet_length() / field->charset()->mbmaxlen),
interval(NULL),
charset(field->charset()), // May be NULL ptr
srid(0),
pack_flag(0),
decimals(field->decimals()),
unireg_check(field->unireg_check)
@ -10926,10 +10924,9 @@ Column_definition_attributes::Column_definition_attributes(const Field *field)
Column_definition_attributes::
Column_definition_attributes(const Type_all_attributes &attr)
:length(attr.max_length),
interval(attr.get_typelib()),
:Type_extra_attributes(attr.type_extra_attributes()),
length(attr.max_length),
charset(attr.collation.collation),
srid(0),
pack_flag(attr.unsigned_flag ? 0 : FIELDFLAG_DECIMAL),
decimals(attr.decimals),
unireg_check(Field::NONE)
@ -10942,7 +10939,6 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
Field *orig_field)
:Column_definition_attributes(old_field)
{
srid= 0;
on_update= NULL;
field_name= old_field->field_name;
flags= old_field->flags;
@ -11034,6 +11030,7 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field,
const handler *file)
{
set_handler(dup_field->type_handler());
Type_extra_attributes::operator=(*dup_field);
default_value= dup_field->default_value;
DBUG_ASSERT(dup_field->charset); // Set by prepare_stage1()
charset= dup_field->charset;
@ -11042,7 +11039,6 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field,
decimals= dup_field->decimals;
unireg_check= dup_field->unireg_check;
flags= dup_field->flags;
interval= dup_field->interval;
vcol_info= dup_field->vcol_info;
invisible= dup_field->invisible;
check_constraint= dup_field->check_constraint;

View File

@ -662,8 +662,8 @@ public:
Retrieve the field metadata for fields.
*/
CHARSET_INFO *m_cs; // NULL if not relevant
TYPELIB *m_enum_typelib; // NULL if not relevant
TYPELIB *m_set_typelib; // NULL if not relevant
const TYPELIB *m_enum_typelib; // NULL if not relevant
const TYPELIB *m_set_typelib; // NULL if not relevant
binlog_sign_t m_signedness;
uint16 m_metadata;
uint8 m_metadata_size;
@ -708,7 +708,7 @@ public:
Binlog_type_info(uchar type_code, uint16 metadata,
uint8 metadata_size,
CHARSET_INFO *cs,
TYPELIB *t_enum, TYPELIB *t_set)
const TYPELIB *t_enum, const TYPELIB *t_set)
:m_cs(cs),
m_enum_typelib(t_enum),
m_set_typelib(t_set),
@ -1661,7 +1661,10 @@ public:
virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
virtual longlong val_datetime_packed(THD *thd);
virtual longlong val_time_packed(THD *thd);
virtual const TYPELIB *get_typelib() const { return NULL; }
virtual const Type_extra_attributes type_extra_attributes() const
{
return Type_extra_attributes();
}
virtual CHARSET_INFO *charset() const= 0;
/* returns TRUE if the new charset differs. */
virtual void change_charset(const DTCollation &new_cs) {}
@ -4778,7 +4781,9 @@ private:
};
class Field_enum :public Field_str {
class Field_enum :public Field_str,
public Type_typelib_attributes
{
static void do_field_enum(const Copy_field *copy_field);
longlong val_int(const uchar *) const;
Data_type_compatibility can_optimize_range_or_keypart_ref(
@ -4787,7 +4792,6 @@ class Field_enum :public Field_str {
protected:
uint packlength;
public:
const TYPELIB *typelib;
Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
@ -4796,7 +4800,8 @@ public:
const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, collation),
packlength(packlength_arg),typelib(typelib_arg)
Type_typelib_attributes(typelib_arg),
packlength(packlength_arg)
{
flags|=ENUM_FLAG;
}
@ -4869,8 +4874,10 @@ public:
/* enum and set are sorted as integers */
CHARSET_INFO *sort_charset() const override { return &my_charset_bin; }
decimal_digits_t decimals() const override { return 0; }
const TYPELIB *get_typelib() const override { return typelib; }
const Type_extra_attributes type_extra_attributes() const override
{
return Type_extra_attributes(m_typelib);
}
uchar *pack(uchar *to, const uchar *from, uint max_length) override;
const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end,
uint param_data) override;
@ -5198,7 +5205,7 @@ public:
extern const LEX_CSTRING null_clex_str;
class Column_definition_attributes
class Column_definition_attributes: public Type_extra_attributes
{
public:
/*
@ -5206,17 +5213,13 @@ public:
max number of characters.
*/
ulonglong length;
const TYPELIB *interval;
CHARSET_INFO *charset;
uint32 srid;
uint32 pack_flag;
decimal_digits_t decimals;
Field::utype unireg_check;
Column_definition_attributes()
:length(0),
interval(NULL),
charset(&my_charset_bin),
srid(0),
pack_flag(0),
decimals(0),
unireg_check(Field::NONE)
@ -5287,7 +5290,7 @@ class Column_definition: public Sql_alloc,
const char **pos;
uint *len;
*max_length= *tot_length= 0;
for (pos= interval->type_names, len= interval->type_lengths;
for (pos= typelib()->type_names, len= typelib()->type_lengths;
*pos ; pos++, len++)
{
size_t length= charset->numchars(*pos, *pos + *len);
@ -5412,7 +5415,7 @@ public:
if (real_field_type() == MYSQL_TYPE_SET)
{
calculate_interval_lengths(&dummy, &field_length);
length= field_length + (interval->count - 1);
length= field_length + (typelib()->count - 1);
}
else /* MYSQL_TYPE_ENUM */
{
@ -5516,15 +5519,14 @@ public:
void set_type(const Column_definition &other)
{
set_handler(other.type_handler());
Type_extra_attributes::operator=(other);
length= other.length;
char_length= other.char_length;
decimals= other.decimals;
flags= other.flags;
pack_length= other.pack_length;
unireg_check= other.unireg_check;
interval= other.interval;
charset= other.charset;
srid= other.srid;
pack_flag= other.pack_flag;
}

View File

@ -1328,7 +1328,14 @@ public:
{
return type_handler()->max_display_length(this);
}
const TYPELIB *get_typelib() const override { return NULL; }
const Type_extra_attributes type_extra_attributes() const override
{
return Type_extra_attributes();
}
Type_extra_attributes *type_extra_attributes_addr() override
{
return nullptr;
}
/* optimized setting of maybe_null without jumps. Minimizes code size */
inline void set_maybe_null(bool maybe_null_arg)
{
@ -1366,11 +1373,6 @@ public:
bool is_top_level_item() const
{ return (bool) (base_flags & item_base_t::AT_TOP_LEVEL); }
void set_typelib(const TYPELIB *typelib) override
{
// Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet.
DBUG_ASSERT(0);
}
Item_cache* get_cache(THD *thd) const
{
return type_handler()->Item_get_cache(thd, this);
@ -3696,7 +3698,10 @@ public:
Field *create_tmp_field_ex(MEM_ROOT *root,
TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param) override;
const TYPELIB *get_typelib() const override { return field->get_typelib(); }
const Type_extra_attributes type_extra_attributes() const override
{
return field->type_extra_attributes();
}
enum_monotonicity_info get_monotonicity_info() const override
{
return MONOTONIC_STRICT_INCREASING;
@ -5731,9 +5736,9 @@ public:
{
return ref ? (*ref)->real_item() : this;
}
const TYPELIB *get_typelib() const override
const Type_extra_attributes type_extra_attributes() const override
{
return ref ? (*ref)->get_typelib() : NULL;
return ref ? (*ref)->type_extra_attributes() : Type_extra_attributes();
}
bool walk(Item_processor processor, bool walk_subquery, void *arg) override
@ -7154,6 +7159,12 @@ public:
const Type_handler *type_handler() const override
{ return Type_handler_hybrid_field_type::type_handler(); }
const Type_extra_attributes type_extra_attributes() const override
{
DBUG_ASSERT(fixed());
return example ? example->type_extra_attributes() :
Type_extra_attributes();
}
Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param) override
{
@ -7677,15 +7688,17 @@ public:
Item_type_holder do not need cleanup() because its time of live limited by
single SP/PS execution.
*/
class Item_type_holder: public Item, public Type_handler_hybrid_field_type
class Item_type_holder: public Item,
public Type_handler_hybrid_field_type,
public Type_extra_attributes
{
protected:
const TYPELIB *enum_set_typelib;
public:
Item_type_holder(THD *thd, Item *item, const Type_handler *handler,
const Type_all_attributes *attr, bool maybe_null_arg)
:Item(thd), Type_handler_hybrid_field_type(handler),
enum_set_typelib(attr->get_typelib())
const Type_all_attributes *attr,
bool maybe_null_arg)
:Item(thd),
Type_handler_hybrid_field_type(handler),
Type_extra_attributes(attr->type_extra_attributes())
{
name= item->name;
Type_std_attributes::set(*attr);
@ -7705,7 +7718,14 @@ public:
}
Type type() const override { return TYPE_HOLDER; }
const TYPELIB *get_typelib() const override { return enum_set_typelib; }
Type_extra_attributes *type_extra_attributes_addr() override
{
return this;
}
const Type_extra_attributes type_extra_attributes() const override
{
return *this;
}
/*
When handling a query like this:
VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin);

View File

@ -3295,7 +3295,7 @@ bool Item_func_find_in_set::fix_length_and_dec(THD *thd)
{
// find is not NULL pointer so args[0] is not a null-value
DBUG_ASSERT(!args[0]->null_value);
enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
enum_value= find_type(((Field_enum*) field)->typelib(), find->ptr(),
find->length(), 0);
enum_bit=0;
if (enum_value)

View File

@ -497,7 +497,8 @@ public:
Functions whose returned field type is determined at fix_fields() time.
*/
class Item_hybrid_func: public Item_func,
public Type_handler_hybrid_field_type
public Type_handler_hybrid_field_type,
public Type_extra_attributes
{
protected:
bool fix_attributes(Item **item, uint nitems);
@ -512,6 +513,14 @@ public:
:Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
const Type_handler *type_handler() const override
{ return Type_handler_hybrid_field_type::type_handler(); }
Type_extra_attributes *type_extra_attributes_addr() override
{
return this;
}
const Type_extra_attributes type_extra_attributes() const override
{
return *this;
}
void fix_length_and_dec_long_or_longlong(uint char_length, bool unsigned_arg)
{
collation= DTCollation_numeric();

View File

@ -4037,6 +4037,8 @@ bool subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
if (set_row(select_lex->item_list, row))
return TRUE;
item->collation.set(row[0]->collation);
if (Type_extra_attributes *eattr= item->type_extra_attributes_addr())
eattr[0]= row[0]->type_extra_attributes();
if (cols() != 1)
maybe_null= 0;
return FALSE;

View File

@ -294,7 +294,8 @@ public:
/* single value subselect */
class Item_cache;
class Item_singlerow_subselect :public Item_subselect
class Item_singlerow_subselect :public Item_subselect,
public Type_extra_attributes
{
protected:
Item_cache *value, **row;
@ -319,6 +320,14 @@ public:
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override;
const Type_handler *type_handler() const override;
bool fix_length_and_dec() override;
Type_extra_attributes *type_extra_attributes_addr() override
{
return this;
}
const Type_extra_attributes type_extra_attributes() const override
{
return *this;
}
uint cols() const override;
Item* element_index(uint i) override

View File

@ -1172,7 +1172,10 @@ public:
{
return get_arg(0)->real_type_handler();
}
const TYPELIB *get_typelib() const override { return args[0]->get_typelib(); }
const Type_extra_attributes type_extra_attributes() const override
{
return args[0]->type_extra_attributes();
}
void update_field() override;
void min_max_update_str_field();
void min_max_update_real_field();

View File

@ -6248,7 +6248,7 @@ bool Table_map_log_event::init_column_name_field()
bool Table_map_log_event::init_set_str_value_field()
{
StringBuffer<1024> buf;
TYPELIB *typelib;
const TYPELIB *typelib;
/*
SET string values are stored in the same format:
@ -6278,7 +6278,7 @@ bool Table_map_log_event::init_set_str_value_field()
bool Table_map_log_event::init_enum_str_value_field()
{
StringBuffer<1024> buf;
TYPELIB *typelib;
const TYPELIB *typelib;
/* ENUM is same to SET columns, see comment in init_set_str_value_field */
for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)

View File

@ -863,7 +863,7 @@ class Grant_table_base
{
Field *field= m_table->field[end_priv_columns];
if (field->real_type() == MYSQL_TYPE_ENUM &&
static_cast<Field_enum*>(field)->typelib->count == 2)
static_cast<Field_enum*>(field)->typelib()->count == 2)
{
if (!start_priv_columns)
start_priv_columns= end_priv_columns;
@ -3052,7 +3052,7 @@ static privilege_t get_access(TABLE *form, uint fieldnr, uint *next_field)
for (pos=form->field+fieldnr, bit=1;
*pos && (*pos)->real_type() == MYSQL_TYPE_ENUM &&
((Field_enum*) (*pos))->typelib->count == 2 ;
((Field_enum*) (*pos))->typelib()->count == 2 ;
pos++, fieldnr++, bit<<=1)
{
if (get_YN_as_bool(*pos))

View File

@ -8197,20 +8197,22 @@ public:
class Type_holder: public Sql_alloc,
public Item_args,
public Type_handler_hybrid_field_type,
public Type_all_attributes
public Type_all_attributes,
public Type_extra_attributes
{
const TYPELIB *m_typelib;
bool m_maybe_null;
public:
Type_holder()
:m_typelib(NULL),
m_maybe_null(false)
:m_maybe_null(false)
{ }
void set_type_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
void set_type_maybe_null(bool maybe_null_arg) override
{
m_maybe_null= maybe_null_arg;
}
bool get_maybe_null() const { return m_maybe_null; }
decimal_digits_t decimal_precision() const
decimal_digits_t decimal_precision() const override
{
/*
Type_holder is not used directly to create fields, so
@ -8222,13 +8224,13 @@ public:
DBUG_ASSERT(0);
return 0;
}
void set_typelib(const TYPELIB *typelib)
Type_extra_attributes *type_extra_attributes_addr() override
{
m_typelib= typelib;
return this;
}
const TYPELIB *get_typelib() const
const Type_extra_attributes type_extra_attributes() const override
{
return m_typelib;
return *this;
}
bool aggregate_attributes(THD *thd)

View File

@ -2269,7 +2269,7 @@ bool Column_definition::prepare_stage2_typelib(const char *type_name,
pack_flag= pack_length_to_packflag(pack_length) | field_flags;
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
return check_duplicates_in_interval(type_name, field_name.str, interval,
return check_duplicates_in_interval(type_name, field_name.str, typelib(),
charset, dup_val_count);
}
@ -2537,13 +2537,13 @@ bool Column_definition::prepare_stage1_check_typelib_default()
{
char *not_used;
uint not_used2;
find_set(interval, def->ptr(), def->length(),
find_set(typelib(), def->ptr(), def->length(),
charset, &not_used, &not_used2, &not_found);
}
else /* MYSQL_TYPE_ENUM */
{
def->length(charset->lengthsp(def->ptr(), def->length()));
not_found= !find_type2(interval, def->ptr(), def->length(), charset);
not_found= !find_type2(typelib(), def->ptr(), def->length(), charset);
}
}
if (not_found)

View File

@ -2666,7 +2666,7 @@ Field *Type_handler_enum::make_conversion_table_field(MEM_ROOT *root,
Field_enum(NULL, target->field_length,
(uchar *) "", 1, Field::NONE, &empty_clex_str,
metadata & 0x00ff/*pack_length()*/,
((const Field_enum*) target)->typelib, target->charset());
((const Field_enum*) target)->typelib(), target->charset());
}
@ -2682,7 +2682,7 @@ Field *Type_handler_set::make_conversion_table_field(MEM_ROOT *root,
Field_set(NULL, target->field_length,
(uchar *) "", 1, Field::NONE, &empty_clex_str,
metadata & 0x00ff/*pack_length()*/,
((const Field_enum*) target)->typelib, target->charset());
((const Field_enum*) target)->typelib(), target->charset());
}
@ -2977,7 +2977,8 @@ void Type_handler_typelib::
const Field *field) const
{
DBUG_ASSERT(def->flags & (ENUM_FLAG | SET_FLAG));
def->interval= field->get_typelib();
const Field_enum *field_enum= static_cast<const Field_enum*>(field);
field_enum->Type_typelib_attributes::store(def);
}
@ -3336,7 +3337,7 @@ bool Type_handler_set::
if (def->prepare_stage2_typelib("SET", FIELDFLAG_BITFIELD, &dup_count))
return true;
/* Check that count of unique members is not more then 64 */
if (def->interval->count - dup_count > sizeof(longlong)*8)
if (def->typelib()->count - dup_count > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), def->field_name.str);
return true;
@ -3549,14 +3550,14 @@ Type_handler_string_result::calc_key_length(const Column_definition &def) const
uint Type_handler_enum::calc_key_length(const Column_definition &def) const
{
DBUG_ASSERT(def.interval);
return get_enum_pack_length(def.interval->count);
DBUG_ASSERT(def.typelib());
return get_enum_pack_length(def.typelib()->count);
}
uint Type_handler_set::calc_key_length(const Column_definition &def) const
{
DBUG_ASSERT(def.interval);
return get_set_pack_length(def.interval->count);
DBUG_ASSERT(def.typelib());
return get_set_pack_length(def.typelib()->count);
}
uint Type_handler_blob_common::calc_key_length(const Column_definition &def) const
@ -3931,13 +3932,14 @@ Field *Type_handler_enum::make_table_field(MEM_ROOT *root,
const Type_all_attributes &attr,
TABLE_SHARE *share) const
{
const TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
const Type_typelib_attributes typelib_attr(attr.type_extra_attributes());
DBUG_ASSERT(typelib_attr.typelib());
return new (root)
Field_enum(addr.ptr(), attr.max_length,
addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
get_enum_pack_length(typelib_attr.typelib()->count),
typelib_attr.typelib(),
attr.collation);
}
@ -3949,13 +3951,14 @@ Field *Type_handler_set::make_table_field(MEM_ROOT *root,
TABLE_SHARE *share) const
{
const TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
const Type_typelib_attributes typelib_attr(attr.type_extra_attributes());
DBUG_ASSERT(typelib_attr.typelib());
return new (root)
Field_set(addr.ptr(), attr.max_length,
addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
get_enum_pack_length(typelib_attr.typelib()->count),
typelib_attr.typelib(),
attr.collation);
}
@ -4694,8 +4697,8 @@ bool Type_handler_typelib::
const TYPELIB *typelib= NULL;
for (uint i= 0; i < nitems; i++)
{
const TYPELIB *typelib2;
if ((typelib2= items[i]->get_typelib()))
const Type_extra_attributes eattr2= items[i]->type_extra_attributes();
if (eattr2.typelib())
{
if (typelib)
{
@ -4707,11 +4710,13 @@ bool Type_handler_typelib::
handler->set_handler(&type_handler_varchar);
return func->aggregate_attributes_string(func_name, items, nitems);
}
typelib= typelib2;
typelib= eattr2.typelib();
}
}
DBUG_ASSERT(typelib); // There must be at least one typelib
func->set_typelib(typelib);
Type_extra_attributes *eattr_addr= func->type_extra_attributes_addr();
if (eattr_addr)
eattr_addr->set_typelib(typelib);
return func->aggregate_attributes_string(func_name, items, nitems);
}
@ -8536,7 +8541,7 @@ Field *Type_handler_enum::
return new (mem_root)
Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, attr->pack_flag_to_pack_length(),
attr->interval, attr->charset);
attr->typelib(), attr->charset);
}
@ -8550,7 +8555,7 @@ Field *Type_handler_set::
return new (mem_root)
Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, attr->pack_flag_to_pack_length(),
attr->interval, attr->charset);
attr->typelib(), attr->charset);
}

View File

@ -3402,6 +3402,98 @@ public:
};
/*
A container for very specific data type attributes.
For now it prodives space for:
- one const pointer attributes
- one unt32 attribute
*/
class Type_extra_attributes
{
const void *m_attr_const_void_ptr[1];
uint32 m_attr_uint32[1];
public:
Type_extra_attributes()
:m_attr_const_void_ptr{0},
m_attr_uint32{0}
{ }
Type_extra_attributes(const void *const_void_ptr)
:m_attr_const_void_ptr{const_void_ptr},
m_attr_uint32{0}
{ }
/*
Generic const pointer attributes.
The ENUM and SET data types store TYPELIB information here.
*/
Type_extra_attributes & set_attr_const_void_ptr(uint i, const void *value)
{
m_attr_const_void_ptr[i]= value;
return *this;
}
const void *get_attr_const_void_ptr(uint i) const
{
return m_attr_const_void_ptr[i];
}
/*
Generic uint32 attributes.
The GEOMETRY data type stores SRID here.
*/
Type_extra_attributes & set_attr_uint32(uint i, uint32 value)
{
m_attr_uint32[i]= value;
return *this;
}
uint32 get_attr_uint32(uint i) const
{
return m_attr_uint32[i];
}
/*
Helper methods for TYPELIB attributes.
They are mostly needed to simplify the code
in Column_definition_attributes and Column_definition methods.
Eventually we should move this code into Type_typelib_attributes
and remove these methods.
*/
Type_extra_attributes & set_typelib(const TYPELIB *typelib)
{
return set_attr_const_void_ptr(0, typelib);
}
const TYPELIB *typelib() const
{
return (const TYPELIB*) get_attr_const_void_ptr(0);
}
};
class Type_typelib_attributes
{
protected:
const TYPELIB *m_typelib;
public:
Type_typelib_attributes()
:m_typelib(nullptr)
{ }
Type_typelib_attributes(const TYPELIB *typelib)
:m_typelib(typelib)
{ }
Type_typelib_attributes(const Type_extra_attributes &eattr)
:m_typelib((const TYPELIB *) eattr.get_attr_const_void_ptr(0))
{ }
void store(Type_extra_attributes *to) const
{
to->set_attr_const_void_ptr(0, m_typelib);
}
const TYPELIB *typelib() const
{
return m_typelib;
}
void set_typelib(const TYPELIB *typelib)
{
m_typelib= typelib;
}
};
class Type_all_attributes: public Type_std_attributes
{
public:
@ -3411,8 +3503,8 @@ public:
virtual void set_type_maybe_null(bool maybe_null_arg)= 0;
// Returns total number of decimal digits
virtual decimal_digits_t decimal_precision() const= 0;
virtual const TYPELIB *get_typelib() const= 0;
virtual void set_typelib(const TYPELIB *typelib)= 0;
virtual Type_extra_attributes *type_extra_attributes_addr() = 0;
virtual const Type_extra_attributes type_extra_attributes() const= 0;
};

View File

@ -22,6 +22,24 @@
#include "sql_type_geom.h"
#include "item_geofunc.h"
class GeomTypeStr: public BinaryStringBuffer<64>
{
public:
GeomTypeStr(const Type_handler &th, const Type_geom_attributes &gattr)
{
append_char('`');
append(th.name().lex_cstring());
append_char(' ');
append(STRING_WITH_LEN("ref_system_id="));
append_ulonglong(gattr.get_srid());
append_char('`');
DBUG_ASSERT(str_length < Alloced_length);
Ptr[str_length]= '\0';
}
};
Named_type_handler<Type_handler_geometry> type_handler_geometry("geometry");
Named_type_handler<Type_handler_point> type_handler_point("point");
Named_type_handler<Type_handler_linestring> type_handler_linestring("linestring");
@ -256,7 +274,7 @@ Field *Type_handler_geometry::make_conversion_table_field(MEM_ROOT *root,
const Field_geom *fg= static_cast<const Field_geom*>(target);
return new (root)
Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 4, fg->type_handler_geom(), fg->srid);
table->s, 4, fg->type_handler_geom(), *fg);
}
@ -272,7 +290,8 @@ void Type_handler_geometry::
Column_definition *def,
const Field *field) const
{
def->srid= ((Field_geom*) field)->srid;
DBUG_ASSERT(dynamic_cast<const Field_geom*>(field));
static_cast<const Field_geom*>(field)->Type_geom_attributes::store(def);
}
@ -486,13 +505,14 @@ Field *Type_handler_geometry::make_table_field(MEM_ROOT *root,
{
return new (root)
Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, share, 4, this, 0);
Field::NONE, name, share, 4, this,
Type_geom_attributes(attr.type_extra_attributes()));
}
bool Type_handler_geometry::
Item_hybrid_func_fix_attributes(THD *thd,
const LEX_CSTRING &func_name,
const LEX_CSTRING &op_name,
Type_handler_hybrid_field_type *handler,
Type_all_attributes *func,
Item **items, uint nitems) const
@ -503,6 +523,24 @@ bool Type_handler_geometry::
func->decimals= 0;
func->max_length= (uint32) UINT_MAX32;
func->set_type_maybe_null(true);
Type_extra_attributes *func_eattr= func->type_extra_attributes_addr();
if (func_eattr && nitems > 0)
{
Type_geom_attributes gattr(items[0]->type_extra_attributes());
for (uint32 i= 1; i < nitems; i++)
{
const Type_geom_attributes gattr1(items[i]->type_extra_attributes());
if (gattr.join(gattr1))
{
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
GeomTypeStr(*items[i-1]->type_handler(), gattr).ptr(),
GeomTypeStr(*items[i]->type_handler(), gattr1).ptr(),
op_name.str);
return true;
}
}
gattr.store(func_eattr);
}
return false;
}
@ -660,7 +698,8 @@ Field *Type_handler_geometry::
return new (root)
Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->pack_flag_to_pack_length(), this, attr->srid);
attr->pack_flag_to_pack_length(), this,
Type_geom_attributes(*attr));
}
@ -708,7 +747,7 @@ Type_handler_geometry::
cbuf[5]= (uchar) def.decimals;
cbuf[6]= FIELDGEOM_SRID;
int4store(cbuf + 7, ((uint32) def.srid));
int4store(cbuf + 7, Type_geom_attributes(def).get_srid());
cbuf[11]= FIELDGEOM_END;
}
@ -775,11 +814,13 @@ bool Type_handler_geometry::
{
uint gis_opt_read, gis_length, gis_decimals;
Field_geom::storage_type st_type;
uint32 srid= 0;
attr->frm_unpack_basic(buffer);
gis_opt_read= gis_field_options_read(gis_options->str,
gis_options->length,
&st_type, &gis_length,
&gis_decimals, &attr->srid);
&gis_decimals, &srid);
Type_geom_attributes(srid).store(attr);
gis_options->str+= gis_opt_read;
gis_options->length-= gis_opt_read;
return false;

View File

@ -24,6 +24,40 @@
#include "mariadb.h"
#include "sql_type.h"
class Type_geom_attributes
{
protected:
uint32 m_srid;
public:
Type_geom_attributes()
:m_srid(0)
{ }
explicit Type_geom_attributes(const Type_extra_attributes &eattr)
:m_srid(eattr.get_attr_uint32(0))
{ }
explicit Type_geom_attributes(uint32 srid)
:m_srid(srid)
{ }
void store(Type_extra_attributes *to) const
{
to->set_attr_uint32(0, m_srid);
}
void set_srid(uint32 srid)
{
m_srid= srid;
}
uint32 get_srid() const
{
return m_srid;
}
bool join(const Type_geom_attributes &rhs)
{
return m_srid != rhs.m_srid;
}
};
#ifdef HAVE_SPATIAL
class Type_handler_geometry: public Type_handler_string_result
{
@ -326,11 +360,11 @@ Type_collection_geometry_handler_by_name(const LEX_CSTRING &name);
#include "field.h"
class Field_geom :public Field_blob
class Field_geom :public Field_blob,
public Type_geom_attributes
{
const Type_handler_geometry *m_type_handler;
public:
uint srid;
uint precision;
enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1};
enum storage_type storage;
@ -339,11 +373,12 @@ public:
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length,
const Type_handler_geometry *gth,
uint field_srid)
const Type_geom_attributes &geom_attr)
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, share, blob_pack_length, &my_charset_bin),
Type_geom_attributes(geom_attr),
m_type_handler(gth)
{ srid= field_srid; }
{ }
enum_conv_type rpl_conv_type_from(const Conv_source &source,
const Relay_log_info *rli,
const Conv_param &param) const override;
@ -363,6 +398,12 @@ public:
{
m_type_handler= th;
}
const Type_extra_attributes type_extra_attributes() const override
{
Type_extra_attributes eattr;
Type_geom_attributes::store(&eattr);
return eattr;
}
enum_field_types type() const override
{
return MYSQL_TYPE_GEOMETRY;
@ -428,7 +469,6 @@ public:
bool load_data_set_null(THD *thd) override;
bool load_data_set_no_data(THD *thd, bool fixed_format) override;
uint get_srid() const { return srid; }
void print_key_value(String *out, uint32 length) override
{
out->append(STRING_WITH_LEN("unprintable_geometry_value"));

View File

@ -6494,11 +6494,11 @@ real_type:
srid_option:
/* empty */
{ Lex->last_field->srid= 0; }
{ Lex->last_field->set_attr_uint32(0, 0); }
|
REF_SYSTEM_ID_SYM '=' NUM
{
Lex->last_field->srid=atoi($3.str);
Lex->last_field->set_attr_uint32(0, (uint32) atoi($3.str));
}
;

View File

@ -2734,7 +2734,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
/* Convert pre-10.2.2 timestamps to use Field::default_value */
name.str= fieldnames.type_names[i];
name.length= strlen(name.str);
attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL;
attr.set_typelib(interval_nr ? share->intervals + interval_nr - 1 : NULL);
Record_addr addr(record + recpos, null_pos, null_bit_pos);
*field_ptr= reg_field=
attr.make_field(share, &share->mem_root, &addr, handler, &name, flags);
@ -10573,7 +10573,7 @@ bool TR_table::check(bool error)
}
Field_enum *iso_level= static_cast<Field_enum *>(table->field[FLD_ISO_LEVEL]);
const st_typelib *typelib= iso_level->typelib;
const st_typelib *typelib= iso_level->typelib();
if (typelib->count != 4)
goto wrong_enum;

View File

@ -644,7 +644,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
{
if (field->save_interval)
{
field->interval= field->save_interval;
field->set_typelib(field->save_interval);
field->save_interval= 0;
}
}
@ -887,7 +887,7 @@ static bool pack_header(THD *thd, uchar *forminfo,
n_length+= field->field_name.length + 1;
field->interval_id=0;
field->save_interval= 0;
if (field->interval)
if (field->typelib())
{
uint old_int_count=int_count;
@ -902,9 +902,9 @@ static bool pack_header(THD *thd, uchar *forminfo,
filled with default values it is saved in save_interval
The HEX representation is created from this copy.
*/
uint count= field->interval->count;
field->save_interval= field->interval;
field->interval= tmpint= (TYPELIB*) thd->alloc(sizeof(TYPELIB));
uint count= field->typelib()->count;
field->save_interval= field->typelib();
field->set_typelib(tmpint= (TYPELIB*) thd->alloc(sizeof(TYPELIB)));
*tmpint= *field->save_interval;
tmpint->type_names=
(const char **) thd->alloc(sizeof(char*) *
@ -913,7 +913,7 @@ static bool pack_header(THD *thd, uchar *forminfo,
tmpint->type_names[count]= 0;
tmpint->type_lengths[count]= 0;
for (uint pos= 0; pos < field->interval->count; pos++)
for (uint pos= 0; pos < field->typelib()->count; pos++)
{
char *dst;
const char *src= field->save_interval->type_names[pos];
@ -929,8 +929,8 @@ static bool pack_header(THD *thd, uchar *forminfo,
field->interval_id=get_interval_id(&int_count,create_fields,field);
if (old_int_count != int_count)
{
int_length+= typelib_values_packed_length(field->interval);
int_parts+= field->interval->count + 1;
int_length+= typelib_values_packed_length(field->typelib());
int_parts+= field->typelib()->count + 1;
}
}
if (f_maybe_null(field->pack_flag))
@ -984,7 +984,7 @@ static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
{
List_iterator<Create_field> it(create_fields);
Create_field *field;
const TYPELIB *interval= last_field->interval;
const TYPELIB *interval= last_field->typelib();
while ((field=it++) != last_field)
{
@ -996,11 +996,11 @@ static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
- mbminlen>1 are written to FRM in hex-encoded format
*/
if (field->interval_id &&
field->interval->count == interval->count &&
field->typelib()->count == interval->count &&
field->charset->mbminlen == last_field->charset->mbminlen)
{
const char **a,**b;
for (a=field->interval->type_names, b=interval->type_names ;
for (a= field->typelib()->type_names, b= interval->type_names ;
*a && !strcmp(*a,*b);
a++,b++) ;
@ -1028,7 +1028,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
{
int_count= field->interval_id;
length++;
length+= typelib_values_packed_length(field->interval);
length+= typelib_values_packed_length(field->typelib());
length++;
}
@ -1096,8 +1096,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
bzero(occ, sizeof(occ));
for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
for (uint j = 0; j < field->interval->type_lengths[i]; j++)
for (i=0; (val= (unsigned char*) field->typelib()->type_names[i]); i++)
for (uint j = 0; j < field->typelib()->type_lengths[i]; j++)
occ[(unsigned int) (val[j])]= 1;
if (!occ[(unsigned char)NAMES_SEP_CHAR])
@ -1127,10 +1127,11 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
int_count= field->interval_id;
*buff++= sep;
for (int i=0; field->interval->type_names[i]; i++)
for (int i=0; field->typelib()->type_names[i]; i++)
{
memcpy(buff, field->interval->type_names[i], field->interval->type_lengths[i]);
buff+= field->interval->type_lengths[i];
memcpy(buff, field->typelib()->type_names[i],
field->typelib()->type_lengths[i]);
buff+= field->typelib()->type_lengths[i];
*buff++= sep;
}
*buff++= 0;
@ -1214,8 +1215,8 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
Record_addr addr(buff + field->offset + data_offset,
null_pos + null_count / 8, null_count & 7);
Column_definition_attributes tmp(*field);
tmp.interval= field->save_interval ?
field->save_interval : field->interval;
tmp.set_typelib(field->save_interval ?
field->save_interval : field->typelib());
/* regfield don't have to be deleted as it's allocated on THD::mem_root */
Field *regfield= tmp.make_field(&share, thd->mem_root, &addr,
field->type_handler(),