[Maria-developers] changes in virtual column patch
![](https://secure.gravatar.com/avatar/ac32c9d693e0b70eec04d9ed68b9b4d8.jpg?s=120&d=mm&r=g)
Hi!
Here is first version of my changes of virtual column patch.
I also propose make following changes:
1) to make syntax even more compatible:
- Add optional 'GENERATED ALWAYS' instead of removed mandatory 'VIRTUAL'.
- Replase 'STORED' keyword with 'MATERIALIZED' and maybe make decision
if nothing mention after field definition whether it will be stored
depended on sql_mode (in oracle mode it will be stored) and add
'VIRTUAL' key word which force our current default (pure virtual column).
2) rename virtual_column_info class according MySQL codding style for
classes (Virtual_column_info)
What I've done:
- VIRTUAL removed.
- in error messages virtual replaced with computed.
- test suite fixed according to above changes.
- numeric error codes in --error in test suite replaced by sumbolic names
- added forgotten Item::check_vcol_func_processor() for many items
(which lead for several crashing bugs).
- strange 'switch' which tests only top most item type replaced with
tree walking so now there is no difference in function checks (and so
error messages) depending on where prohibited function used in the
expression.
- because of above check in fix_fields_vcol_func() removed by #ifdef
PARANOID usage (should be fixed in the final patch).
- fixed bug in altering computed field put in partitioning function
expression
- Added test for subquery in computed column expression which tests
subquery allowance and return ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
instead of previously tested syntax error.
=== modified file 'BUILD/SETUP.sh'
--- BUILD/SETUP.sh 2009-03-22 12:16:09 +0000
+++ BUILD/SETUP.sh 2009-03-24 16:06:06 +0000
@@ -169,7 +169,7 @@ max_no_embedded_configs="$SSL_LIBRARY --
max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server -with-libevent"
# Disable NDB in maria max builds
-max_configs=$max_no_ndb_configs
+#max_configs=$max_no_ndb_configs
#
# CPU and platform specific compilation flags.
=== modified file 'include/mysql_com.h'
--- include/mysql_com.h 2008-10-10 15:28:41 +0000
+++ include/mysql_com.h 2009-03-24 10:47:20 +0000
@@ -67,7 +67,14 @@ enum enum_server_command
COM_END
};
-
+/* The length of the header part for each virtual column in the .frm file. */
+#define FRM_VCOL_HEADER_SIZE 3
+/*
+ Maximum length of the expression statement defined for virtual columns.
+*/
+#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE
+/* sql type field stored in .frm files for each virtual field. */
+#define MYSQL_TYPE_VIRTUAL 245
/*
Length of random string sent by server on handshake; this is also length of
obfuscated password, recieved from client
=== modified file 'sql/field.cc'
--- sql/field.cc 2009-02-19 09:01:25 +0000
+++ sql/field.cc 2009-03-26 21:46:28 +0000
@@ -1312,7 +1312,8 @@ Field::Field(uchar *ptr_arg,uint32 lengt
key_start(0), part_of_key(0), part_of_key_not_clustered(0),
part_of_sortkey(0), unireg_check(unireg_check_arg),
field_length(length_arg), null_bit(null_bit_arg),
- is_created_from_null_item(FALSE)
+ is_created_from_null_item(FALSE),
+ vcol_info(0), stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -9495,6 +9496,8 @@ void Create_field::init_for_tmp_table(en
((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
(is_unsigned ? 0 : FIELDFLAG_DECIMAL));
+ vcol_info= 0;
+ stored_in_db= TRUE;
}
@@ -9514,6 +9517,7 @@ void Create_field::init_for_tmp_table(en
@param fld_interval_list Interval list (if any)
@param fld_charset Field charset
@param fld_geom_type Field geometry type (if any)
+ @param fld_vcol_info Virtual column data
@retval
FALSE on success
@@ -9526,7 +9530,8 @@ bool Create_field::init(THD *thd, char *
uint fld_type_modifier, Item *fld_default_value,
Item *fld_on_update_value, LEX_STRING *fld_comment,
char *fld_change, List<String> *fld_interval_list,
- CHARSET_INFO *fld_charset, uint fld_geom_type)
+ CHARSET_INFO *fld_charset, uint fld_geom_type,
+ virtual_column_info *fld_vcol_info)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9557,6 +9562,34 @@ bool Create_field::init(THD *thd, char *
interval_list.empty();
comment= *fld_comment;
+ vcol_info= fld_vcol_info;
+ stored_in_db= TRUE;
+
+ /* Initialize data for a virtual field */
+ if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(vcol_info);
+ DBUG_ASSERT(vcol_info->expr_item);
+ stored_in_db= vcol_info->get_field_stored();
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ if (vcol_info->expr_item->walk(&Item::check_vcol_func_processor, 0, NULL))
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Make a field created for the real type.
+ Note that "real" and virtual fields differ from each other
+ only by Field::vcol_info, which is always 0 for normal columns.
+ vcol_info is updated for fields later in procedure open_binary_frm.
+ */
+ sql_type= fld_type= vcol_info->get_real_type();
+ }
+
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
@@ -9847,7 +9880,7 @@ bool Create_field::init(THD *thd, char *
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
- }
+ }
/* Remember the value of length */
char_length= length;
@@ -9946,7 +9979,6 @@ uint pack_length_to_packflag(uint type)
return 0; // This shouldn't happen
}
-
Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
@@ -10140,6 +10172,8 @@ Create_field::Create_field(Field *old_fi
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
+ vcol_info= old_field->vcol_info;
+ stored_in_db= old_field->stored_in_db;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
=== modified file 'sql/field.h'
--- sql/field.h 2009-02-19 09:01:25 +0000
+++ sql/field.h 2009-03-26 21:35:01 +0000
@@ -45,6 +45,67 @@ inline uint get_set_pack_length(int elem
return len > 4 ? 8 : len;
}
+class virtual_column_info: public Sql_alloc
+{
+public:
+ Item *expr_item;
+ LEX_STRING expr_str;
+ Item *item_free_list;
+ virtual_column_info()
+ : expr_item(0), item_free_list(0),
+ field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
+ stored_in_db(FALSE), implicitly_stored_in_db(FALSE),data_inited(FALSE)
+ {
+ expr_str.str= NULL;
+ expr_str.length= 0;
+ };
+ ~virtual_column_info() {}
+ enum_field_types get_real_type()
+ {
+ DBUG_ASSERT(data_inited);
+ return data_inited ? field_type : (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
+ }
+ void set_field_type(enum_field_types fld_type)
+ {
+ /* Calling this function can only be done once. */
+ DBUG_ASSERT(!data_inited);
+ data_inited= TRUE;
+ field_type= fld_type;
+ }
+ bool get_field_stored()
+ {
+ DBUG_ASSERT(data_inited);
+ return data_inited ? stored_in_db : TRUE;
+ }
+ void set_field_stored(bool stored)
+ {
+ stored_in_db= stored;
+ }
+ bool is_field_implicitly_stored()
+ {
+ return implicitly_stored_in_db;
+ }
+ void set_field_implicitly_stored()
+ {
+ implicitly_stored_in_db= TRUE;
+ }
+private:
+ /*
+ The following data is only updated by the parser and read
+ when a Create_field object is created/initialized.
+ */
+ enum_field_types field_type; /* Real field type*/
+ /* Indication that the field is physically stored in the database*/
+ my_bool stored_in_db;
+ /* Indication that the field used in partitioning expression */
+ my_bool implicitly_stored_in_db;
+ /*
+ This flag is used to prevent other applications from
+ reading and using incorrect data.
+ */
+ my_bool data_inited;
+};
+
class Field
{
Field(const Item &); /* Prevent use of these */
@@ -103,6 +164,15 @@ public:
*/
bool is_created_from_null_item;
+ /* Virtual column data */
+ virtual_column_info *vcol_info;
+ /*
+ Indication that the field is phycically stored in tables
+ rather than just generated on SQL queries.
+ As of now, FALSE can only be set for generated-only virtual columns.
+ */
+ bool stored_in_db;
+
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg);
@@ -2044,6 +2114,16 @@ public:
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
+
+ /* Virtual column expression statement */
+ virtual_column_info *vcol_info;
+ /*
+ Indication that the field is phycically stored in tables
+ rather than just generated on SQL queries.
+ As of now, FALSE can only be set for generated-only virtual columns.
+ */
+ bool stored_in_db;
+
Create_field() :after(0) {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
@@ -2060,7 +2140,8 @@ public:
char *decimals, uint type_modifier, Item *default_value,
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ virtual_column_info *vcol_info);
};
=== modified file 'sql/filesort.cc'
--- sql/filesort.cc 2009-02-19 09:01:25 +0000
+++ sql/filesort.cc 2009-03-24 10:47:20 +0000
@@ -563,6 +563,8 @@ static ha_rows find_all_keys(SORTPARAM *
{
if ((error= select->quick->get_next()))
break;
+ if (!error)
+ update_virtual_fields_marked_for_write(sort_form);
file->position(sort_form->record[0]);
DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
}
@@ -580,6 +582,8 @@ static ha_rows find_all_keys(SORTPARAM *
else
{
error=file->rnd_next(sort_form->record[0]);
+ if (!error)
+ update_virtual_fields_marked_for_write(sort_form);
if (!flag)
{
my_store_ptr(ref_pos,ref_length,record); // Position to row
=== modified file 'sql/ha_partition.cc'
--- sql/ha_partition.cc 2009-02-19 09:01:25 +0000
+++ sql/ha_partition.cc 2009-03-24 10:47:20 +0000
@@ -2408,7 +2408,7 @@ int ha_partition::open(const char *name,
DBUG_RETURN(1);
m_start_key.length= 0;
m_rec0= table->record[0];
- m_rec_length= table_share->reclength;
+ m_rec_length= table_share->stored_rec_length;
alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
alloc_len+= table_share->max_key_length;
if (!m_ordered_rec_buffer)
=== modified file 'sql/ha_partition.h'
--- sql/ha_partition.h 2009-02-19 09:01:25 +0000
+++ sql/ha_partition.h 2009-03-24 10:47:20 +0000
@@ -245,6 +245,7 @@ public:
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
private:
=== modified file 'sql/handler.h'
--- sql/handler.h 2009-02-19 09:01:25 +0000
+++ sql/handler.h 2009-03-24 10:47:20 +0000
@@ -1755,6 +1755,12 @@ public:
LEX_STRING *engine_name() { return hton_name(ht); }
+ /*
+ This procedure defines if the storage engine supports virtual columns.
+ Default FALSE means "not supported".
+ */
+ virtual bool check_if_supported_virtual_columns(void) { return FALSE;}
+
protected:
/* Service methods for use by storage engines. */
void ha_statistic_increment(ulong SSV::*offset) const;
=== modified file 'sql/item.cc'
--- sql/item.cc 2009-02-19 09:01:25 +0000
+++ sql/item.cc 2009-03-26 21:24:20 +0000
@@ -677,9 +677,26 @@ bool Item_field::register_field_in_read_
TABLE *table= (TABLE *) arg;
if (field->table == table || !table)
bitmap_set_bit(field->table->read_set, field->field_index);
+ if (field->vcol_info && field->vcol_info->expr_item)
+ return field->vcol_info->expr_item->walk(&Item::register_field_in_read_map,
+ 1, arg);
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_field::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap= (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, field->field_index);
+ return 0;
+}
bool Item::check_cols(uint c)
{
@@ -4188,6 +4205,20 @@ error:
return TRUE;
}
+/**
+ Marks virtual columns as implicitly stored
+*/
+
+bool Item_field::vcol_in_partition_func_processor(uchar *int_arg)
+{
+ DBUG_ASSERT(fixed);
+ if (field->vcol_info)
+ {
+ field->vcol_info->set_field_implicitly_stored();
+ }
+ return TRUE;
+}
+
Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
{
=== modified file 'sql/item.h'
--- sql/item.h 2009-02-19 09:01:25 +0000
+++ sql/item.h 2009-03-26 20:59:23 +0000
@@ -889,6 +889,11 @@ public:
virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; }
/*
+ The next function differs from the previous one that a bitmap to be updated
+ is passed as uchar *arg.
+ */
+ virtual bool register_field_in_bitmap(uchar *arg) { return 0; }
+ /*
Check if a partition function is allowed
SYNOPSIS
check_partition_func_processor()
@@ -940,11 +945,28 @@ public:
fields.
*/
virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;}
+ virtual bool vcol_in_partition_func_processor(uchar *bool_arg) { return TRUE;}
virtual bool subst_argument_checker(uchar **arg)
- {
+ {
if (*arg)
- *arg= NULL;
- return TRUE;
+ *arg= NULL;
+ return TRUE;
+ }
+ /*
+ Check if an expression/function is allowed for a virtual column
+ SYNOPSIS
+ check_vcol_func_processor()
+ int_arg is just ignored
+ RETURN VALUE
+ TRUE Function not accepted
+ FALSE Function accepted
+ */
+ virtual bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
}
virtual Item *equal_fields_propagator(uchar * arg) { return this; }
@@ -1298,6 +1320,13 @@ public:
{
return value_item->send(protocol, str);
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_name_const::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
bool agg_item_collations(DTCollation &c, const char *name,
@@ -1315,6 +1344,7 @@ public:
virtual Item_num *neg()= 0;
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
#define NO_CACHED_FIELD_INDEX ((uint)(-1))
@@ -1474,7 +1504,10 @@ public:
bool collect_item_field_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool vcol_in_partition_func_processor(uchar *int_arg);
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
void cleanup();
bool result_as_longlong()
{
@@ -1534,6 +1567,7 @@ public:
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_null_result :public Item_null
@@ -1547,7 +1581,14 @@ public:
save_in_field(result_field, no_conversions);
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
-};
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_PRINT("info", (" Item name: %s", full_name()));
+ return TRUE;
+ }
+};
/* Item represents one placeholder ('?') of prepared statement */
@@ -1688,6 +1729,7 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
};
@@ -1723,6 +1765,7 @@ public:
{ return (uint)(max_length - test(value < 0)); }
bool eq(const Item *, bool binary_cmp) const;
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1741,6 +1784,7 @@ public:
Item_num *neg ();
uint decimal_precision() const { return max_length; }
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1782,6 +1826,7 @@ public:
bool eq(const Item *, bool binary_cmp) const;
void set_decimal_value(my_decimal *value_par);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1939,6 +1984,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
/**
Return TRUE if character-set-introducer was explicitly specified in the
@@ -2006,6 +2052,13 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_static_string_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2017,6 +2070,14 @@ public:
CHARSET_INFO *cs= NULL):
Item_string(name_arg, length, cs)
{}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_partition_func_safe_string::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2096,6 +2157,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -2126,6 +2188,7 @@ public:
save_in_field(result_field, no_conversions);
}
void cleanup();
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -2251,7 +2314,14 @@ public:
if (ref && result_type() == ROW_RESULT)
(*ref)->bring_value();
}
-
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_ref::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2484,6 +2554,14 @@ public:
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2614,6 +2692,13 @@ public:
return arg->walk(processor, walk_subquery, args) ||
(this->*processor)(args);
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_insert_value::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2710,6 +2795,14 @@ private:
BEFORE INSERT of BEFORE UPDATE trigger.
*/
bool read_only;
+ virtual bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_trigger_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2769,6 +2862,15 @@ public:
{
return this == item;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_cache::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
+
};
=== modified file 'sql/item_func.cc'
--- sql/item_func.cc 2009-02-19 09:01:25 +0000
+++ sql/item_func.cc 2009-03-24 10:47:20 +0000
@@ -3894,10 +3894,30 @@ bool Item_func_set_user_var::register_fi
TABLE *table= (TABLE *) arg;
if (result_field->table == table || !table)
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
+ if (result_field->vcol_info && result_field->vcol_info->expr_item)
+ return result_field->vcol_info->
+ expr_item->walk(&Item::register_field_in_read_map, 1, arg);
}
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap = (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (result_field)
+ {
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, result_field->field_index);
+ }
+ return 0;
+}
/**
Set value to user variable.
=== modified file 'sql/item_func.h'
--- sql/item_func.h 2009-02-19 09:01:25 +0000
+++ sql/item_func.h 2009-03-24 20:19:28 +0000
@@ -339,6 +339,7 @@ public:
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -398,6 +399,7 @@ public:
Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -433,6 +435,7 @@ public:
my_decimal *decimal_op(my_decimal *);
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -465,6 +468,7 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -479,6 +483,7 @@ public:
void result_precision();
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -495,6 +500,7 @@ public:
void fix_num_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -508,6 +514,7 @@ public:
const char *func_name() const { return "abs"; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
// A class to handle logarithmic and trigonometric functions
@@ -663,6 +670,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -675,6 +683,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
/* This handles round and truncate */
@@ -704,6 +713,13 @@ public:
bool const_item() const { return 0; }
void update_used_tables();
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_rand::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
private:
void seed_random (Item * val);
};
@@ -986,6 +1002,13 @@ public:
max_length= args[0]->max_length;
}
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_last_insert_id::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -999,6 +1022,13 @@ public:
const char *func_name() const { return "benchmark"; }
void fix_length_and_dec() { max_length=1; maybe_null=0; }
virtual void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_benchmark::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1014,6 +1044,13 @@ public:
used_tables_cache|= RAND_TABLE_BIT;
}
longlong val_int();
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sleep::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1263,6 +1300,13 @@ class Item_func_get_lock :public Item_in
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_get_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
class Item_func_release_lock :public Item_int_func
@@ -1273,6 +1317,13 @@ public:
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_release_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
/* replication functions */
@@ -1286,6 +1337,13 @@ public:
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_master_pos_wait::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1356,6 +1414,7 @@ public:
}
void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
};
@@ -1528,6 +1587,14 @@ public:
bool fix_index();
void init_search(bool no_order);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /* TODO: consider adding in support for the MATCH-based virtual columns */
+ DBUG_ENTER("Item_func_match::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1547,6 +1614,13 @@ public:
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_is_free_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
class Item_func_is_used_lock :public Item_int_func
@@ -1557,6 +1631,13 @@ public:
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_is_used_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
/* For type casts */
@@ -1576,6 +1657,13 @@ public:
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_row_count::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1684,6 +1772,13 @@ public:
{
return sp_result_field;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sp::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1694,6 +1789,13 @@ public:
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_found_rows::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1708,5 +1810,12 @@ public:
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_uuid_short::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_row.h'
--- sql/item_row.h 2008-02-22 10:30:33 +0000
+++ sql/item_row.h 2009-03-24 10:47:20 +0000
@@ -76,4 +76,5 @@ public:
bool check_cols(uint c);
bool null_inside() { return with_null; };
void bring_value();
-};
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE; }
+ };
=== modified file 'sql/item_strfunc.h'
--- sql/item_strfunc.h 2009-02-19 09:01:25 +0000
+++ sql/item_strfunc.h 2009-03-24 10:47:20 +0000
@@ -335,6 +335,14 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
const char *func_name() const { return "encrypt"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_encrypt::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
#include "sql_crypt.h"
@@ -372,6 +380,13 @@ public:
call
*/
virtual const char *fully_qualified_func_name() const = 0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sysconst::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -635,6 +650,13 @@ public:
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_load_file::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -831,5 +853,12 @@ public:
}
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_uuid::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_subselect.h'
--- sql/item_subselect.h 2008-02-22 10:30:33 +0000
+++ sql/item_subselect.h 2009-03-26 19:13:42 +0000
@@ -126,6 +126,13 @@ public:
virtual void reset_value_registration() {}
enum_parsing_place place() { return parsing_place; }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
/**
Get the SELECT_LEX structure associated with this Item.
=== modified file 'sql/item_sum.h'
--- sql/item_sum.h 2008-12-09 19:43:10 +0000
+++ sql/item_sum.h 2009-03-25 21:24:46 +0000
@@ -384,6 +384,13 @@ public:
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -664,6 +671,13 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_avg_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -732,6 +746,13 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_variance_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_timefunc.h'
--- sql/item_timefunc.h 2008-12-23 14:21:01 +0000
+++ sql/item_timefunc.h 2009-03-24 10:47:20 +0000
@@ -70,6 +70,7 @@ public:
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -86,6 +87,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -111,6 +113,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -124,6 +127,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE;}
};
@@ -140,6 +144,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -156,6 +161,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -172,6 +178,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -188,6 +195,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -204,6 +212,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -234,6 +243,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -252,6 +262,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -282,6 +293,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_func_dayname :public Item_func_weekday
@@ -294,6 +306,7 @@ class Item_func_dayname :public Item_fun
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -310,6 +323,18 @@ public:
decimals=0;
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /*
+ TODO: Allow UNIX_TIMESTAMP called with an argument to be a part
+ of the expression for a virtual column
+ */
+ DBUG_ENTER("Item_func_unix_timestamp::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -325,6 +350,7 @@ public:
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -444,6 +470,14 @@ public:
*/
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
bool result_as_longlong() { return TRUE; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_curtime::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -480,6 +514,13 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_curdate::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -520,6 +561,13 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_now::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -577,6 +625,7 @@ public:
const char *func_name() const { return "from_days"; }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -704,6 +753,7 @@ class Item_extract :public Item_int_func
bool eq(const Item *item, bool binary_cmp) const;
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -952,6 +1002,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
=== modified file 'sql/item_xmlfunc.cc'
--- sql/item_xmlfunc.cc 2009-01-31 21:22:44 +0000
+++ sql/item_xmlfunc.cc 2009-03-24 21:10:53 +0000
@@ -220,6 +220,14 @@ public:
collation.collation= pxml->charset();
}
const char *func_name() const { return "nodeset"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_nodeset_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -526,6 +534,13 @@ public:
enum Type type() const { return XPATH_NODESET_CMP; };
const char *func_name() const { return "xpath_nodeset_to_const_comparator"; }
bool is_bool_func() { return 1; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_nodeset_to_const_comparator::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
longlong val_int()
{
=== modified file 'sql/item_xmlfunc.h'
--- sql/item_xmlfunc.h 2007-11-21 12:00:09 +0000
+++ sql/item_xmlfunc.h 2009-03-24 10:47:20 +0000
@@ -40,6 +40,13 @@ public:
}
void fix_length_and_dec();
String *parse_xml(String *raw_xml, String *parsed_xml_buf);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_xml_str_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/lex.h'
--- sql/lex.h 2008-04-28 16:24:05 +0000
+++ sql/lex.h 2009-03-24 15:40:47 +0000
@@ -388,6 +388,7 @@ static SYMBOL symbols[] = {
{ "PARSER", SYM(PARSER_SYM)},
{ "PAGE", SYM(PAGE_SYM)},
{ "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)},
+ { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
@@ -514,6 +515,7 @@ static SYMBOL symbols[] = {
{ "STATUS", SYM(STATUS_SYM)},
{ "STOP", SYM(STOP_SYM)},
{ "STORAGE", SYM(STORAGE_SYM)},
+ { "STORED", SYM(STORED_SYM)},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN)},
{ "STRING", SYM(STRING_SYM)},
{ "SUBJECT", SYM(SUBJECT_SYM)},
=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h 2009-03-12 22:27:35 +0000
+++ sql/mysql_priv.h 2009-03-24 10:47:20 +0000
@@ -1312,6 +1312,8 @@ find_field_in_table(THD *thd, TABLE *tab
bool allow_rowid, uint *cached_field_index_ptr);
Field *
find_field_in_table_sef(TABLE *table, const char *name);
+int update_virtual_fields_marked_for_write(TABLE *table,
+ bool ignore_stored= TRUE);
#endif /* MYSQL_SERVER */
@@ -1432,14 +1434,16 @@ bool add_field_to_list(THD *thd, LEX_STR
LEX_STRING *comment,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ virtual_column_info *vcol_info);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ virtual_column_info *vcol_info);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
bool push_new_name_resolution_context(THD *thd,
=== modified file 'sql/procedure.h'
--- sql/procedure.h 2008-03-21 15:48:28 +0000
+++ sql/procedure.h 2009-03-24 21:48:56 +0000
@@ -43,6 +43,14 @@ public:
init_make_field(tmp_field,field_type());
}
unsigned int size_of() { return sizeof(*this);}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
class Item_proc_real :public Item_proc
=== modified file 'sql/records.cc'
--- sql/records.cc 2008-07-17 18:26:55 +0000
+++ sql/records.cc 2009-03-24 10:47:20 +0000
@@ -323,6 +323,7 @@ static int rr_quick(READ_RECORD *info)
break;
}
}
+ update_virtual_fields_marked_for_write(info->table);
return tmp;
}
@@ -395,6 +396,8 @@ int rr_sequential(READ_RECORD *info)
break;
}
}
+ if (!tmp)
+ update_virtual_fields_marked_for_write(info->table);
return tmp;
}
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2008-12-10 09:02:25 +0000
+++ sql/share/errmsg.txt 2009-03-25 21:24:46 +0000
@@ -6154,3 +6154,30 @@ WARN_PLUGIN_BUSY
ER_VARIABLE_IS_READONLY
eng "%s variable '%s' is read-only. Use SET %s to assign the value"
+
+ER_VCOL_BASED_ON_VCOL
+ eng "A computed column cannot be based on a computed column"
+
+ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ eng "Function or expression is not allowed for column '%s'."
+
+ER_DATA_CONVERSION_ERROR_FOR_VIRTUAL_COLUMN
+ eng "Generated value for computed column '%s' cannot be converted to type '%s'."
+
+ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN
+ eng "Primary key cannot be defined upon a computed column."
+
+ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+ eng "Key/Index cannot be defined on a non-stored computed column."
+
+ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+ eng "Cannot define foreign key with %s clause on a computed column."
+
+ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN
+ eng "The value specified for computed column '%s' in table '%s' ignored."
+
+ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+ eng "'%s' is not yet supported for computed columns."
+
+ER_CONST_EXPR_IN_VCOL
+ eng "Constant expression in computed column function is not allowed."
=== modified file 'sql/sp_head.cc'
--- sql/sp_head.cc 2009-02-19 09:01:25 +0000
+++ sql/sp_head.cc 2009-03-24 10:47:20 +0000
@@ -815,6 +815,8 @@ sp_head::create_result_field(uint field_
m_return_field_def.interval,
field_name ? field_name : (const char *) m_name.str);
+ field->vcol_info= m_return_field_def.vcol_info;
+ field->stored_in_db= m_return_field_def.stored_in_db;
if (field)
field->init(table);
@@ -2194,7 +2196,8 @@ sp_head::fill_field_definition(THD *thd,
&lex->interval_list,
lex->charset ? lex->charset :
thd->variables.collation_database,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_base.cc'
--- sql/sql_base.cc 2009-02-19 09:01:25 +0000
+++ sql/sql_base.cc 2009-03-24 10:47:20 +0000
@@ -5875,6 +5875,23 @@ find_field_in_table(THD *thd, TABLE *tab
if (field_ptr && *field_ptr)
{
+ if ((*field_ptr)->vcol_info)
+ {
+ if (thd->mark_used_columns != MARK_COLUMNS_NONE)
+ {
+ Item *vcol_item= (*field_ptr)->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ /*
+ Set the virtual field for write here if
+ 1) this procedure is called for a read-only operation (SELECT), and
+ 2) the virtual column is not phycically stored in the table
+ */
+ if (thd->mark_used_columns != MARK_COLUMNS_WRITE &&
+ !(*field_ptr)->stored_in_db)
+ bitmap_set_bit((*field_ptr)->table->write_set, (*field_ptr)->field_index);
+ }
+ }
*cached_field_index_ptr= field_ptr - table->field;
field= *field_ptr;
}
@@ -7857,6 +7874,17 @@ insert_fields(THD *thd, Name_resolution_
{
/* Mark fields as used to allow storage engine to optimze access */
bitmap_set_bit(field->table->read_set, field->field_index);
+ /*
+ Mark virtual fields for write and others that the virtual fields
+ depend on for read.
+ */
+ if (field->vcol_info)
+ {
+ Item *vcol_item= field->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ bitmap_set_bit(field->table->write_set, field->field_index);
+ }
if (table)
{
table->covering_keys.intersect(field->part_of_key);
@@ -8068,7 +8096,10 @@ fill_record(THD * thd, List<Item> &field
Item *value, *fld;
Item_field *field;
TABLE *table= 0;
+ List<TABLE> tbl_list;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -8102,14 +8133,54 @@ fill_record(THD * thd, List<Item> &field
table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (rfield->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ rfield->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields_marked_for_write(table, FALSE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8145,9 +8216,31 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, fields, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, fields, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers)
+ {
+ TABLE *table= 0;
+ List_iterator_fast<Item> f(fields);
+ Item *fld;
+ Item_field *item_field;
+ if (fields.elements)
+ {
+ fld= (Item_field*)f++;
+ item_field= fld->filed_for_view_update();
+ if (item_field && item_field->field &&
+ (table= item_field->field->table) &&
+ table->vfield)
+ result= update_virtual_fields_marked_for_write(table, FALSE);
+ }
+ }
+ return result;
}
@@ -8175,11 +8268,14 @@ bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
+ List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
Field *field;
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
only one row.
@@ -8199,12 +8295,52 @@ fill_record(THD *thd, Field **ptr, List<
table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (field->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ field->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if (value->save_in_field(field, 0) < 0)
goto err;
+ tbl_list.push_back(table);
+ }
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields_marked_for_write(table, FALSE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
}
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8240,9 +8376,22 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, ptr, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, ptr, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers && *ptr)
+ {
+ TABLE *table= (*ptr)->table;
+ if (table->vfield)
+ result= update_virtual_fields_marked_for_write(table, FALSE);
+ }
+ return result;
+
}
=== modified file 'sql/sql_class.cc'
--- sql/sql_class.cc 2009-03-12 22:27:35 +0000
+++ sql/sql_class.cc 2009-03-24 10:47:20 +0000
@@ -193,6 +193,57 @@ bool foreign_key_prefix(Key *a, Key *b)
#endif
}
+/*
+ Check if the foreign key options are compatible with columns
+ on which the FK is created.
+
+ RETURN
+ 0 Key valid
+ 1 Key invalid
+*/
+bool Foreign_key::validate(List
![](https://secure.gravatar.com/avatar/ac32c9d693e0b70eec04d9ed68b9b4d8.jpg?s=120&d=mm&r=g)
Hi!
Here is second version of changed virtual column patch:
- syntax now looks like
<name> <type> [GENERATED ALWAYS] AS <expression> [MATERIALIZED|VIRTUAL]
if MATERIALIZED|VIRTUAL is omitted then default is MATERIALIZED in
oracle mode, in other modes it is VIRTUAL.
- Virtual_column_info renamed
- GENERATED, ALWAYS, MATERIALIZED, VIRTUAL made non-reserved words
- spelling errors an spaces at the end of lines somewhere removed.
- Removed assigning of variable 'item' which was not used.
=== modified file 'BUILD/SETUP.sh'
--- BUILD/SETUP.sh 2009-03-22 12:16:09 +0000
+++ BUILD/SETUP.sh 2009-03-24 16:06:06 +0000
@@ -169,7 +169,7 @@ max_no_embedded_configs="$SSL_LIBRARY --
max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent"
max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server -with-libevent"
# Disable NDB in maria max builds
-max_configs=$max_no_ndb_configs
+#max_configs=$max_no_ndb_configs
#
# CPU and platform specific compilation flags.
=== modified file 'include/mysql_com.h'
--- include/mysql_com.h 2008-10-10 15:28:41 +0000
+++ include/mysql_com.h 2009-03-24 10:47:20 +0000
@@ -67,7 +67,14 @@ enum enum_server_command
COM_END
};
-
+/* The length of the header part for each virtual column in the .frm file. */
+#define FRM_VCOL_HEADER_SIZE 3
+/*
+ Maximum length of the expression statement defined for virtual columns.
+*/
+#define VIRTUAL_COLUMN_EXPRESSION_MAXLEN 255 - FRM_VCOL_HEADER_SIZE
+/* sql type field stored in .frm files for each virtual field. */
+#define MYSQL_TYPE_VIRTUAL 245
/*
Length of random string sent by server on handshake; this is also length of
obfuscated password, recieved from client
=== modified file 'sql/field.cc'
--- sql/field.cc 2009-02-19 09:01:25 +0000
+++ sql/field.cc 2009-03-30 14:42:36 +0000
@@ -1312,7 +1312,8 @@ Field::Field(uchar *ptr_arg,uint32 lengt
key_start(0), part_of_key(0), part_of_key_not_clustered(0),
part_of_sortkey(0), unireg_check(unireg_check_arg),
field_length(length_arg), null_bit(null_bit_arg),
- is_created_from_null_item(FALSE)
+ is_created_from_null_item(FALSE),
+ vcol_info(0), stored_in_db(TRUE)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -9495,6 +9496,8 @@ void Create_field::init_for_tmp_table(en
((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
(is_unsigned ? 0 : FIELDFLAG_DECIMAL));
+ vcol_info= 0;
+ stored_in_db= TRUE;
}
@@ -9514,6 +9517,7 @@ void Create_field::init_for_tmp_table(en
@param fld_interval_list Interval list (if any)
@param fld_charset Field charset
@param fld_geom_type Field geometry type (if any)
+ @param fld_vcol_info Virtual column data
@retval
FALSE on success
@@ -9526,13 +9530,14 @@ bool Create_field::init(THD *thd, char *
uint fld_type_modifier, Item *fld_default_value,
Item *fld_on_update_value, LEX_STRING *fld_comment,
char *fld_change, List<String> *fld_interval_list,
- CHARSET_INFO *fld_charset, uint fld_geom_type)
+ CHARSET_INFO *fld_charset, uint fld_geom_type,
+ Virtual_column_info *fld_vcol_info)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("Create_field::init()");
-
+
field= 0;
field_name= fld_name;
def= fld_default_value;
@@ -9557,6 +9562,34 @@ bool Create_field::init(THD *thd, char *
interval_list.empty();
comment= *fld_comment;
+ vcol_info= fld_vcol_info;
+ stored_in_db= TRUE;
+
+ /* Initialize data for a virtual field */
+ if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ {
+ DBUG_ASSERT(vcol_info);
+ DBUG_ASSERT(vcol_info->expr_item);
+ stored_in_db= vcol_info->get_field_stored();
+ /*
+ Walk through the Item tree checking if all items are valid
+ to be part of the virtual column
+ */
+ if (vcol_info->expr_item->walk(&Item::check_vcol_func_processor, 0, NULL))
+ {
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Make a field created for the real type.
+ Note that "real" and virtual fields differ from each other
+ only by Field::vcol_info, which is always 0 for normal columns.
+ vcol_info is updated for fields later in procedure open_binary_frm.
+ */
+ sql_type= fld_type= vcol_info->get_real_type();
+ }
+
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
@@ -9847,7 +9880,7 @@ bool Create_field::init(THD *thd, char *
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
- }
+ }
/* Remember the value of length */
char_length= length;
@@ -9946,7 +9979,6 @@ uint pack_length_to_packflag(uint type)
return 0; // This shouldn't happen
}
-
Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
@@ -10140,6 +10172,8 @@ Create_field::Create_field(Field *old_fi
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
+ vcol_info= old_field->vcol_info;
+ stored_in_db= old_field->stored_in_db;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
=== modified file 'sql/field.h'
--- sql/field.h 2009-02-19 09:01:25 +0000
+++ sql/field.h 2009-03-30 14:42:36 +0000
@@ -45,6 +45,67 @@ inline uint get_set_pack_length(int elem
return len > 4 ? 8 : len;
}
+class Virtual_column_info: public Sql_alloc
+{
+public:
+ Item *expr_item;
+ LEX_STRING expr_str;
+ Item *item_free_list;
+ Virtual_column_info()
+ : expr_item(0), item_free_list(0),
+ field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
+ stored_in_db(FALSE), implicitly_stored_in_db(FALSE),data_inited(FALSE)
+ {
+ expr_str.str= NULL;
+ expr_str.length= 0;
+ };
+ ~Virtual_column_info() {}
+ enum_field_types get_real_type()
+ {
+ DBUG_ASSERT(data_inited);
+ return data_inited ? field_type : (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
+ }
+ void set_field_type(enum_field_types fld_type)
+ {
+ /* Calling this function can only be done once. */
+ DBUG_ASSERT(!data_inited);
+ data_inited= TRUE;
+ field_type= fld_type;
+ }
+ bool get_field_stored()
+ {
+ DBUG_ASSERT(data_inited);
+ return data_inited ? stored_in_db : TRUE;
+ }
+ void set_field_stored(bool stored)
+ {
+ stored_in_db= stored;
+ }
+ bool is_field_implicitly_stored()
+ {
+ return implicitly_stored_in_db;
+ }
+ void set_field_implicitly_stored()
+ {
+ implicitly_stored_in_db= TRUE;
+ }
+private:
+ /*
+ The following data is only updated by the parser and read
+ when a Create_field object is created/initialized.
+ */
+ enum_field_types field_type; /* Real field type*/
+ /* Indication that the field is physically stored in the database*/
+ my_bool stored_in_db;
+ /* Indication that the field used in partitioning expression */
+ my_bool implicitly_stored_in_db;
+ /*
+ This flag is used to prevent other applications from
+ reading and using incorrect data.
+ */
+ my_bool data_inited;
+};
+
class Field
{
Field(const Item &); /* Prevent use of these */
@@ -57,7 +118,7 @@ public:
uchar *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
/*
- Note that you can use table->in_use as replacement for current_thd member
+ Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
struct st_table *table; // Pointer for table
@@ -67,10 +128,10 @@ public:
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
key_map part_of_sortkey;
- /*
- We use three additional unireg types for TIMESTAMP to overcome limitation
- of current binary format of .frm file. We'd like to be able to support
- NOW() as default and on update value for such fields but unable to hold
+ /*
+ We use three additional unireg types for TIMESTAMP to overcome limitation
+ of current binary format of .frm file. We'd like to be able to support
+ NOW() as default and on update value for such fields but unable to hold
this info anywhere except unireg_check field. This issue will be resolved
in more clean way with transition to new text based .frm format.
See also comment for Field_timestamp::Field_timestamp().
@@ -103,6 +164,15 @@ public:
*/
bool is_created_from_null_item;
+ /* Virtual column data */
+ Virtual_column_info *vcol_info;
+ /*
+ Indication that the field is physically stored in tables
+ rather than just generated on SQL queries.
+ As of now, FALSE can only be set for generated-only virtual columns.
+ */
+ bool stored_in_db;
+
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg);
@@ -2044,6 +2114,16 @@ public:
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
+
+ /* Virtual column expression statement */
+ Virtual_column_info *vcol_info;
+ /*
+ Indication that the field is physically stored in tables
+ rather than just generated on SQL queries.
+ As of now, FALSE can only be set for generated-only virtual columns.
+ */
+ bool stored_in_db;
+
Create_field() :after(0) {}
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
@@ -2060,7 +2140,8 @@ public:
char *decimals, uint type_modifier, Item *default_value,
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
};
=== modified file 'sql/filesort.cc'
--- sql/filesort.cc 2009-02-19 09:01:25 +0000
+++ sql/filesort.cc 2009-03-24 10:47:20 +0000
@@ -563,6 +563,8 @@ static ha_rows find_all_keys(SORTPARAM *
{
if ((error= select->quick->get_next()))
break;
+ if (!error)
+ update_virtual_fields_marked_for_write(sort_form);
file->position(sort_form->record[0]);
DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
}
@@ -580,6 +582,8 @@ static ha_rows find_all_keys(SORTPARAM *
else
{
error=file->rnd_next(sort_form->record[0]);
+ if (!error)
+ update_virtual_fields_marked_for_write(sort_form);
if (!flag)
{
my_store_ptr(ref_pos,ref_length,record); // Position to row
=== modified file 'sql/ha_partition.cc'
--- sql/ha_partition.cc 2009-02-19 09:01:25 +0000
+++ sql/ha_partition.cc 2009-03-24 10:47:20 +0000
@@ -2408,7 +2408,7 @@ int ha_partition::open(const char *name,
DBUG_RETURN(1);
m_start_key.length= 0;
m_rec0= table->record[0];
- m_rec_length= table_share->reclength;
+ m_rec_length= table_share->stored_rec_length;
alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
alloc_len+= table_share->max_key_length;
if (!m_ordered_rec_buffer)
=== modified file 'sql/ha_partition.h'
--- sql/ha_partition.h 2009-02-19 09:01:25 +0000
+++ sql/ha_partition.h 2009-03-24 10:47:20 +0000
@@ -245,6 +245,7 @@ public:
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
+ bool check_if_supported_virtual_columns(void) { return TRUE;}
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
private:
=== modified file 'sql/handler.h'
--- sql/handler.h 2009-02-19 09:01:25 +0000
+++ sql/handler.h 2009-03-24 10:47:20 +0000
@@ -1755,6 +1755,12 @@ public:
LEX_STRING *engine_name() { return hton_name(ht); }
+ /*
+ This procedure defines if the storage engine supports virtual columns.
+ Default FALSE means "not supported".
+ */
+ virtual bool check_if_supported_virtual_columns(void) { return FALSE;}
+
protected:
/* Service methods for use by storage engines. */
void ha_statistic_increment(ulong SSV::*offset) const;
=== modified file 'sql/item.cc'
--- sql/item.cc 2009-02-19 09:01:25 +0000
+++ sql/item.cc 2009-03-26 23:39:01 +0000
@@ -677,9 +677,26 @@ bool Item_field::register_field_in_read_
TABLE *table= (TABLE *) arg;
if (field->table == table || !table)
bitmap_set_bit(field->table->read_set, field->field_index);
+ if (field->vcol_info && field->vcol_info->expr_item)
+ return field->vcol_info->expr_item->walk(&Item::register_field_in_read_map,
+ 1, arg);
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_field::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap= (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, field->field_index);
+ return 0;
+}
bool Item::check_cols(uint c)
{
@@ -4188,6 +4205,20 @@ error:
return TRUE;
}
+/**
+ Marks virtual columns as implicitly stored
+*/
+
+bool Item_field::vcol_in_partition_func_processor(uchar *int_arg)
+{
+ DBUG_ASSERT(fixed);
+ if (field->vcol_info)
+ {
+ field->vcol_info->set_field_implicitly_stored();
+ }
+ return FALSE;
+}
+
Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
{
=== modified file 'sql/item.h'
--- sql/item.h 2009-02-19 09:01:25 +0000
+++ sql/item.h 2009-03-26 23:39:00 +0000
@@ -889,6 +889,11 @@ public:
virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; }
/*
+ The next function differs from the previous one that a bitmap to be updated
+ is passed as uchar *arg.
+ */
+ virtual bool register_field_in_bitmap(uchar *arg) { return 0; }
+ /*
Check if a partition function is allowed
SYNOPSIS
check_partition_func_processor()
@@ -940,11 +945,31 @@ public:
fields.
*/
virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;}
+ virtual bool vcol_in_partition_func_processor(uchar *bool_arg)
+ {
+ return FALSE;
+ }
virtual bool subst_argument_checker(uchar **arg)
- {
+ {
if (*arg)
- *arg= NULL;
- return TRUE;
+ *arg= NULL;
+ return TRUE;
+ }
+ /*
+ Check if an expression/function is allowed for a virtual column
+ SYNOPSIS
+ check_vcol_func_processor()
+ int_arg is just ignored
+ RETURN VALUE
+ TRUE Function not accepted
+ FALSE Function accepted
+ */
+ virtual bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
}
virtual Item *equal_fields_propagator(uchar * arg) { return this; }
@@ -1298,6 +1323,13 @@ public:
{
return value_item->send(protocol, str);
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_name_const::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
bool agg_item_collations(DTCollation &c, const char *name,
@@ -1315,6 +1347,7 @@ public:
virtual Item_num *neg()= 0;
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
#define NO_CACHED_FIELD_INDEX ((uint)(-1))
@@ -1474,7 +1507,10 @@ public:
bool collect_item_field_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool vcol_in_partition_func_processor(uchar *int_arg);
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
void cleanup();
bool result_as_longlong()
{
@@ -1534,6 +1570,7 @@ public:
Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_null_result :public Item_null
@@ -1547,7 +1584,14 @@ public:
save_in_field(result_field, no_conversions);
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
-};
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_PRINT("info", (" Item name: %s", full_name()));
+ return TRUE;
+ }
+};
/* Item represents one placeholder ('?') of prepared statement */
@@ -1688,6 +1732,7 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
};
@@ -1723,6 +1768,7 @@ public:
{ return (uint)(max_length - test(value < 0)); }
bool eq(const Item *, bool binary_cmp) const;
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1741,6 +1787,7 @@ public:
Item_num *neg ();
uint decimal_precision() const { return max_length; }
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1782,6 +1829,7 @@ public:
bool eq(const Item *, bool binary_cmp) const;
void set_decimal_value(my_decimal *value_par);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -1939,6 +1987,7 @@ public:
}
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
/**
Return TRUE if character-set-introducer was explicitly specified in the
@@ -2006,6 +2055,13 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_static_string_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2017,6 +2073,14 @@ public:
CHARSET_INFO *cs= NULL):
Item_string(name_arg, length, cs)
{}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_partition_func_safe_string::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2096,6 +2160,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -2126,6 +2191,7 @@ public:
save_in_field(result_field, no_conversions);
}
void cleanup();
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -2251,7 +2317,14 @@ public:
if (ref && result_type() == ROW_RESULT)
(*ref)->bring_value();
}
-
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_ref::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2484,6 +2557,14 @@ public:
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2614,6 +2695,13 @@ public:
return arg->walk(processor, walk_subquery, args) ||
(this->*processor)(args);
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_insert_value::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2710,6 +2798,14 @@ private:
BEFORE INSERT of BEFORE UPDATE trigger.
*/
bool read_only;
+ virtual bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_trigger_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
@@ -2769,6 +2865,15 @@ public:
{
return this == item;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_cache::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
+
};
=== modified file 'sql/item_func.cc'
--- sql/item_func.cc 2009-02-19 09:01:25 +0000
+++ sql/item_func.cc 2009-03-24 10:47:20 +0000
@@ -3894,10 +3894,30 @@ bool Item_func_set_user_var::register_fi
TABLE *table= (TABLE *) arg;
if (result_field->table == table || !table)
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
+ if (result_field->vcol_info && result_field->vcol_info->expr_item)
+ return result_field->vcol_info->
+ expr_item->walk(&Item::register_field_in_read_map, 1, arg);
}
return 0;
}
+/*
+ Mark field in bitmap supplied as *arg
+
+*/
+
+bool Item_func_set_user_var::register_field_in_bitmap(uchar *arg)
+{
+ MY_BITMAP *bitmap = (MY_BITMAP *) arg;
+ DBUG_ASSERT(bitmap);
+ if (result_field)
+ {
+ if (!bitmap)
+ return 1;
+ bitmap_set_bit(bitmap, result_field->field_index);
+ }
+ return 0;
+}
/**
Set value to user variable.
=== modified file 'sql/item_func.h'
--- sql/item_func.h 2009-02-19 09:01:25 +0000
+++ sql/item_func.h 2009-03-24 20:19:28 +0000
@@ -339,6 +339,7 @@ public:
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -398,6 +399,7 @@ public:
Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -433,6 +435,7 @@ public:
my_decimal *decimal_op(my_decimal *);
void result_precision();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -465,6 +468,7 @@ public:
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -479,6 +483,7 @@ public:
void result_precision();
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -495,6 +500,7 @@ public:
void fix_num_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -508,6 +514,7 @@ public:
const char *func_name() const { return "abs"; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
// A class to handle logarithmic and trigonometric functions
@@ -663,6 +670,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -675,6 +683,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
/* This handles round and truncate */
@@ -704,6 +713,13 @@ public:
bool const_item() const { return 0; }
void update_used_tables();
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_rand::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
private:
void seed_random (Item * val);
};
@@ -986,6 +1002,13 @@ public:
max_length= args[0]->max_length;
}
bool fix_fields(THD *thd, Item **ref);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_last_insert_id::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -999,6 +1022,13 @@ public:
const char *func_name() const { return "benchmark"; }
void fix_length_and_dec() { max_length=1; maybe_null=0; }
virtual void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_benchmark::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1014,6 +1044,13 @@ public:
used_tables_cache|= RAND_TABLE_BIT;
}
longlong val_int();
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sleep::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1263,6 +1300,13 @@ class Item_func_get_lock :public Item_in
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_get_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
class Item_func_release_lock :public Item_int_func
@@ -1273,6 +1317,13 @@ public:
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_release_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
/* replication functions */
@@ -1286,6 +1337,13 @@ public:
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_master_pos_wait::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1356,6 +1414,7 @@ public:
}
void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
};
@@ -1528,6 +1587,14 @@ public:
bool fix_index();
void init_search(bool no_order);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /* TODO: consider adding in support for the MATCH-based virtual columns */
+ DBUG_ENTER("Item_func_match::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1547,6 +1614,13 @@ public:
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_is_free_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
class Item_func_is_used_lock :public Item_int_func
@@ -1557,6 +1631,13 @@ public:
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_is_used_lock::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
/* For type casts */
@@ -1576,6 +1657,13 @@ public:
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_row_count::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1684,6 +1772,13 @@ public:
{
return sp_result_field;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sp::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1694,6 +1789,13 @@ public:
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_found_rows::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -1708,5 +1810,12 @@ public:
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_uuid_short::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_row.h'
--- sql/item_row.h 2008-02-22 10:30:33 +0000
+++ sql/item_row.h 2009-03-24 10:47:20 +0000
@@ -76,4 +76,5 @@ public:
bool check_cols(uint c);
bool null_inside() { return with_null; };
void bring_value();
-};
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE; }
+ };
=== modified file 'sql/item_strfunc.h'
--- sql/item_strfunc.h 2009-02-19 09:01:25 +0000
+++ sql/item_strfunc.h 2009-03-24 10:47:20 +0000
@@ -335,6 +335,14 @@ public:
String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; }
const char *func_name() const { return "encrypt"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_encrypt::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
#include "sql_crypt.h"
@@ -372,6 +380,13 @@ public:
call
*/
virtual const char *fully_qualified_func_name() const = 0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_sysconst::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -635,6 +650,13 @@ public:
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_load_file::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -831,5 +853,12 @@ public:
}
const char *func_name() const{ return "uuid"; }
String *val_str(String *);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_uuid::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_subselect.h'
--- sql/item_subselect.h 2008-02-22 10:30:33 +0000
+++ sql/item_subselect.h 2009-03-26 19:13:42 +0000
@@ -126,6 +126,13 @@ public:
virtual void reset_value_registration() {}
enum_parsing_place place() { return parsing_place; }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
/**
Get the SELECT_LEX structure associated with this Item.
=== modified file 'sql/item_sum.h'
--- sql/item_sum.h 2008-12-09 19:43:10 +0000
+++ sql/item_sum.h 2009-03-25 21:24:46 +0000
@@ -384,6 +384,13 @@ public:
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -664,6 +671,13 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_avg_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -732,6 +746,13 @@ public:
}
void fix_length_and_dec() {}
enum Item_result result_type () const { return hybrid_type; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_variance_field::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/item_timefunc.h'
--- sql/item_timefunc.h 2008-12-23 14:21:01 +0000
+++ sql/item_timefunc.h 2009-03-24 10:47:20 +0000
@@ -70,6 +70,7 @@ public:
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -86,6 +87,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -111,6 +113,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -124,6 +127,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) {return FALSE;}
};
@@ -140,6 +144,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -156,6 +161,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -172,6 +178,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -188,6 +195,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -204,6 +212,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -234,6 +243,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -252,6 +262,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -282,6 +293,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
class Item_func_dayname :public Item_func_weekday
@@ -294,6 +306,7 @@ class Item_func_dayname :public Item_fun
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -310,6 +323,18 @@ public:
decimals=0;
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ /*
+ TODO: Allow UNIX_TIMESTAMP called with an argument to be a part
+ of the expression for a virtual column
+ */
+ DBUG_ENTER("Item_func_unix_timestamp::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -325,6 +350,7 @@ public:
max_length=10*MY_CHARSET_BIN_MB_MAXLEN;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -444,6 +470,14 @@ public:
*/
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
bool result_as_longlong() { return TRUE; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_curtime::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -480,6 +514,13 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_curdate::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -520,6 +561,13 @@ public:
void fix_length_and_dec();
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_func_now::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
@@ -577,6 +625,7 @@ public:
const char *func_name() const { return "from_days"; }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -704,6 +753,7 @@ class Item_extract :public Item_int_func
bool eq(const Item *item, bool binary_cmp) const;
virtual void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
@@ -952,6 +1002,7 @@ public:
maybe_null=1;
}
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
};
=== modified file 'sql/item_xmlfunc.cc'
--- sql/item_xmlfunc.cc 2009-01-31 21:22:44 +0000
+++ sql/item_xmlfunc.cc 2009-03-24 21:10:53 +0000
@@ -220,6 +220,14 @@ public:
collation.collation= pxml->charset();
}
const char *func_name() const { return "nodeset"; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_nodeset_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
+
};
@@ -526,6 +534,13 @@ public:
enum Type type() const { return XPATH_NODESET_CMP; };
const char *func_name() const { return "xpath_nodeset_to_const_comparator"; }
bool is_bool_func() { return 1; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_nodeset_to_const_comparator::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
longlong val_int()
{
=== modified file 'sql/item_xmlfunc.h'
--- sql/item_xmlfunc.h 2007-11-21 12:00:09 +0000
+++ sql/item_xmlfunc.h 2009-03-24 10:47:20 +0000
@@ -40,6 +40,13 @@ public:
}
void fix_length_and_dec();
String *parse_xml(String *raw_xml, String *parsed_xml_buf);
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_xml_str_func::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_RETURN(TRUE);
+ }
};
=== modified file 'sql/lex.h'
--- sql/lex.h 2008-04-28 16:24:05 +0000
+++ sql/lex.h 2009-03-27 12:33:10 +0000
@@ -62,6 +62,7 @@ static SYMBOL symbols[] = {
{ "ALL", SYM(ALL)},
{ "ALGORITHM", SYM(ALGORITHM_SYM)},
{ "ALTER", SYM(ALTER)},
+ { "ALWAYS", SYM(ALWAYS_SYM)},
{ "ANALYZE", SYM(ANALYZE_SYM)},
{ "AND", SYM(AND_SYM)},
{ "ANY", SYM(ANY_SYM)},
@@ -220,6 +221,7 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL)},
{ "FULLTEXT", SYM(FULLTEXT_SYM)},
{ "FUNCTION", SYM(FUNCTION_SYM)},
+ { "GENERATED", SYM(GENERATED_SYM)},
{ "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)},
@@ -320,6 +322,7 @@ static SYMBOL symbols[] = {
{ "MASTER_SSL_KEY", SYM(MASTER_SSL_KEY_SYM)},
{ "MASTER_SSL_VERIFY_SERVER_CERT", SYM(MASTER_SSL_VERIFY_SERVER_CERT_SYM)},
{ "MASTER_USER", SYM(MASTER_USER_SYM)},
+ { "MATERIALIZED", SYM(MATERIALIZED_SYM)},
{ "MATCH", SYM(MATCH)},
{ "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)},
{ "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)},
@@ -388,6 +391,7 @@ static SYMBOL symbols[] = {
{ "PARSER", SYM(PARSER_SYM)},
{ "PAGE", SYM(PAGE_SYM)},
{ "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)},
+ { "PARSE_VCOL_EXPR", SYM(PARSE_VCOL_EXPR_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
@@ -581,6 +585,7 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
+ { "VIRTUAL", SYM(VIRTUAL_SYM)},
{ "WAIT", SYM(WAIT_SYM)},
{ "WARNINGS", SYM(WARNINGS)},
{ "WEEK", SYM(WEEK_SYM)},
=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h 2009-03-12 22:27:35 +0000
+++ sql/mysql_priv.h 2009-03-30 14:42:36 +0000
@@ -1312,6 +1312,8 @@ find_field_in_table(THD *thd, TABLE *tab
bool allow_rowid, uint *cached_field_index_ptr);
Field *
find_field_in_table_sef(TABLE *table, const char *name);
+int update_virtual_fields_marked_for_write(TABLE *table,
+ bool ignore_stored= TRUE);
#endif /* MYSQL_SERVER */
@@ -1432,14 +1434,16 @@ bool add_field_to_list(THD *thd, LEX_STR
LEX_STRING *comment,
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type);
+ uint uint_geom_type,
+ Virtual_column_info *vcol_info);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
bool push_new_name_resolution_context(THD *thd,
=== modified file 'sql/procedure.h'
--- sql/procedure.h 2008-03-21 15:48:28 +0000
+++ sql/procedure.h 2009-03-24 21:48:56 +0000
@@ -43,6 +43,14 @@ public:
init_make_field(tmp_field,field_type());
}
unsigned int size_of() { return sizeof(*this);}
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ DBUG_ENTER("Item_sum::check_vcol_func_processor");
+ DBUG_PRINT("info",
+ ("check_vcol_func_processor returns TRUE: unsupported function"));
+ DBUG_ASSERT(0); /* this is not possible */
+ DBUG_RETURN(TRUE);
+ }
};
class Item_proc_real :public Item_proc
=== modified file 'sql/records.cc'
--- sql/records.cc 2008-07-17 18:26:55 +0000
+++ sql/records.cc 2009-03-24 10:47:20 +0000
@@ -323,6 +323,7 @@ static int rr_quick(READ_RECORD *info)
break;
}
}
+ update_virtual_fields_marked_for_write(info->table);
return tmp;
}
@@ -395,6 +396,8 @@ int rr_sequential(READ_RECORD *info)
break;
}
}
+ if (!tmp)
+ update_virtual_fields_marked_for_write(info->table);
return tmp;
}
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2008-12-10 09:02:25 +0000
+++ sql/share/errmsg.txt 2009-03-25 21:24:46 +0000
@@ -6154,3 +6154,30 @@ WARN_PLUGIN_BUSY
ER_VARIABLE_IS_READONLY
eng "%s variable '%s' is read-only. Use SET %s to assign the value"
+
+ER_VCOL_BASED_ON_VCOL
+ eng "A computed column cannot be based on a computed column"
+
+ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED
+ eng "Function or expression is not allowed for column '%s'."
+
+ER_DATA_CONVERSION_ERROR_FOR_VIRTUAL_COLUMN
+ eng "Generated value for computed column '%s' cannot be converted to type '%s'."
+
+ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN
+ eng "Primary key cannot be defined upon a computed column."
+
+ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN
+ eng "Key/Index cannot be defined on a non-stored computed column."
+
+ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN
+ eng "Cannot define foreign key with %s clause on a computed column."
+
+ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN
+ eng "The value specified for computed column '%s' in table '%s' ignored."
+
+ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN
+ eng "'%s' is not yet supported for computed columns."
+
+ER_CONST_EXPR_IN_VCOL
+ eng "Constant expression in computed column function is not allowed."
=== modified file 'sql/sp_head.cc'
--- sql/sp_head.cc 2009-02-19 09:01:25 +0000
+++ sql/sp_head.cc 2009-03-24 10:47:20 +0000
@@ -815,6 +815,8 @@ sp_head::create_result_field(uint field_
m_return_field_def.interval,
field_name ? field_name : (const char *) m_name.str);
+ field->vcol_info= m_return_field_def.vcol_info;
+ field->stored_in_db= m_return_field_def.stored_in_db;
if (field)
field->init(table);
@@ -2194,7 +2196,8 @@ sp_head::fill_field_definition(THD *thd,
&lex->interval_list,
lex->charset ? lex->charset :
thd->variables.collation_database,
- lex->uint_geom_type))
+ lex->uint_geom_type,
+ lex->vcol_info))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_base.cc'
--- sql/sql_base.cc 2009-02-19 09:01:25 +0000
+++ sql/sql_base.cc 2009-03-30 14:42:36 +0000
@@ -5875,6 +5875,23 @@ find_field_in_table(THD *thd, TABLE *tab
if (field_ptr && *field_ptr)
{
+ if ((*field_ptr)->vcol_info)
+ {
+ if (thd->mark_used_columns != MARK_COLUMNS_NONE)
+ {
+ Item *vcol_item= (*field_ptr)->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ /*
+ Set the virtual field for write here if
+ 1) this procedure is called for a read-only operation (SELECT), and
+ 2) the virtual column is not physically stored in the table
+ */
+ if (thd->mark_used_columns != MARK_COLUMNS_WRITE &&
+ !(*field_ptr)->stored_in_db)
+ bitmap_set_bit((*field_ptr)->table->write_set, (*field_ptr)->field_index);
+ }
+ }
*cached_field_index_ptr= field_ptr - table->field;
field= *field_ptr;
}
@@ -7857,6 +7874,17 @@ insert_fields(THD *thd, Name_resolution_
{
/* Mark fields as used to allow storage engine to optimze access */
bitmap_set_bit(field->table->read_set, field->field_index);
+ /*
+ Mark virtual fields for write and others that the virtual fields
+ depend on for read.
+ */
+ if (field->vcol_info)
+ {
+ Item *vcol_item= field->vcol_info->expr_item;
+ DBUG_ASSERT(vcol_item);
+ vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+ bitmap_set_bit(field->table->write_set, field->field_index);
+ }
if (table)
{
table->covering_keys.intersect(field->part_of_key);
@@ -8068,7 +8096,10 @@ fill_record(THD * thd, List<Item> &field
Item *value, *fld;
Item_field *field;
TABLE *table= 0;
+ List<TABLE> tbl_list;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
@@ -8102,14 +8133,54 @@ fill_record(THD * thd, List<Item> &field
table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (rfield->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ rfield->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
+ tbl_list.push_back(table);
+ }
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields_marked_for_write(table, FALSE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
}
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8145,9 +8216,31 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, fields, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, fields, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers)
+ {
+ TABLE *table= 0;
+ List_iterator_fast<Item> f(fields);
+ Item *fld;
+ Item_field *item_field;
+ if (fields.elements)
+ {
+ fld= (Item_field*)f++;
+ item_field= fld->filed_for_view_update();
+ if (item_field && item_field->field &&
+ (table= item_field->field->table) &&
+ table->vfield)
+ result= update_virtual_fields_marked_for_write(table, FALSE);
+ }
+ }
+ return result;
}
@@ -8175,11 +8268,14 @@ bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
+ List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
+ bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
Field *field;
+ tbl_list.empty();
/*
Reset the table->auto_increment_field_not_null as it is valid for
only one row.
@@ -8199,12 +8295,52 @@ fill_record(THD *thd, Field **ptr, List<
table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
+ if (field->vcol_info &&
+ value->type() != Item::DEFAULT_VALUE_ITEM &&
+ value->type() != Item::NULL_ITEM &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
+ {
+ thd->abort_on_warning= FALSE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
+ ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
+ field->field_name, table->s->table_name.str);
+ thd->abort_on_warning= abort_on_warning_saved;
+ }
if (value->save_in_field(field, 0) < 0)
goto err;
+ tbl_list.push_back(table);
}
+ /* Update virtual fields*/
+ thd->abort_on_warning= FALSE;
+ if (tbl_list.head())
+ {
+ List_iterator_fast<TABLE> t(tbl_list);
+ TABLE *prev_table= 0;
+ while ((table= t++))
+ {
+ /*
+ Do simple optimization to prevent unnecessary re-generating
+ values for virtual fields
+ */
+ if (table != prev_table)
+ {
+ prev_table= table;
+ if (table->vfield)
+ {
+ if (update_virtual_fields_marked_for_write(table, FALSE))
+ {
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error());
err:
+ thd->abort_on_warning= abort_on_warning_saved;
if (table)
table->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
@@ -8240,9 +8376,22 @@ fill_record_n_invoke_before_triggers(THD
Table_triggers_list *triggers,
enum trg_event_type event)
{
- return (fill_record(thd, ptr, values, ignore_errors) ||
- (triggers && triggers->process_triggers(thd, event,
- TRG_ACTION_BEFORE, TRUE)));
+ bool result;
+ result= (fill_record(thd, ptr, values, ignore_errors) ||
+ (triggers && triggers->process_triggers(thd, event,
+ TRG_ACTION_BEFORE, TRUE)));
+ /*
+ Re-calculate virtual fields to cater for cases when base columns are
+ updated by the triggers.
+ */
+ if (!result && triggers && *ptr)
+ {
+ TABLE *table= (*ptr)->table;
+ if (table->vfield)
+ result= update_virtual_fields_marked_for_write(table, FALSE);
+ }
+ return result;
+
}
=== modified file 'sql/sql_class.cc'
--- sql/sql_class.cc 2009-03-12 22:27:35 +0000
+++ sql/sql_class.cc 2009-03-24 10:47:20 +0000
@@ -193,6 +193,57 @@ bool foreign_key_prefix(Key *a, Key *b)
#endif
}
+/*
+ Check if the foreign key options are compatible with columns
+ on which the FK is created.
+
+ RETURN
+ 0 Key valid
+ 1 Key invalid
+*/
+bool Foreign_key::validate(List
participants (1)
-
Oleksandr "Sanja" Byelkin