summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h27
-rw-r--r--sql/item.cc9
-rw-r--r--sql/item.h5
-rw-r--r--sql/table.cc18
4 files changed, 48 insertions, 11 deletions
diff --git a/sql/field.h b/sql/field.h
index 7aa45cf1177..14f14afdaf7 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -563,7 +563,10 @@ inline bool is_temporal_type_with_time(enum_field_types type)
enum enum_vcol_info_type
{
VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
- VCOL_DEFAULT, VCOL_CHECK_FIELD, VCOL_CHECK_TABLE
+ VCOL_DEFAULT, VCOL_CHECK_FIELD, VCOL_CHECK_TABLE,
+ /* Additional types should be added here */
+ /* Following is the highest value last */
+ VCOL_TYPE_NONE = 127 // Since the 0 value is already in use
};
static inline const char *vcol_type_name(enum_vcol_info_type type)
@@ -578,6 +581,8 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
case VCOL_CHECK_FIELD:
case VCOL_CHECK_TABLE:
return "CHECK";
+ case VCOL_TYPE_NONE:
+ return "UNTYPED";
}
return 0;
}
@@ -591,7 +596,8 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
#define VCOL_NON_DETERMINISTIC 2
#define VCOL_SESSION_FUNC 4 /* uses session data, e.g. USER or DAYNAME */
#define VCOL_TIME_FUNC 8
-#define VCOL_IMPOSSIBLE 16
+#define VCOL_AUTO_INC 16
+#define VCOL_IMPOSSIBLE 32
#define VCOL_NOT_STRICTLY_DETERMINISTIC \
(VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC)
@@ -609,6 +615,7 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
class Virtual_column_info: public Sql_alloc
{
private:
+ enum_vcol_info_type vcol_type; /* Virtual column expression type */
/*
The following data is only updated by the parser and read
when a Create_field object is created/initialized.
@@ -626,7 +633,8 @@ public:
uint flags;
Virtual_column_info()
- : field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
+ : vcol_type((enum_vcol_info_type)VCOL_TYPE_NONE),
+ field_type((enum enum_field_types)MYSQL_TYPE_VIRTUAL),
in_partitioning_expr(FALSE), stored_in_db(FALSE),
utf8(TRUE), expr(NULL), flags(0)
{
@@ -634,6 +642,19 @@ public:
name.length= 0;
};
~Virtual_column_info() {}
+ enum_vcol_info_type get_vcol_type() const
+ {
+ return vcol_type;
+ }
+ void set_vcol_type(enum_vcol_info_type v_type)
+ {
+ vcol_type= v_type;
+ }
+ const char *get_vcol_type_name() const
+ {
+ DBUG_ASSERT(vcol_type != VCOL_TYPE_NONE);
+ return vcol_type_name(vcol_type);
+ }
enum_field_types get_real_type() const
{
return field_type;
diff --git a/sql/item.cc b/sql/item.cc
index 08316d95276..446176ff398 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -979,7 +979,7 @@ bool Item_field::register_field_in_write_map(void *arg)
This means:
- For default fields we can't access the same field or a field after
itself that doesn't have a non-constant default value.
- - A virtual fields can't access itself or a virtual field after itself.
+ - A virtual field can't access itself or a virtual field after itself.
- user-specified values will not see virtual fields or default expressions,
as in INSERT t1 (a) VALUES (b);
- no virtual fields can access auto-increment values
@@ -995,13 +995,6 @@ bool Item_field::check_field_expression_processor(void *arg)
Field *org_field= (Field*) arg;
if (field->flags & NO_DEFAULT_VALUE_FLAG)
return 0;
- if (field->flags & AUTO_INCREMENT_FLAG)
- {
- my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD,
- MYF(0),
- org_field->field_name, field->field_name);
- return 1;
- }
if ((field->default_value && field->default_value->flags) || field->vcol_info)
{
if (field == org_field ||
diff --git a/sql/item.h b/sql/item.h
index 6d69e3b60de..078641c490c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2611,6 +2611,11 @@ public:
bool check_vcol_func_processor(void *arg)
{
context= 0;
+ if (field && (field->unireg_check == Field::NEXT_NUMBER))
+ {
+ // Auto increment fields are unsupported
+ return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
+ }
return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF);
}
void cleanup();
diff --git a/sql/table.cc b/sql/table.cc
index 6d1a3a7f8d8..380da5fcd7b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1962,6 +1962,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
unireg_check == Field::TIMESTAMP_DN_FIELD)
{
reg_field->default_value= new (&share->mem_root) Virtual_column_info();
+ reg_field->default_value->set_vcol_type(VCOL_DEFAULT);
reg_field->default_value->stored_in_db= 1;
share->default_expressions++;
}
@@ -2361,6 +2362,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (!(vcol_info= new (&share->mem_root) Virtual_column_info()))
goto err;
+
/* The following can only be true for check_constraints */
if (field_nr != UINT_MAX16)
@@ -2370,6 +2372,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
vcol_screen_pos+= FRM_VCOL_NEW_HEADER_SIZE;
+ vcol_info->set_vcol_type((enum_vcol_info_type) type);
vcol_info->name.length= name_length;
if (name_length)
vcol_info->name.str= strmake_root(&share->mem_root,
@@ -2811,6 +2814,20 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
"???", "?????");
DBUG_RETURN(1);
}
+ else if (res.errors & VCOL_AUTO_INC)
+ {
+ /*
+ An auto_increment field may not be used in an expression for
+ a check constraint, a default value or a generated column
+
+ Note that this error condition is not detected during parsing
+ of the statement because the field item does not have a field
+ pointer at that time
+ */
+ my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0),
+ "AUTO_INCREMENT", vcol->get_vcol_type_name(), res.name);
+ DBUG_RETURN(1);
+ }
vcol->flags= res.errors;
if (vcol->flags & VCOL_SESSION_FUNC)
@@ -2879,6 +2896,7 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table,
if (error)
goto end;
+ vcol_storage.vcol_info->set_vcol_type(vcol->get_vcol_type());
vcol_storage.vcol_info->stored_in_db= vcol->stored_in_db;
vcol_storage.vcol_info->name= vcol->name;
vcol_storage.vcol_info->utf8= vcol->utf8;