summaryrefslogtreecommitdiff
path: root/sql/item.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.h')
-rw-r--r--sql/item.h1431
1 files changed, 767 insertions, 664 deletions
diff --git a/sql/item.h b/sql/item.h
index cee88756bbf..945e388fd60 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -55,6 +55,23 @@ struct st_value
C_MODE_END
+
+template<size_t buffer_size>
+class ValueBuffer: public st_value
+{
+ char buffer[buffer_size];
+ void reset_buffer()
+ {
+ m_string.set(buffer, buffer_size, &my_charset_bin);
+ }
+public:
+ ValueBuffer()
+ {
+ reset_buffer();
+ }
+};
+
+
const char *dbug_print_item(Item *item);
class Protocol;
@@ -96,13 +113,6 @@ enum precedence {
typedef Bounds_checked_array<Item*> Ref_ptr_array;
-static inline uint32
-char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg)
-{
- ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg;
- return tmp > UINT_MAX32 ? UINT_MAX32 : static_cast<uint32>(tmp);
-}
-
bool mark_unsupported_function(const char *where, void *store, uint result);
/* convenience helper for mark_unsupported_function() above */
@@ -113,124 +123,12 @@ bool mark_unsupported_function(const char *w1, const char *w2,
#define SPLIT_SUM_SKIP_REGISTERED 1 /* Skip registered funcs */
#define SPLIT_SUM_SELECT 2 /* SELECT item; Split all parts */
-/*
- "Declared Type Collation"
- A combination of collation and its derivation.
-
- Flags for collation aggregation modes:
- MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
- MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
- (i.e. constant).
- MY_COLL_ALLOW_CONV - allow any kind of conversion
- (combination of the above two)
- MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to
- @@character_set_connection
- MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE
- (e.g. when aggregating for comparison)
- MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV
- and MY_COLL_DISALLOW_NONE
-*/
-
-#define MY_COLL_ALLOW_SUPERSET_CONV 1
-#define MY_COLL_ALLOW_COERCIBLE_CONV 2
-#define MY_COLL_DISALLOW_NONE 4
-#define MY_COLL_ALLOW_NUMERIC_CONV 8
-
-#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV)
-#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE)
#define NO_EXTRACTION_FL (1 << 6)
#define FULL_EXTRACTION_FL (1 << 7)
#define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL)
-class DTCollation {
-public:
- CHARSET_INFO *collation;
- enum Derivation derivation;
- uint repertoire;
-
- void set_repertoire_from_charset(CHARSET_INFO *cs)
- {
- repertoire= cs->state & MY_CS_PUREASCII ?
- MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
- }
- DTCollation()
- {
- collation= &my_charset_bin;
- derivation= DERIVATION_NONE;
- repertoire= MY_REPERTOIRE_UNICODE30;
- }
- DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- DTCollation(CHARSET_INFO *collation_arg,
- Derivation derivation_arg,
- uint repertoire_arg)
- :collation(collation_arg),
- derivation(derivation_arg),
- repertoire(repertoire_arg)
- { }
- void set(const DTCollation &dt)
- {
- collation= dt.collation;
- derivation= dt.derivation;
- repertoire= dt.repertoire;
- }
- void set(CHARSET_INFO *collation_arg, Derivation derivation_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- void set(CHARSET_INFO *collation_arg,
- Derivation derivation_arg,
- uint repertoire_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- repertoire= repertoire_arg;
- }
- void set_numeric()
- {
- collation= &my_charset_numeric;
- derivation= DERIVATION_NUMERIC;
- repertoire= MY_REPERTOIRE_NUMERIC;
- }
- void set(CHARSET_INFO *collation_arg)
- {
- collation= collation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- void set(Derivation derivation_arg)
- { derivation= derivation_arg; }
- bool aggregate(const DTCollation &dt, uint flags= 0);
- bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0)
- { set(dt1); return aggregate(dt2, flags); }
- const char *derivation_name() const
- {
- switch(derivation)
- {
- case DERIVATION_NUMERIC: return "NUMERIC";
- case DERIVATION_IGNORABLE: return "IGNORABLE";
- case DERIVATION_COERCIBLE: return "COERCIBLE";
- case DERIVATION_IMPLICIT: return "IMPLICIT";
- case DERIVATION_SYSCONST: return "SYSCONST";
- case DERIVATION_EXPLICIT: return "EXPLICIT";
- case DERIVATION_NONE: return "NONE";
- default: return "UNKNOWN";
- }
- }
- int sortcmp(const String *s, const String *t) const
- {
- return collation->coll->strnncollsp(collation,
- (uchar *) s->ptr(), s->length(),
- (uchar *) t->ptr(), t->length());
- }
-};
-
+extern const char *item_empty_name;
void dummy_error_processor(THD *thd, void *data);
@@ -496,7 +394,7 @@ class Rewritable_query_parameter
/*
Byte length of parameter name in the statement. This is not
- Item::name_length because name_length contains byte length of UTF8-encoded
+ Item::name.length because name.length contains byte length of UTF8-encoded
name, but the query string is in the client charset.
*/
uint len_in_query;
@@ -601,49 +499,8 @@ public:
};
-/**
- A class to store type attributes for the standard data types.
- Does not include attributes for the extended data types
- such as ENUM, SET, GEOMETRY.
-*/
-class Type_std_attributes
-{
-public:
- DTCollation collation;
- uint decimals;
- /*
- The maximum value length in characters multiplied by collation->mbmaxlen.
- Almost always it's the maximum value length in bytes.
- */
- uint32 max_length;
- bool unsigned_flag;
- Type_std_attributes()
- :collation(&my_charset_bin, DERIVATION_COERCIBLE),
- decimals(0), max_length(0), unsigned_flag(false)
- { }
- Type_std_attributes(const Type_std_attributes *other)
- :collation(other->collation),
- decimals(other->decimals),
- max_length(other->max_length),
- unsigned_flag(other->unsigned_flag)
- { }
- void set(const Type_std_attributes *other)
- {
- *this= *other;
- }
- void set(const Field *field)
- {
- decimals= field->decimals();
- max_length= field->field_length;
- collation.set(field->charset());
- unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG);
- }
-};
-
-
class Item: public Value_source,
- public Type_std_attributes,
- public Type_handler
+ public Type_all_attributes
{
void operator=(Item &);
/**
@@ -696,14 +553,76 @@ protected:
SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param);
- virtual Field *make_string_field(TABLE *table);
- Field *tmp_table_field_from_field_type(TABLE *table,
- bool fixed_length,
- bool set_blob_packlength);
- Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length);
+ /**
+ Create a field based on the exact data type handler.
+ */
+ Field *create_table_field_from_handler(TABLE *table)
+ {
+ const Type_handler *h= type_handler();
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ /**
+ Create a field based on field_type of argument.
+ This is used to create a field for
+ - IFNULL(x,something)
+ - time functions
+ - prepared statement placeholders
+ - SP variables with data type references: DECLARE a TYPE OF t1.a;
+ @retval NULL error
+ @retval !NULL on success
+ */
+ Field *tmp_table_field_from_field_type(TABLE *table)
+ {
+ const Type_handler *h= type_handler()->type_handler_for_tmp_table(this);
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd);
void push_note_converted_to_positive_complement(THD *thd);
+
+ /* Helper methods, to get an Item value from another Item */
+ double val_real_from_item(Item *item)
+ {
+ DBUG_ASSERT(fixed == 1);
+ double value= item->val_real();
+ null_value= item->null_value;
+ return value;
+ }
+ longlong val_int_from_item(Item *item)
+ {
+ DBUG_ASSERT(fixed == 1);
+ longlong value= item->val_int();
+ null_value= item->null_value;
+ return value;
+ }
+ String *val_str_from_item(Item *item, String *str)
+ {
+ DBUG_ASSERT(fixed == 1);
+ String *res= item->val_str(str);
+ if (res)
+ res->set_charset(collation.collation);
+ if ((null_value= item->null_value))
+ res= NULL;
+ return res;
+ }
+ my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value)
+ {
+ DBUG_ASSERT(fixed == 1);
+ my_decimal *value= item->val_decimal(decimal_value);
+ if ((null_value= item->null_value))
+ value= NULL;
+ return value;
+ }
+ bool get_date_with_conversion_from_item(Item *item,
+ MYSQL_TIME *ltime, uint fuzzydate)
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
+ }
+
public:
/*
Cache val_str() into the own buffer, e.g. to evaluate constant
@@ -711,9 +630,9 @@ public:
*/
String *val_str() { return val_str(&str_value); }
- char * name; /* Name from select */
+ LEX_CSTRING name; /* Name of item */
/* Original item name (if it was renamed)*/
- char * orig_name;
+ const char *orig_name;
/**
Intrusive list pointer for free list. If not null, points to the next
Item on some Query_arena's free list. For instance, stored procedures
@@ -722,12 +641,6 @@ public:
@see Query_arena::free_list
*/
Item *next;
- /*
- TODO: convert name and name_length fields into LEX_STRING to keep them in
- sync (see bug #11829681/60295 etc). Then also remove some strlen(name)
- calls.
- */
- uint name_length; /* Length of name */
int marker;
bool maybe_null; /* If item may be null */
bool in_rollup; /* If used in GROUP BY list
@@ -759,15 +672,13 @@ public:
virtual ~Item()
{
#ifdef EXTRA_DEBUG
- name=0;
+ name.str= 0;
+ name.length= 0;
#endif
} /*lint -e1509 */
void set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs);
void set_name_no_truncate(THD *thd, const char *str, uint length,
CHARSET_INFO *cs);
- void set_name_for_rollback(THD *thd, const char *str, uint length,
- CHARSET_INFO *cs);
- void rename(char *new_name);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup();
virtual void make_field(THD *thd, Send_field *field);
@@ -791,54 +702,9 @@ public:
*/
virtual inline void quick_fix_field() { fixed= 1; }
- bool store(struct st_value *value, ulonglong fuzzydate)
+ bool save_in_value(struct st_value *value)
{
- switch (cmp_type()) {
- case INT_RESULT:
- {
- value->m_type= unsigned_flag ? DYN_COL_UINT : DYN_COL_INT;
- value->value.m_longlong= val_int();
- break;
- }
- case REAL_RESULT:
- {
- value->m_type= DYN_COL_DOUBLE;
- value->value.m_double= val_real();
- break;
- }
- case DECIMAL_RESULT:
- {
- value->m_type= DYN_COL_DECIMAL;
- my_decimal *dec= val_decimal(&value->m_decimal);
- if (dec != &value->m_decimal && !null_value)
- my_decimal2decimal(dec, &value->m_decimal);
- break;
- }
- case STRING_RESULT:
- {
- value->m_type= DYN_COL_STRING;
- String *str= val_str(&value->m_string);
- if (str != &value->m_string && !null_value)
- value->m_string.set(str->ptr(), str->length(), str->charset());
- break;
- }
- case TIME_RESULT:
- {
- value->m_type= DYN_COL_DATETIME;
- get_date(&value->value.m_time, fuzzydate);
- break;
- }
- case ROW_RESULT:
- DBUG_ASSERT(false);
- null_value= true;
- break;
- }
- if (null_value)
- {
- value->m_type= DYN_COL_NULL;
- return true;
- }
- return false;
+ return type_handler()->Item_save_in_value(this, value);
}
/* Function returns 1 on overflow and -1 on fatal errors */
@@ -853,42 +719,80 @@ public:
{ return NULL; }
virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
- virtual bool send(Protocol *protocol, String *str);
+ virtual bool send(Protocol *protocol, st_value *buffer)
+ {
+ return type_handler()->Item_send(this, protocol, buffer);
+ }
virtual bool eq(const Item *, bool binary_cmp) const;
- const Type_handler *type_handler() const
+ enum_field_types field_type() const
+ {
+ return type_handler()->field_type();
+ }
+ virtual const Type_handler *type_handler() const= 0;
+ const Type_handler *type_handler_for_comparison() const
{
- return get_handler_by_field_type(field_type());
+ return type_handler()->type_handler_for_comparison();
}
- Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
- const Item *item) const
+ virtual const Type_handler *real_type_handler() const
{
- return type_handler()->make_num_distinct_aggregator_field(mem_root, this);
+ return type_handler();
}
- Field *make_conversion_table_field(TABLE *table,
- uint metadata, const Field *target) const
+ virtual const Type_handler *cast_to_int_type_handler() const
{
- DBUG_ASSERT(0); // Should not be called in Item context
- return NULL;
+ return type_handler();
}
/* result_type() of an item specifies how the value should be returned */
- Item_result result_type() const { return type_handler()->result_type(); }
+ Item_result result_type() const
+ {
+ return type_handler()->result_type();
+ }
/* ... while cmp_type() specifies how it should be compared */
- Item_result cmp_type() const { return type_handler()->cmp_type(); }
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+ Item_result cmp_type() const
+ {
+ return type_handler()->cmp_type();
+ }
+ const Type_handler *string_type_handler() const
+ {
+ return Type_handler::string_type_handler(max_length);
+ }
+ /*
+ Calculate the maximum length of an expression.
+ This method is used in data type aggregation for UNION, e.g.:
+ SELECT 'b' UNION SELECT COALESCE(double_10_3_field) FROM t1;
+
+ The result is usually equal to max_length, except for some numeric types.
+ In case of the INT, FLOAT, DOUBLE data types Item::max_length and
+ Item::decimals are ignored, so the returned value depends only on the
+ data type itself. E.g. for an expression of the DOUBLE(10,3) data type,
+ the result is always 53 (length 10 and precision 3 do not matter).
+
+ max_length is ignored for these numeric data types because the length limit
+ means only "expected maximum length", it is not a hard limit, so it does
+ not impose any data truncation. E.g. a column of the type INT(4) can
+ normally store big values up to 2147483647 without truncation. When we're
+ aggregating such column for UNION it's important to create a long enough
+ result column, not to lose any data.
+
+ For detailed behaviour of various data types see implementations of
+ the corresponding Type_handler_xxx::max_display_length().
+
+ Note, Item_field::max_display_length() overrides this to get
+ max_display_length() from the underlying field.
+ */
+ virtual uint32 max_display_length() const
{
- type_handler()->make_sort_key(to, item, sort_field, param);
+ return type_handler()->max_display_length(this);
}
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const
+ TYPELIB *get_typelib() const { return NULL; }
+ void set_maybe_null(bool maybe_null_arg) { maybe_null= maybe_null_arg; }
+ void set_typelib(TYPELIB *typelib)
{
- type_handler()->sortlength(thd, item, attr);
+ // Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet.
+ DBUG_ASSERT(0);
}
- virtual Item_result cast_to_int_type() const { return cmp_type(); }
- enum_field_types string_field_type() const
+ Item_cache* get_cache(THD *thd) const
{
- return Type_handler::string_type_handler(max_length)->field_type();
+ return type_handler()->Item_get_cache(thd, this);
}
virtual enum Type type() const =0;
/*
@@ -972,20 +876,45 @@ public:
to negative complements.
Values of non-integer data types are adjusted to the SIGNED range.
*/
- virtual longlong val_int_signed_typecast();
+ virtual longlong val_int_signed_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_signed_typecast(this);
+ }
+ longlong val_int_signed_typecast_from_str();
/**
Get a value for CAST(x AS UNSIGNED).
Negative signed integer values are converted
to positive complements.
Values of non-integer data types are adjusted to the UNSIGNED range.
*/
- virtual longlong val_int_unsigned_typecast();
+ virtual longlong val_int_unsigned_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this);
+ }
+ longlong val_int_unsigned_typecast_from_decimal();
+ longlong val_int_unsigned_typecast_from_int();
+ longlong val_int_unsigned_typecast_from_str();
/*
This is just a shortcut to avoid the cast. You should still use
unsigned_flag to check the sign of the item.
*/
inline ulonglong val_uint() { return (ulonglong) val_int(); }
/*
+ Adjust the result of val_int() to an unsigned number:
+ - NULL value is converted to 0. The caller can check "null_value"
+ to distinguish between 0 and NULL when necessary.
+ - Negative numbers are converted to 0.
+ - Positive numbers bigger than upper_bound are converted to upper_bound.
+ - Other numbers are returned as is.
+ */
+ ulonglong val_uint_from_val_int(ulonglong upper_bound)
+ {
+ longlong nr= val_int();
+ return (null_value || (nr < 0 && !unsigned_flag)) ? 0 :
+ (ulonglong) nr > upper_bound ? upper_bound : (ulonglong) nr;
+ }
+
+ /*
Return string representation of this item object.
SYNOPSIS
@@ -1157,16 +1086,21 @@ public:
// Check NULL value for a TIME, DATE or DATETIME expression
bool is_null_from_temporal();
- int save_time_in_field(Field *field);
- int save_date_in_field(Field *field);
+ int save_time_in_field(Field *field, bool no_conversions);
+ int save_date_in_field(Field *field, bool no_conversions);
+ int save_str_in_field(Field *field, bool no_conversions);
+ int save_real_in_field(Field *field, bool no_conversions);
+ int save_int_in_field(Field *field, bool no_conversions);
+ int save_decimal_in_field(Field *field, bool no_conversions);
+
int save_str_value_in_field(Field *field, String *result);
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *create_field_for_create_select(TABLE *table);
virtual Field *create_field_for_schema(THD *thd, TABLE *table);
- virtual const char *full_name() const { return name ? name : "???"; }
+ virtual const char *full_name() const { return name.str ? name.str : "???"; }
const char *field_name_or_null()
- { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; }
+ { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; }
/*
*result* family of methods is analog of *val* family (see above) but
@@ -1217,7 +1151,10 @@ public:
inline uint float_length(uint decimals_par) const
{ return decimals < FLOATING_POINT_DECIMALS ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
/* Returns total number of decimal digits */
- virtual uint decimal_precision() const;
+ virtual uint decimal_precision() const
+ {
+ return type_handler()->Item_decimal_precision(this);
+ }
/* Returns the number of integer part digits only */
inline int decimal_int_part() const
{ return my_decimal_int_part(decimal_precision(), decimals); }
@@ -1228,10 +1165,7 @@ public:
*/
uint decimal_scale() const
{
- return decimals < NOT_FIXED_DEC ? decimals :
- is_temporal_type_with_time(field_type()) ?
- TIME_SECOND_PART_DIGITS :
- MY_MIN(max_length, DECIMAL_MAX_SCALE);
+ return type_handler()->Item_decimal_scale(this);
}
/*
Returns how many digits a divisor adds into a division result.
@@ -1252,15 +1186,25 @@ public:
*/
uint divisor_precision_increment() const
{
- return decimals < NOT_FIXED_DEC ? decimals :
- is_temporal_type_with_time(field_type()) ?
- TIME_SECOND_PART_DIGITS :
- decimals;
+ return type_handler()->Item_divisor_precision_increment(this);
}
/**
TIME or DATETIME precision of the item: 0..6
*/
- uint temporal_precision(enum_field_types type);
+ uint time_precision()
+ {
+ return const_item() ? type_handler()->Item_time_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ uint datetime_precision()
+ {
+ return const_item() ? type_handler()->Item_datetime_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ virtual longlong val_int_min() const
+ {
+ return LONGLONG_MIN;
+ }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -1410,28 +1354,6 @@ public:
return f_type == MYSQL_TYPE_TIME ? val_time_packed() :
val_datetime_packed();
}
- enum_field_types field_type_for_temporal_comparison(const Item *other) const
- {
- if (cmp_type() == TIME_RESULT)
- {
- if (other->cmp_type() == TIME_RESULT)
- return Field::field_type_merge(field_type(), other->field_type());
- else
- return field_type();
- }
- else
- {
- if (other->cmp_type() == TIME_RESULT)
- return other->field_type();
- DBUG_ASSERT(0); // Two non-temporal data types, we should not get to here
- return MYSQL_TYPE_DATETIME;
- }
- }
- // Get a temporal value to compare to another Item
- longlong val_temporal_packed(const Item *other)
- {
- return val_temporal_packed(field_type_for_temporal_comparison(other));
- }
bool get_seconds(ulonglong *sec, ulong *sec_part);
virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date(ltime,fuzzydate); }
@@ -1514,14 +1436,9 @@ public:
static CHARSET_INFO *default_charset();
- /*
- For backward compatibility, to make numeric
- data types return "binary" charset in client-side metadata.
- */
- virtual CHARSET_INFO *charset_for_protocol(void) const
+ CHARSET_INFO *charset_for_protocol(void) const
{
- return cmp_type() == STRING_RESULT ? collation.collation :
- &my_charset_bin;
+ return type_handler()->charset_for_protocol(this);
};
virtual bool walk(Item_processor processor, bool walk_subquery, void *arg)
@@ -1732,22 +1649,33 @@ public:
virtual Item **this_item_addr(THD *thd, Item **addr_arg) { return addr_arg; }
// Row emulation
- virtual uint cols() { return 1; }
+ virtual uint cols() const { return 1; }
virtual Item* element_index(uint i) { return this; }
+ virtual bool element_index_by_name(uint *idx, const LEX_CSTRING &name) const
+ {
+ return true; // Error
+ }
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
+ bool check_type_traditional_scalar(const char *opname) const;
+ bool check_type_scalar(const char *opname) const;
+ bool check_type_or_binary(const char *opname, const Type_handler *handler) const;
+ bool check_type_general_purpose_string(const char *opname) const;
+ bool check_type_can_return_int(const char *opname) const;
+ bool check_type_can_return_real(const char *opname) const;
// It is not row => null inside is impossible
virtual bool null_inside() { return 0; }
// used in row subselects to get value of elements
virtual void bring_value() {}
+ const Type_handler *type_handler_long_or_longlong() const
+ {
+ return Type_handler::type_handler_long_or_longlong(max_char_length());
+ }
+
virtual Field *create_tmp_field(bool group, TABLE *table)
{
- /*
- Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
- Field_long : make them Field_longlong.
- */
- return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2);
+ return tmp_table_field_from_field_type(table);
}
virtual Item_field *field_for_view_update() { return 0; }
@@ -1850,10 +1778,14 @@ public:
}
virtual Field::geometry_type get_geometry_type() const
{ return Field::GEOM_GEOMETRY; };
+ uint uint_geometry_type() const
+ { return get_geometry_type(); }
+ void set_geometry_type(uint type)
+ {
+ DBUG_ASSERT(0);
+ }
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
- uint32 max_char_length() const
- { return max_length / collation.collation->mbmaxlen; }
bool too_big_for_varchar() const
{ return max_char_length() > CONVERT_IF_BIGGER_TO_BLOB; }
void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs)
@@ -1950,6 +1882,56 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item)
}
+class Type_geometry_attributes
+{
+ uint m_geometry_type;
+ static const uint m_geometry_type_unknown= Field::GEOM_GEOMETRYCOLLECTION + 1;
+ void copy(const Type_handler *handler, const Type_all_attributes *gattr)
+ {
+ // Ignore implicit NULLs
+ m_geometry_type= handler == &type_handler_geometry ?
+ gattr->uint_geometry_type() :
+ m_geometry_type_unknown;
+ }
+public:
+ Type_geometry_attributes()
+ :m_geometry_type(m_geometry_type_unknown)
+ { }
+ Type_geometry_attributes(const Type_handler *handler,
+ const Type_all_attributes *gattr)
+ :m_geometry_type(m_geometry_type_unknown)
+ {
+ copy(handler, gattr);
+ }
+ void join(const Item *item)
+ {
+ // Ignore implicit NULLs
+ if (m_geometry_type == m_geometry_type_unknown)
+ copy(item->type_handler(), item);
+ else if (item->type_handler() == &type_handler_geometry)
+ {
+ m_geometry_type=
+ Field_geom::geometry_type_merge((Field_geom::geometry_type)
+ m_geometry_type,
+ (Field_geom::geometry_type)
+ item->uint_geometry_type());
+ }
+ }
+ Field::geometry_type get_geometry_type() const
+ {
+ return m_geometry_type == m_geometry_type_unknown ?
+ Field::GEOM_GEOMETRY :
+ (Field::geometry_type) m_geometry_type;
+ }
+ void set_geometry_type(uint type)
+ {
+ DBUG_ASSERT(type <= m_geometry_type_unknown);
+ m_geometry_type= type;
+ }
+};
+
+
+
/**
Compare two Items for List<Item>::add_unique()
*/
@@ -1957,6 +1939,120 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item)
bool cmp_items(Item *a, Item *b);
+/**
+ Array of items, e.g. function or aggerate function arguments.
+*/
+class Item_args
+{
+protected:
+ Item **args, *tmp_arg[2];
+ uint arg_count;
+ void set_arguments(THD *thd, List<Item> &list);
+ bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->walk(processor, walk_subquery, arg))
+ return true;
+ }
+ return false;
+ }
+ bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
+ void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
+ bool excl_dep_on_table(table_map tab_map)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_table(tab_map))
+ return false;
+ }
+ return true;
+ }
+ bool excl_dep_on_grouping_fields(st_select_lex *sel)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_grouping_fields(sel))
+ return false;
+ }
+ return true;
+ }
+public:
+ Item_args(void)
+ :args(NULL), arg_count(0)
+ { }
+ Item_args(Item *a)
+ :args(tmp_arg), arg_count(1)
+ {
+ args[0]= a;
+ }
+ Item_args(Item *a, Item *b)
+ :args(tmp_arg), arg_count(2)
+ {
+ args[0]= a; args[1]= b;
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
+ {
+ arg_count= 3;
+ args[0]= a; args[1]= b; args[2]= c;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
+ {
+ arg_count= 4;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
+ {
+ arg_count= 5;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
+ {
+ arg_count= 5;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
+ }
+ }
+ Item_args(THD *thd, List<Item> &list)
+ {
+ set_arguments(thd, list);
+ }
+ Item_args(THD *thd, const Item_args *other);
+ bool alloc_arguments(THD *thd, uint count);
+ void add_argument(Item *item)
+ {
+ args[arg_count++]= item;
+ }
+ inline Item **arguments() const { return args; }
+ inline uint argument_count() const { return arg_count; }
+ inline void remove_arguments() { arg_count=0; }
+};
+
+
+class Item_spvar_args: public Item_args
+{
+ TABLE *m_table;
+public:
+ Item_spvar_args():Item_args(), m_table(NULL) { }
+ ~Item_spvar_args();
+ bool row_create_items(THD *thd, List<Spvar_definition> *list);
+ Field *get_row_field(uint i) const
+ {
+ DBUG_ASSERT(m_table);
+ return m_table->field[i];
+ }
+};
+
+
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -2091,7 +2187,10 @@ public:
done again between subsequent executions of a prepared statement.
*/
if (orig_name)
- name= orig_name;
+ {
+ name.str= orig_name;
+ name.length= strlen(orig_name);
+ }
}
};
@@ -2112,8 +2211,9 @@ protected:
*/
THD *m_thd;
+ bool fix_fields_from_item(THD *thd, Item **, const Item *);
public:
- LEX_STRING m_name;
+ LEX_CSTRING m_name;
public:
#ifndef DBUG_OFF
@@ -2125,10 +2225,10 @@ public:
#endif
public:
- Item_sp_variable(THD *thd, char *sp_var_name_str, uint sp_var_name_length);
+ Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name);
public:
- bool fix_fields(THD *thd, Item **);
+ bool fix_fields(THD *thd, Item **)= 0;
double val_real();
longlong val_int();
@@ -2137,12 +2237,12 @@ public:
bool is_null();
public:
- inline void make_field(THD *thd, Send_field *field);
+ void make_field(THD *thd, Send_field *field);
inline bool const_item() const;
inline int save_in_field(Field *field, bool no_conversions);
- inline bool send(Protocol *protocol, String *str);
+ inline bool send(Protocol *protocol, st_value *buffer);
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(m_name.str, arg, VCOL_IMPOSSIBLE);
@@ -2153,17 +2253,6 @@ public:
Item_sp_variable inline implementation.
*****************************************************************************/
-inline void Item_sp_variable::make_field(THD *thd, Send_field *field)
-{
- Item *it= this_item();
-
- if (name)
- it->set_name(thd, name, (uint) strlen(name), system_charset_info);
- else
- it->set_name(thd, m_name.str, (uint) m_name.length, system_charset_info);
- it->make_field(thd, field);
-}
-
inline bool Item_sp_variable::const_item() const
{
return TRUE;
@@ -2174,9 +2263,9 @@ inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions)
return this_item()->save_in_field(field, no_conversions);
}
-inline bool Item_sp_variable::send(Protocol *protocol, String *str)
+inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer)
{
- return this_item()->send(protocol, str);
+ return this_item()->send(protocol, buffer);
}
@@ -2190,14 +2279,18 @@ class Item_splocal :public Item_sp_variable,
public Rewritable_query_parameter,
public Type_handler_hybrid_field_type
{
+protected:
uint m_var_idx;
Type m_type;
+
+ bool append_value_for_log(THD *thd, String *str);
public:
- Item_splocal(THD *thd, const LEX_STRING &sp_var_name, uint sp_var_idx,
+ Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx,
enum_field_types sp_var_type,
uint pos_in_q= 0, uint len_in_q= 0);
+ bool fix_fields(THD *, Item **);
Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **);
@@ -2205,17 +2298,17 @@ public:
virtual void print(String *str, enum_query_type query_type);
public:
- inline const LEX_STRING *my_name() const;
+ inline const LEX_CSTRING *my_name() const;
inline uint get_var_idx() const;
inline enum Type type() const;
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+ uint cols() const { return this_item()->cols(); }
+ Item* element_index(uint i) { return this_item()->element_index(i); }
+ Item** addr(uint i) { return this_item()->addr(i); }
+ bool check_cols(uint c);
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
@@ -2232,13 +2325,108 @@ public:
bool append_for_log(THD *thd, String *str);
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
+
+ /*
+ Override the inherited create_field_for_create_select(),
+ because we want to preserve the exact data type for:
+ DECLARE a1 INT;
+ DECLARE a2 TYPE OF t1.a2;
+ CREATE TABLE t1 AS SELECT a1, a2;
+ The inherited implementation would create a column
+ based on result_type(), which is less exact.
+ */
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
};
+
+class Item_splocal_row: public Item_splocal
+{
+public:
+ Item_splocal_row(THD *thd, const LEX_CSTRING *sp_var_name,
+ uint sp_var_idx, uint pos_in_q, uint len_in_q)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ pos_in_q, len_in_q)
+ {
+ set_handler(&type_handler_row);
+ }
+ enum Type type() const { return ROW_ITEM; }
+};
+
+
+/**
+ An Item_splocal variant whose data type becomes known only at
+ sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE".
+*/
+class Item_splocal_with_delayed_data_type: public Item_splocal
+{
+public:
+ Item_splocal_with_delayed_data_type(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ uint sp_var_idx,
+ uint pos_in_q, uint len_in_q)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ pos_in_q, len_in_q)
+ { }
+};
+
+
+/**
+ SP variables that are fields of a ROW.
+ DELCARE r ROW(a INT,b INT);
+ SELECT r.a; -- This is handled by Item_splocal_row_field
+*/
+class Item_splocal_row_field :public Item_splocal
+{
+protected:
+ LEX_CSTRING m_field_name;
+ uint m_field_idx;
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+public:
+ Item_splocal_row_field(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ const LEX_CSTRING *sp_field_name,
+ uint sp_var_idx, uint sp_field_idx,
+ enum_field_types sp_var_type,
+ uint pos_in_q= 0, uint len_in_q= 0)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type,
+ pos_in_q, len_in_q),
+ m_field_name(*sp_field_name),
+ m_field_idx(sp_field_idx)
+ { }
+ bool fix_fields(THD *thd, Item **);
+ Item *this_item();
+ const Item *this_item() const;
+ Item **this_item_addr(THD *thd, Item **);
+ bool append_for_log(THD *thd, String *str);
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_splocal_row_field_by_name :public Item_splocal_row_field
+{
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+public:
+ Item_splocal_row_field_by_name(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ const LEX_CSTRING *sp_field_name,
+ uint sp_var_idx,
+ enum_field_types sp_var_type,
+ uint pos_in_q= 0, uint len_in_q= 0)
+ :Item_splocal_row_field(thd, sp_var_name, sp_field_name,
+ sp_var_idx, 0 /* field index will be set later */,
+ sp_var_type, pos_in_q, len_in_q)
+ { }
+ bool fix_fields(THD *thd, Item **it);
+ void print(String *str, enum_query_type query_type);
+};
+
+
/*****************************************************************************
Item_splocal inline implementation.
*****************************************************************************/
-inline const LEX_STRING *Item_splocal::my_name() const
+inline const LEX_CSTRING *Item_splocal::my_name() const
{
return &m_name;
}
@@ -2263,13 +2451,13 @@ public:
Item_case_expr(THD *thd, uint case_expr_id);
public:
+ bool fix_fields(THD *thd, Item **);
Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **);
inline enum Type type() const;
- inline Item_result result_type() const;
- enum_field_types field_type() const { return this_item()->field_type(); }
+ const Type_handler *type_handler() const { return this_item()->type_handler(); }
public:
/*
@@ -2293,12 +2481,6 @@ inline enum Item::Type Item_case_expr::type() const
return this_item()->type();
}
-inline Item_result Item_case_expr::result_type() const
-{
- return this_item()->result_type();
-}
-
-
/*
NAME_CONST(given_name, const_value).
This 'function' has all properties of the supplied const_value (which is
@@ -2331,14 +2513,9 @@ public:
bool is_null();
virtual void print(String *str, enum_query_type query_type);
- enum_field_types field_type() const
- {
- return value_item->field_type();
- }
-
- Item_result result_type() const
+ const Type_handler *type_handler() const
{
- return value_item->result_type();
+ return value_item->type_handler();
}
bool const_item() const
@@ -2351,9 +2528,9 @@ public:
return value_item->save_in_field(field, no_conversions);
}
- bool send(Protocol *protocol, String *str)
+ bool send(Protocol *protocol, st_value *buffer)
{
- return value_item->send(protocol, str);
+ return value_item->send(protocol, buffer);
}
bool check_vcol_func_processor(void *arg)
{
@@ -2415,13 +2592,13 @@ protected:
*/
const char *orig_db_name;
const char *orig_table_name;
- const char *orig_field_name;
+ LEX_CSTRING orig_field_name;
public:
Name_resolution_context *context;
const char *db_name;
const char *table_name;
- const char *field_name;
+ LEX_CSTRING field_name;
bool alias_name_used; /* true if item was resolved against alias */
/*
Cached value of index for this field in table->field array, used by prep.
@@ -2451,9 +2628,9 @@ public:
bool can_be_depended;
Item_ident(THD *thd, Name_resolution_context *context_arg,
const char *db_name_arg, const char *table_name_arg,
- const char *field_name_arg);
+ const LEX_CSTRING *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
- Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_arg);
+ Item_ident(THD *thd, TABLE_LIST *view_arg, const LEX_CSTRING *field_name_arg);
const char *full_name() const;
void cleanup();
st_select_lex *get_depended_from() const;
@@ -2482,17 +2659,20 @@ public:
Item_ident_for_show(THD *thd, Field *par_field, const char *db_arg,
const char *table_name_arg):
Item(thd), field(par_field), db_name(db_arg), table_name(table_name_arg)
- {}
-
+ {
+ Type_std_attributes::set(par_field);
+ }
enum Type type() const { return FIELD_ITEM; }
double val_real() { return field->val_real(); }
longlong val_int() { return field->val_int(); }
String *val_str(String *str) { return field->val_str(str); }
my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); }
void make_field(THD *thd, Send_field *tmp_field);
- CHARSET_INFO *charset_for_protocol(void) const
- { return field->charset_for_protocol(); }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const
+ {
+ const Type_handler *handler= field->type_handler();
+ return handler->type_handler_for_item_field();
+ }
Item* get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_ident_for_show>(thd, mem_root, this); }
};
@@ -2514,7 +2694,7 @@ public:
bool any_privileges;
Item_field(THD *thd, Name_resolution_context *context_arg,
const char *db_arg,const char *table_name_arg,
- const char *field_name_arg);
+ const LEX_CSTRING *field_name_arg);
/*
Constructor needed to process subselect with temporary tables (see Item)
*/
@@ -2544,7 +2724,7 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
- bool send(Protocol *protocol, String *str_arg);
+ bool send(Protocol *protocol, st_value *buffer);
void reset_field(Field *f);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
@@ -2554,18 +2734,22 @@ public:
fast_field_copier setup_fast_field_copier(Field *field);
table_map used_tables() const;
table_map all_used_tables() const;
- enum Item_result result_type () const
+ const Type_handler *type_handler() const
{
- return field->result_type();
+ const Type_handler *handler= field->type_handler();
+ return handler->type_handler_for_item_field();
}
- Item_result cast_to_int_type() const
+ const Type_handler *cast_to_int_type_handler() const
{
- return field->cmp_type();
+ return field->type_handler()->cast_to_int_type_handler();
}
- enum_field_types field_type() const
+ const Type_handler *real_type_handler() const
{
- return field->type();
+ if (field->is_created_from_null_item)
+ return &type_handler_null;
+ return field->type_handler();
}
+ TYPELIB *get_typelib() const { return field->get_typelib(); }
enum_monotonicity_info get_monotonicity_info() const
{
return MONOTONIC_STRICT_INCREASING;
@@ -2640,9 +2824,9 @@ public:
if (field && (field->unireg_check == Field::NEXT_NUMBER))
{
// Auto increment fields are unsupported
- return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
+ return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
}
- return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF);
+ return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF);
}
void cleanup();
Item_equal *get_item_equal() { return item_equal; }
@@ -2650,7 +2834,7 @@ public:
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
Item *replace_equal_field(THD *thd, uchar *arg);
- inline uint32 max_disp_length() { return field->max_display_length(); }
+ uint32 max_display_length() const { return field->max_display_length(); }
Item_field *field_for_view_update() { return this; }
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
@@ -2677,14 +2861,44 @@ public:
DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY);
return field->get_geometry_type();
}
- CHARSET_INFO *charset_for_protocol(void) const
- { return field->charset_for_protocol(); }
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
};
+/**
+ Item_field for the ROW data type
+*/
+class Item_field_row: public Item_field,
+ public Item_spvar_args
+{
+public:
+ Item_field_row(THD *thd, Field *field)
+ :Item_field(thd, field),
+ Item_spvar_args()
+ { }
+
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_field_row>(thd, mem_root, this); }
+
+ const Type_handler *type_handler() const { return &type_handler_row; }
+ uint cols() const { return arg_count; }
+ bool element_index_by_name(uint *idx, const LEX_CSTRING &name) const;
+ Item* element_index(uint i) { return arg_count ? args[i] : this; }
+ Item** addr(uint i) { return arg_count ? args + i : NULL; }
+ bool check_cols(uint c)
+ {
+ if (cols() != c)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), c);
+ return true;
+ }
+ return false;
+ }
+};
+
+
/*
@brief
Item_temptable_field is the same as Item_field, except that print()
@@ -2728,12 +2942,13 @@ public:
class Item_null :public Item_basic_constant
{
public:
- Item_null(THD *thd, char *name_par=0, CHARSET_INFO *cs= &my_charset_bin):
+ Item_null(THD *thd, const char *name_par=0, CHARSET_INFO *cs= &my_charset_bin):
Item_basic_constant(thd)
{
maybe_null= null_value= TRUE;
max_length= 0;
- name= name_par ? name_par : (char*) "NULL";
+ name.str= name_par ? name_par : "NULL";
+ name.length= strlen(name.str);
fixed= 1;
collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
@@ -2745,9 +2960,8 @@ public:
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
- bool send(Protocol *protocol, String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+ bool send(Protocol *protocol, st_value *buffer);
+ const Type_handler *type_handler() const { return &type_handler_null; }
bool basic_const_item() const { return 1; }
Item *clone_item(THD *thd);
bool is_null() { return 1; }
@@ -2795,7 +3009,8 @@ public:
class Item_param :public Item_basic_value,
private Settable_routine_parameter,
public Rewritable_query_parameter,
- public Type_handler_hybrid_field_type
+ public Type_handler_hybrid_field_type,
+ public Type_geometry_attributes
{
/*
NO_VALUE is a special value meaning that the parameter has not been
@@ -2922,14 +3137,17 @@ public:
MYSQL_TIME time;
} value;
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+
+ Field::geometry_type get_geometry_type() const
+ { return Type_geometry_attributes::get_geometry_type(); };
+
+ void set_geometry_type(uint type)
+ { Type_geometry_attributes::set_geometry_type(type); }
- Item_param(THD *thd, uint pos_in_query_arg);
+ Item_param(THD *thd, const LEX_CSTRING *name_arg,
+ uint pos_in_query_arg, uint len_in_query_arg);
enum Type type() const
{
@@ -3054,12 +3272,21 @@ public:
{ max_length=length; fixed= 1; unsigned_flag= 1; }
Item_int(THD *thd, const char *str_arg,longlong i,uint length):
Item_num(thd), value(i)
- { max_length=length; name=(char*) str_arg; fixed= 1; }
+ {
+ max_length=length;
+ name.str= str_arg; name.length= safe_strlen(name.str);
+ fixed= 1;
+ }
Item_int(THD *thd, const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
@@ -3139,8 +3366,7 @@ public:
Item_decimal(THD *thd, const uchar *bin, int precision, int scale);
enum Type type() const { return DECIMAL_ITEM; }
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
longlong val_int();
double val_real();
String *val_str(String*);
@@ -3160,16 +3386,17 @@ public:
class Item_float :public Item_num
{
- char *presentation;
+ const char *presentation;
public:
double value;
Item_float(THD *thd, const char *str_arg, uint length);
Item_float(THD *thd, const char *str, double val_arg, uint decimal_par,
uint length): Item_num(thd), value(val_arg)
{
- presentation= name=(char*) str;
+ presentation= name.str= str;
+ name.length= safe_strlen(str);
decimals=(uint8) decimal_par;
- max_length=length;
+ max_length= length;
fixed= 1;
}
Item_float(THD *thd, double value_par, uint decimal_par):
@@ -3180,7 +3407,7 @@ public:
}
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
@@ -3295,7 +3522,7 @@ public:
{
str_value.set_or_copy_aligned(str, length, cs);
fix_from_value(dv, Metadata(&str_value));
- set_name(thd, name_par, 0, system_charset_info);
+ set_name(thd, name_par, safe_strlen(name_par), system_charset_info);
}
Item_string(THD *thd, const char *name_par, const char *str, uint length,
CHARSET_INFO *cs, Derivation dv, uint repertoire):
@@ -3303,7 +3530,7 @@ public:
{
str_value.set_or_copy_aligned(str, length, cs);
fix_from_value(dv, Metadata(&str_value, repertoire));
- set_name(thd, name_par, 0, system_charset_info);
+ set_name(thd, name_par, safe_strlen(name_par), system_charset_info);
}
void print_value(String *to) const
{
@@ -3319,8 +3546,7 @@ public:
}
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const
{
@@ -3331,7 +3557,7 @@ public:
{
return const_charset_converter(thd, tocs, true);
}
- inline void append(char *str, uint length)
+ inline void append(const char *str, uint length)
{
str_value.append(str, length);
max_length= str_value.numchars() * collation.collation->mbmaxlen;
@@ -3366,7 +3592,7 @@ public:
String *check_well_formed_result(bool send_error)
{ return Item::check_well_formed_result(&str_value, send_error); }
- enum_field_types odbc_temporal_literal_type(const LEX_STRING *type_str) const
+ enum_field_types odbc_temporal_literal_type(const LEX_CSTRING *type_str) const
{
/*
If string is a reasonably short pure ASCII string literal,
@@ -3505,7 +3731,10 @@ public:
Item_partition_func_safe_string(thd, name_arg, length_arg, &my_charset_bin),
date_time_field_type(field_type_arg)
{ decimals= 0; }
- enum_field_types field_type() const { return date_time_field_type; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::get_handler_by_field_type(date_time_field_type);
+ }
};
@@ -3513,12 +3742,21 @@ class Item_blob :public Item_partition_func_safe_string
{
public:
Item_blob(THD *thd, const char *name_arg, uint length):
- Item_partition_func_safe_string(thd, name_arg, strlen(name_arg), &my_charset_bin)
+ Item_partition_func_safe_string(thd, name_arg, safe_strlen(name_arg), &my_charset_bin)
{ max_length= length; }
enum Type type() const { return TYPE_HOLDER; }
- enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::blob_type_handler(max_length);
+ }
+ const Type_handler *real_type_handler() const
+ {
+ // Should not be called, Item_blob is used for SHOW purposes only.
+ DBUG_ASSERT(0);
+ return &type_handler_varchar;
+ }
Field *create_field_for_schema(THD *thd, TABLE *table)
- { return tmp_table_field_from_field_type(table, false, true); }
+ { return tmp_table_field_from_field_type(table); }
};
@@ -3535,7 +3773,11 @@ public:
CHARSET_INFO *cs= NULL):
Item_partition_func_safe_string(thd, "", 0,
cs ? cs : &my_charset_utf8_general_ci)
- { name=(char*) header; max_length= length * collation.collation->mbmaxlen; }
+ {
+ name.str= header;
+ name.length= strlen(name.str);
+ max_length= length * collation.collation->mbmaxlen;
+ }
void make_field(THD *thd, Send_field *field);
};
@@ -3550,7 +3792,10 @@ public:
{
unsigned_flag=1;
}
- enum_field_types field_type() const { return int_field_type; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::get_handler_by_field_type(int_field_type);
+ }
};
@@ -3572,8 +3817,7 @@ public:
hex_string_init(thd, str, str_length);
}
enum Type type() const { return VARBIN_ITEM; }
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
{
return const_charset_converter(thd, tocs, true);
@@ -3583,7 +3827,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const
{
return item->basic_const_item() && item->type() == type() &&
- item->cast_to_int_type() == cast_to_int_type() &&
+ item->cast_to_int_type_handler() == cast_to_int_type_handler() &&
str_value.bin_eq(&((Item_hex_constant*)item)->str_value);
}
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
@@ -3601,6 +3845,7 @@ public:
Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {}
Item_hex_hybrid(THD *thd, const char *str, uint str_length):
Item_hex_constant(thd, str, str_length) {}
+ uint decimal_precision() const;
double val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -3625,7 +3870,10 @@ public:
field->set_notnull();
return field->store_hex_hybrid(str_value.ptr(), str_value.length());
}
- enum Item_result cast_to_int_type() const { return INT_RESULT; }
+ const Type_handler *cast_to_int_type_handler() const
+ {
+ return &type_handler_longlong;
+ }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_hex_hybrid>(thd, mem_root, this); }
@@ -3667,7 +3915,6 @@ public:
return field->store(str_value.ptr(), str_value.length(),
collation.collation);
}
- enum Item_result cast_to_int_type() const { return STRING_RESULT; }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_hex_string>(thd, mem_root, this); }
@@ -3707,8 +3954,6 @@ public:
bool const_item() const { return true; }
enum Type type() const { return DATE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- enum Item_result result_type () const { return STRING_RESULT; }
- Item_result cmp_type() const { return TIME_RESULT; }
bool check_partition_func_processor(void *int_arg) {return FALSE;}
@@ -3724,7 +3969,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
int save_in_field(Field *field, bool no_conversions)
- { return save_date_in_field(field); }
+ { return save_date_in_field(field, no_conversions); }
};
@@ -3748,7 +3993,7 @@ public:
*/
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3769,7 +4014,7 @@ public:
max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0);
fixed= 1;
}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3792,7 +4037,7 @@ public:
// See the comment on maybe_null in Item_date_literal
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3858,100 +4103,6 @@ public:
};
-/**
- Array of items, e.g. function or aggerate function arguments.
-*/
-class Item_args
-{
-protected:
- Item **args, *tmp_arg[2];
- uint arg_count;
- void set_arguments(THD *thd, List<Item> &list);
- bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->walk(processor, walk_subquery, arg))
- return true;
- }
- return false;
- }
- bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
- void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
- bool excl_dep_on_table(table_map tab_map)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->const_item())
- continue;
- if (!args[i]->excl_dep_on_table(tab_map))
- return false;
- }
- return true;
- }
- bool excl_dep_on_grouping_fields(st_select_lex *sel)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->const_item())
- continue;
- if (!args[i]->excl_dep_on_grouping_fields(sel))
- return false;
- }
- return true;
- }
-public:
- Item_args(void)
- :args(NULL), arg_count(0)
- { }
- Item_args(Item *a)
- :args(tmp_arg), arg_count(1)
- {
- args[0]= a;
- }
- Item_args(Item *a, Item *b)
- :args(tmp_arg), arg_count(2)
- {
- args[0]= a; args[1]= b;
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
- {
- arg_count= 3;
- args[0]= a; args[1]= b; args[2]= c;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
- {
- arg_count= 4;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
- {
- arg_count= 5;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
- {
- arg_count= 5;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
- }
- }
- Item_args(THD *thd, List<Item> &list)
- {
- set_arguments(thd, list);
- }
- Item_args(THD *thd, const Item_args *other);
- inline Item **arguments() const { return args; }
- inline uint argument_count() const { return arg_count; }
- inline void remove_arguments() { arg_count=0; }
-};
-
-
class Used_tables_and_const_cache
{
public:
@@ -4021,80 +4172,31 @@ class Item_func_or_sum: public Item_result_field,
public Item_args,
public Used_tables_and_const_cache
{
- bool agg_item_collations(DTCollation &c, const char *name,
- Item **items, uint nitems,
- uint flags, int item_sep);
- bool agg_item_set_converter(const DTCollation &coll, const char *fname,
- Item **args, uint nargs,
- uint flags, int item_sep);
protected:
- /*
- Collect arguments' character sets together.
- We allow to apply automatic character set conversion in some cases.
- The conditions when conversion is possible are:
- - arguments A and B have different charsets
- - A wins according to coercibility rules
- (i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column)
- - character set of A is either superset for character set of B,
- or B is a string constant which can be converted into the
- character set of A without data loss.
-
- If all of the above is true, then it's possible to convert
- B into the character set of A, and then compare according
- to the collation of A.
-
- For functions with more than two arguments:
-
- collect(A,B,C) ::= collect(collect(A,B),C)
-
- Since this function calls THD::change_item_tree() on the passed Item **
- pointers, it is necessary to pass the original Item **'s, not copies.
- Otherwise their values will not be properly restored (see BUG#20769).
- If the items are not consecutive (eg. args[2] and args[5]), use the
- item_sep argument, ie.
-
- agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
- */
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
uint flags, int item_sep)
{
- if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep))
- return true;
-
- return agg_item_set_converter(c, func_name(), items, nitems,
- flags, item_sep);
+ return Type_std_attributes::agg_arg_charsets(c, func_name(),
+ items, nitems,
+ flags, item_sep);
}
- /*
- Aggregate arguments for string result, e.g: CONCAT(a,b)
- - convert to @@character_set_connection if all arguments are numbers
- - allow DERIVATION_NONE
- */
bool agg_arg_charsets_for_string_result(DTCollation &c,
Item **items, uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_ALLOW_NUMERIC_CONV;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_string_result(c, func_name(),
+ items, nitems, item_sep);
}
- /*
- Aggregate arguments for string result, when some comparison
- is involved internally, e.g: REPLACE(a,b,c)
- - convert to @@character_set_connection if all arguments are numbers
- - disallow DERIVATION_NONE
- */
bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
Item **items,
uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_ALLOW_NUMERIC_CONV |
- MY_COLL_DISALLOW_NONE;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_string_result_with_comparison(c, func_name(),
+ items, nitems,
+ item_sep);
}
/*
@@ -4106,13 +4208,10 @@ protected:
Item **items, uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_DISALLOW_NONE;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep);
}
-
public:
// This method is used by Arg_comparator
bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b)
@@ -4195,7 +4294,7 @@ public:
bool reference_trough_name;
Item_ref(THD *thd, Name_resolution_context *context_arg,
const char *db_arg, const char *table_name_arg,
- const char *field_name_arg):
+ const LEX_CSTRING *field_name_arg):
Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg),
set_properties_only(0), ref(0), reference_trough_name(1) {}
/*
@@ -4213,10 +4312,10 @@ public:
with Bar, and if we have a more broader set of problems like this.
*/
Item_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
- const char *table_name_arg, const char *field_name_arg,
+ const char *table_name_arg, const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE);
Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg, bool alias_name_used_arg= FALSE);
+ const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE);
/* Constructor need to process subselect with temporary tables (see Item) */
Item_ref(THD *thd, Item_ref *item)
@@ -4244,7 +4343,7 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
- bool send(Protocol *prot, String *tmp);
+ bool send(Protocol *prot, st_value *buffer);
void make_field(THD *thd, Send_field *field);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
@@ -4252,8 +4351,9 @@ public:
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
fast_field_copier setup_fast_field_copier(Field *field)
{ return (*ref)->setup_fast_field_copier(field); }
- enum Item_result result_type () const { return (*ref)->result_type(); }
- enum_field_types field_type() const { return (*ref)->field_type(); }
+ const Type_handler *type_handler() const { return (*ref)->type_handler(); }
+ const Type_handler *real_type_handler() const
+ { return (*ref)->real_type_handler(); }
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
@@ -4291,6 +4391,11 @@ public:
{
return ref ? (*ref)->real_item() : this;
}
+ TYPELIB *get_typelib() const
+ {
+ return ref ? (*ref)->get_typelib() : NULL;
+ }
+
bool walk(Item_processor processor, bool walk_subquery, void *arg)
{
if (ref && *ref)
@@ -4319,7 +4424,7 @@ public:
virtual Ref_Type ref_type() { return REF; }
// Row emulation: forwarding of ROW-related calls to ref
- uint cols()
+ uint cols() const
{
return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1;
}
@@ -4405,7 +4510,7 @@ class Item_direct_ref :public Item_ref
public:
Item_direct_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE):
Item_ref(thd, context_arg, item, table_name_arg,
field_name_arg, alias_name_used_arg)
@@ -4413,7 +4518,7 @@ public:
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
Item_direct_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE):
Item_ref(thd, view_arg, item, field_name_arg,
alias_name_used_arg)
@@ -4451,7 +4556,7 @@ class Item_direct_ref_to_ident :public Item_direct_ref
public:
Item_direct_ref_to_ident(THD *thd, Item_ident *item):
Item_direct_ref(thd, item->context, (Item**)&item, item->table_name,
- item->field_name, FALSE)
+ &item->field_name, FALSE)
{
ident= item;
ref= (Item**)&ident;
@@ -4524,7 +4629,7 @@ public:
bool val_bool();
bool is_null();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
@@ -4552,8 +4657,7 @@ public:
orig_item->fix_after_pullout(new_parent, &orig_item);
}
int save_in_field(Field *to, bool no_conversions);
- enum Item_result result_type () const { return orig_item->result_type(); }
- enum_field_types field_type() const { return orig_item->field_type(); }
+ const Type_handler *type_handler() const { return orig_item->type_handler(); }
table_map used_tables() const { return orig_item->used_tables(); }
void update_used_tables()
{
@@ -4572,7 +4676,7 @@ public:
{ return orig_item->field_for_view_update(); }
/* Row emulation: forwarding of ROW-related calls to orig_item */
- uint cols()
+ uint cols() const
{ return result_type() == ROW_RESULT ? orig_item->cols() : 1; }
Item* element_index(uint i)
{ return result_type() == ROW_RESULT ? orig_item->element_index(i) : this; }
@@ -4638,7 +4742,7 @@ public:
Item_direct_view_ref(THD *thd, Name_resolution_context *context_arg,
Item **item,
const char *table_name_arg,
- const char *field_name_arg,
+ LEX_CSTRING *field_name_arg,
TABLE_LIST *view_arg):
Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg),
item_equal(0), view(view_arg),
@@ -4745,7 +4849,7 @@ public:
}
return Item_direct_ref::get_date(ltime, fuzzydate);
}
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
@@ -4799,7 +4903,7 @@ public:
Item_outer_ref(THD *thd, Name_resolution_context *context_arg,
Item_field *outer_field_arg):
Item_direct_ref(thd, context_arg, 0, outer_field_arg->table_name,
- outer_field_arg->field_name),
+ &outer_field_arg->field_name),
outer_ref(outer_field_arg), in_sum_func(0),
found_in_select_list(0), found_in_group_by(0)
{
@@ -4808,7 +4912,7 @@ public:
fixed= 0; /* reset flag set in set_properties() */
}
Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
- const char *table_name_arg, const char *field_name_arg,
+ const char *table_name_arg, LEX_CSTRING *field_name_arg,
bool alias_name_used_arg):
Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg,
alias_name_used_arg),
@@ -4849,7 +4953,8 @@ protected:
public:
Item_ref_null_helper(THD *thd, Name_resolution_context *context_arg,
Item_in_subselect* master, Item **item,
- const char *table_name_arg, const char *field_name_arg):
+ const char *table_name_arg,
+ const LEX_CSTRING *field_name_arg):
Item_ref(thd, context_arg, item, table_name_arg, field_name_arg),
owner(master) {}
void save_val(Field *to);
@@ -4952,8 +5057,8 @@ protected:
item= i;
null_value=maybe_null=item->maybe_null;
Type_std_attributes::set(item);
- name=item->name;
- set_handler_by_field_type(item->field_type());
+ name= item->name;
+ set_handler(item->type_handler());
fixed= item->fixed;
}
@@ -4979,12 +5084,8 @@ public:
/** All of the subclasses should have the same type tag */
enum Type type() const { return COPY_STR_ITEM; }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
void make_field(THD *thd, Send_field *field) { item->make_field(thd, field); }
table_map used_tables() const { return (table_map) 1L; }
@@ -5239,15 +5340,15 @@ public:
Item *arg;
Item_default_value(THD *thd, Name_resolution_context *context_arg)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(NULL) {}
Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(a) {}
Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(NULL) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -5258,7 +5359,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)
{
@@ -5310,7 +5411,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
};
@@ -5330,7 +5431,7 @@ public:
Item *arg;
Item_insert_value(THD *thd, Name_resolution_context *context_arg, Item *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(a) {}
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
@@ -5391,7 +5492,7 @@ public:
Item_trigger_field(THD *thd, Name_resolution_context *context_arg,
row_version_type row_ver_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
ulong priv, const bool ro)
:Item_field(thd, context_arg,
(const char *)NULL, (const char *)NULL, field_name_arg),
@@ -5477,7 +5578,7 @@ protected:
public:
Item_cache(THD *thd):
Item_basic_constant(thd),
- Type_handler_hybrid_field_type(MYSQL_TYPE_STRING),
+ Type_handler_hybrid_field_type(&type_handler_string),
example(0), cached_field(0),
value_cached(0)
{
@@ -5486,9 +5587,9 @@ public:
null_value= 1;
}
protected:
- Item_cache(THD *thd, enum_field_types field_type_arg):
+ Item_cache(THD *thd, const Type_handler *handler):
Item_basic_constant(thd),
- Type_handler_hybrid_field_type(field_type_arg),
+ Type_handler_hybrid_field_type(handler),
example(0), cached_field(0),
value_cached(0)
{
@@ -5509,15 +5610,9 @@ public:
};
enum Type type() const { return CACHE_ITEM; }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
-
- static Item_cache* get_cache(THD *thd, const Item *item);
- static Item_cache* get_cache(THD *thd, const Item* item, const Item_result type);
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+
virtual void keep_array() {}
virtual void print(String *str, enum_query_type query_type);
bool eq_def(const Field *field)
@@ -5608,16 +5703,15 @@ class Item_cache_int: public Item_cache
protected:
longlong value;
public:
- Item_cache_int(THD *thd): Item_cache(thd, MYSQL_TYPE_LONGLONG),
+ Item_cache_int(THD *thd): Item_cache(thd, &type_handler_longlong),
value(0) {}
- Item_cache_int(THD *thd, enum_field_types field_type_arg):
- Item_cache(thd, field_type_arg), value(0) {}
+ Item_cache_int(THD *thd, const Type_handler *handler):
+ Item_cache(thd, handler), value(0) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return INT_RESULT; }
bool cache_value();
int save_in_field(Field *field, bool no_conversions);
Item *convert_to_basic_const_item(THD *thd);
@@ -5629,7 +5723,7 @@ public:
class Item_cache_temporal: public Item_cache_int
{
public:
- Item_cache_temporal(THD *thd, enum_field_types field_type_arg);
+ Item_cache_temporal(THD *thd, const Type_handler *handler);
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
longlong val_int();
@@ -5639,7 +5733,6 @@ public:
bool cache_value();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int save_in_field(Field *field, bool no_conversions);
- Item_result cmp_type() const { return TIME_RESULT; }
void store_packed(longlong val_arg, Item *example);
/*
Having a clone_item method tells optimizer that this object
@@ -5657,14 +5750,13 @@ class Item_cache_real: public Item_cache
{
double value;
public:
- Item_cache_real(THD *thd): Item_cache(thd, MYSQL_TYPE_DOUBLE),
+ Item_cache_real(THD *thd): Item_cache(thd, &type_handler_double),
value(0) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return REAL_RESULT; }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -5677,13 +5769,12 @@ class Item_cache_decimal: public Item_cache
protected:
my_decimal decimal_value;
public:
- Item_cache_decimal(THD *thd): Item_cache(thd, MYSQL_TYPE_NEWDECIMAL) {}
+ Item_cache_decimal(THD *thd): Item_cache(thd, &type_handler_newdecimal) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return DECIMAL_RESULT; }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -5699,7 +5790,7 @@ class Item_cache_str: public Item_cache
public:
Item_cache_str(THD *thd, const Item *item):
- Item_cache(thd, item->field_type()), value(0),
+ Item_cache(thd, item->type_handler()), value(0),
is_varbinary(item->type() == FIELD_ITEM &&
Item_cache_str::field_type() == MYSQL_TYPE_VARCHAR &&
!((const Item_field *) item)->field->has_charset())
@@ -5710,7 +5801,6 @@ public:
longlong val_int();
String* val_str(String *);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); };
int save_in_field(Field *field, bool no_conversions);
bool cache_value();
@@ -5792,9 +5882,7 @@ public:
return 0;
};
- enum Item_result result_type() const { return ROW_RESULT; }
-
- uint cols() { return item_count; }
+ uint cols() const { return item_count; }
Item *element_index(uint i) { return values[i]; }
Item **addr(uint i) { return (Item **) (values + i); }
bool check_cols(uint c);
@@ -5826,50 +5914,65 @@ public:
single SP/PS execution.
*/
class Item_type_holder: public Item,
- public Type_handler_hybrid_real_field_type
+ public Type_handler_hybrid_field_type,
+ public Type_geometry_attributes
{
protected:
TYPELIB *enum_set_typelib;
- Field::geometry_type geometry_type;
-
- void get_full_info(Item *item);
-
- /* It is used to count decimal precision in join_types */
- int prev_decimal_int_part;
public:
- Item_type_holder(THD*, Item*);
+ Item_type_holder(THD *thd, Item *item)
+ :Item(thd, item),
+ Type_handler_hybrid_field_type(item->real_type_handler()),
+ enum_set_typelib(0)
+ {
+ DBUG_ASSERT(item->fixed);
+ maybe_null= item->maybe_null;
+ }
+ Item_type_holder(THD *thd,
+ const LEX_CSTRING *name_arg,
+ const Type_handler *handler,
+ const Type_all_attributes *attr,
+ bool maybe_null_arg)
+ :Item(thd),
+ Type_handler_hybrid_field_type(handler),
+ Type_geometry_attributes(handler, attr),
+ enum_set_typelib(attr->get_typelib())
+ {
+ name= *name_arg;
+ Type_std_attributes::set(*attr);
+ maybe_null= maybe_null_arg;
+ }
- enum_field_types field_type() const
- { return Type_handler_hybrid_real_field_type::field_type(); }
- enum_field_types real_field_type() const
- { return Type_handler_hybrid_real_field_type::real_field_type(); }
- enum Item_result result_type () const
+ const Type_handler *type_handler() const
{
- /*
- In 10.1 Item_type_holder::result_type() returned
- Field::result_merge_type(field_type()), which returned STRING_RESULT
- for the BIT data type. In 10.2 it returns INT_RESULT, similar
- to what Field_bit::result_type() does. This should not be
- important because Item_type_holder is a limited purpose Item
- and its result_type() should not be called from outside of
- Item_type_holder. It's called only internally from decimal_int_part()
- from join_types(), to calculate "decimals" of the result data type.
- As soon as we get BIT as one of the joined types, the result field
- type cannot be numeric: it's either BIT, or VARBINARY.
- */
- return Type_handler_hybrid_real_field_type::result_type();
+ const Type_handler *handler= Type_handler_hybrid_field_type::type_handler();
+ return handler->type_handler_for_item_field();
+ }
+ const Type_handler *real_type_handler() const
+ {
+ return Type_handler_hybrid_field_type::type_handler();
}
enum Type type() const { return TYPE_HOLDER; }
+ TYPELIB *get_typelib() const { return enum_set_typelib; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
- bool join_types(THD *thd, Item *);
- Field *make_field_by_type(TABLE *table);
- static uint32 display_length(Item *item);
- static enum_field_types get_real_type(Item *);
- Field::geometry_type get_geometry_type() const { return geometry_type; };
+ Field *create_tmp_field(bool group, TABLE *table)
+ {
+ return Item_type_holder::real_type_handler()->
+ make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ Field::geometry_type get_geometry_type() const
+ {
+ return Type_geometry_attributes::get_geometry_type();
+ }
+ void set_geometry_type(uint type)
+ {
+ Type_geometry_attributes::set_geometry_type(type);
+ }
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
};