summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc71
1 files changed, 65 insertions, 6 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 132cfa2846a..bffa7e2990d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2010, 2014, Monty Program Ab.
+ Copyright (c) 2010, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1179,6 +1179,42 @@ Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
/**
+ Some pieces of the code do not support changing of
+ Item_cache to other Item types.
+
+ Example:
+ Item_singlerow_subselect has "Item_cache **row".
+ Creating of Item_func_conv_charset followed by THD::change_item_tree()
+ should not change row[i] from Item_cache directly to Item_func_conv_charset, because Item_singlerow_subselect
+ because Item_singlerow_subselect later calls Item_cache-specific methods,
+ e.g. row[i]->store() and row[i]->cache_value().
+
+ Let's wrap Item_func_conv_charset in a new Item_cache,
+ so the Item_cache-specific methods can still be used for
+ Item_singlerow_subselect::row[i] safely.
+
+ As a bonus we cache the converted value, instead of converting every time
+
+ TODO: we should eventually check all other use cases of change_item_tree().
+ Perhaps some more potentially dangerous substitution examples exist.
+*/
+Item *Item_cache::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ if (!example)
+ return Item::safe_charset_converter(tocs);
+ Item *conv= example->safe_charset_converter(tocs);
+ if (conv == example)
+ return this;
+ Item_cache *cache;
+ if (!conv || !(cache= new Item_cache_str(conv)))
+ return NULL; // Safe conversion is not possible, or OEM
+ cache->setup(conv);
+ cache->fixed= false; // Make Item::fix_fields() happy
+ return cache;
+}
+
+
+/**
@details
Created mostly for mysql_prepare_table(). Important
when a string ENUM/SET column is described with a numeric default value:
@@ -7931,6 +7967,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
return TRUE;
if (view->table && view->table->maybe_null)
maybe_null= TRUE;
+ set_null_ref_table();
return FALSE;
}
@@ -9470,6 +9507,11 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
item_decimals= 0;
decimals= MY_MAX(decimals, item_decimals);
}
+
+ if (fld_type == FIELD_TYPE_GEOMETRY)
+ geometry_type=
+ Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type());
+
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
{
decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
@@ -9775,13 +9817,30 @@ void Item_ref::update_used_tables()
(*ref)->update_used_tables();
}
+void Item_direct_view_ref::update_used_tables()
+{
+ set_null_ref_table();
+ Item_direct_ref::update_used_tables();
+}
+
+
table_map Item_direct_view_ref::used_tables() const
{
- return get_depended_from() ?
- OUTER_REF_TABLE_BIT :
- ((view->is_merged_derived() || view->merged || !view->table) ?
- (*ref)->used_tables() :
- view->table->map);
+ DBUG_ASSERT(null_ref_table);
+
+ if (get_depended_from())
+ return OUTER_REF_TABLE_BIT;
+
+ if (view->is_merged_derived() || view->merged || !view->table)
+ {
+ table_map used= (*ref)->used_tables();
+ return (used ?
+ used :
+ ((null_ref_table != NO_NULL_TABLE) ?
+ null_ref_table->map :
+ (table_map)0 ));
+ }
+ return view->table->map;
}
table_map Item_direct_view_ref::not_null_tables() const