1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

move away from TIMESTAMP_DNUN_FIELD/TIMESTAMP_DN_FIELD code

use the new approach with Field->default_value expressions.
But keep the old TIMESTAMP_UN_FIELD for ON UPDATE NOW().
This commit is contained in:
Sergei Golubchik
2016-07-24 15:12:54 +02:00
parent 12d2c4fcd0
commit cd51c7fb60
9 changed files with 84 additions and 170 deletions

View File

@@ -4920,12 +4920,12 @@ void Field_double::sql_type(String &res) const
field has NOW() as default and is updated when row changes, else it is
field which has 0 as default value and is not automatically updated.
TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
automatically (TIMESTAMP DEFAULT NOW())
automatically (TIMESTAMP DEFAULT NOW()), not used in Field since 10.2.2
TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
NOW() as default (but it may has 0 or some other const timestamp as
default) (TIMESTAMP ON UPDATE NOW()).
TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on
update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW())
update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW()), not used in Field since 10.2.2
NONE - field which is not auto-set on update with some other than NOW()
default value (TIMESTAMP DEFAULT 0).
@@ -4956,8 +4956,8 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
this field will be automaticly updated on insert.
*/
flags|= TIMESTAMP_FLAG;
if (unireg_check != TIMESTAMP_DN_FIELD)
flags|= ON_UPDATE_NOW_FLAG;
flags|= ON_UPDATE_NOW_FLAG;
DBUG_ASSERT(unireg_check == TIMESTAMP_UN_FIELD);
}
}
@@ -10561,40 +10561,24 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
- The column didn't have a default expression
*/
if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) &&
old_field->ptr != NULL &&
orig_field != NULL &&
!default_value)
old_field->ptr != NULL && orig_field != NULL)
{
bool default_now= false;
if (real_type_with_now_as_default(sql_type))
{
// The SQL type of the new field allows a function default:
default_now= orig_field->has_insert_default_function();
bool update_now= orig_field->has_update_default_function();
if (orig_field->has_update_default_function())
unireg_check= Field::TIMESTAMP_UN_FIELD;
if (default_now && update_now)
unireg_check= Field::TIMESTAMP_DNUN_FIELD;
else if (default_now)
unireg_check= Field::TIMESTAMP_DN_FIELD;
else if (update_now)
unireg_check= Field::TIMESTAMP_UN_FIELD;
}
if (!default_now) // Give a constant default
/* Get the value from default_values */
const uchar *dv= orig_field->table->s->default_values;
if (!default_value && !orig_field->is_null_in_record(dv))
{
/* Get the value from default_values */
const uchar *dv= orig_field->table->s->default_values;
if (!orig_field->is_null_in_record(dv))
{
StringBuffer<MAX_FIELD_WIDTH> tmp(charset);
String *res= orig_field->val_str(&tmp, orig_field->ptr_in_record(dv));
char *pos= (char*) thd->strmake(res->ptr(), res->length());
default_value= new (thd->mem_root) Virtual_column_info();
default_value->expr_str.str= pos;
default_value->expr_str.length= res->length();
default_value->expr_item=
new (thd->mem_root) Item_string(thd, pos, res->length(), charset);
default_value->utf8= 0;
}
StringBuffer<MAX_FIELD_WIDTH> tmp(charset);
String *res= orig_field->val_str(&tmp, orig_field->ptr_in_record(dv));
char *pos= (char*) thd->strmake(res->ptr(), res->length());
default_value= new (thd->mem_root) Virtual_column_info();
default_value->expr_str.str= pos;
default_value->expr_str.length= res->length();
default_value->expr_item=
new (thd->mem_root) Item_string(thd, pos, res->length(), charset);
default_value->utf8= 0;
}
}
}

View File

@@ -473,20 +473,6 @@ inline bool is_temporal_type_with_date(enum_field_types type)
}
/**
Tests if a field real type can have "DEFAULT CURRENT_TIMESTAMP"
@param type Field type, as returned by field->real_type().
@retval true If field real type can have "DEFAULT CURRENT_TIMESTAMP".
@retval false If field real type can not have "DEFAULT CURRENT_TIMESTAMP".
*/
inline bool real_type_with_now_as_default(enum_field_types type)
{
return type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_TIMESTAMP2 ||
type == MYSQL_TYPE_DATETIME || type == MYSQL_TYPE_DATETIME2;
}
/**
Recognizer for concrete data type (called real_type for some reason),
returning true if it is one of the TIMESTAMP types.
@@ -928,16 +914,9 @@ public:
}
virtual void set_default();
bool has_insert_default_function() const
{
return (unireg_check == TIMESTAMP_DN_FIELD ||
unireg_check == TIMESTAMP_DNUN_FIELD);
}
bool has_update_default_function() const
{
return (unireg_check == TIMESTAMP_UN_FIELD ||
unireg_check == TIMESTAMP_DNUN_FIELD);
return unireg_check == TIMESTAMP_UN_FIELD;
}
/*
@@ -2377,21 +2356,7 @@ public:
void sql_type(String &str) const;
bool zero_pack() const { return 0; }
virtual int set_time();
virtual void set_default()
{
if (has_insert_default_function())
set_time();
else
Field::set_default();
}
virtual void set_explicit_default(Item *value);
virtual int evaluate_insert_default_function()
{
int res= 0;
if (has_insert_default_function())
res= set_time();
return res;
}
virtual int evaluate_update_default_function()
{
int res= 0;
@@ -2821,20 +2786,6 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return Field_datetime::get_TIME(ltime, ptr, fuzzydate); }
virtual int set_time();
virtual void set_default()
{
if (has_insert_default_function())
set_time();
else
Field::set_default();
}
virtual int evaluate_insert_default_function()
{
int res= 0;
if (has_insert_default_function())
res= set_time();
return res;
}
virtual int evaluate_update_default_function()
{
int res= 0;
@@ -3813,9 +3764,7 @@ public:
bool has_default_function() const
{
return (unireg_check == Field::TIMESTAMP_DN_FIELD ||
unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
unireg_check == Field::TIMESTAMP_UN_FIELD ||
return (unireg_check == Field::TIMESTAMP_UN_FIELD ||
unireg_check == Field::NEXT_NUMBER);
}

View File

@@ -956,8 +956,7 @@ bool Item_field::check_field_expression_processor(void *arg)
{
if (field->flags & NO_DEFAULT_VALUE_FLAG)
return 0;
if ((field->default_value && field->default_value->flags)
|| field->has_insert_default_function() || field->vcol_info)
if ((field->default_value && field->default_value->flags) || field->vcol_info)
{
Field *org_field= (Field*) arg;
if (field == org_field ||
@@ -8258,7 +8257,7 @@ void Item_default_value::print(String *str, enum_query_type query_type)
void Item_default_value::calculate()
{
if (field->default_value || field->has_insert_default_function())
if (field->default_value)
field->set_default();
}

View File

@@ -2489,8 +2489,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
(*field)->default_value= vcol;
*dfield_ptr++= *field;
}
if ((*field)->has_insert_default_function() ||
(*field)->has_update_default_function())
else
if ((*field)->has_update_default_function())
*dfield_ptr++= *field;
}
if (vfield)

View File

@@ -1634,20 +1634,11 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value,
bool quoted)
{
bool has_default;
bool has_now_default;
enum enum_field_types field_type= field->type();
/*
We are using CURRENT_TIMESTAMP instead of NOW because it is
more standard
*/
has_now_default= field->has_insert_default_function();
has_default= (field->default_value ||
(!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
field->unireg_check != Field::NEXT_NUMBER &&
!((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
&& has_now_default)));
field->unireg_check != Field::NEXT_NUMBER));
def_value->length(0);
if (has_default)
@@ -1662,17 +1653,14 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value,
field->default_value->expr_str.length);
def_value->append(')');
}
else if (field->unireg_check)
def_value->append(field->default_value->expr_str.str,
field->default_value->expr_str.length);
else
def_value->set(field->default_value->expr_str.str,
field->default_value->expr_str.length,
&my_charset_utf8mb4_general_ci);
}
else if (has_now_default)
{
def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
if (field->decimals() > 0)
def_value->append_parenthesized(field->decimals());
}
else if (!field->is_null())
{ // Not null by default
char tmp[MAX_FIELD_WIDTH];
@@ -1704,13 +1692,13 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value,
if (quoted)
append_unescaped(def_value, def_val.ptr(), def_val.length());
else
def_value->append(def_val.ptr(), def_val.length());
def_value->move(def_val);
}
else if (quoted)
def_value->append(STRING_WITH_LEN("''"));
def_value->set(STRING_WITH_LEN("''"), system_charset_info);
}
else if (field->maybe_null() && quoted)
def_value->append(STRING_WITH_LEN("NULL")); // Null as default
def_value->set(STRING_WITH_LEN("NULL"), system_charset_info); // Null as default
else
return 0;
@@ -1797,8 +1785,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
const char *alias;
String type(tmp, sizeof(tmp), system_charset_info);
String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
String type;
String def_value;
Field **ptr,*field;
uint primary_key;
KEY *key_info;
@@ -1891,12 +1879,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" "));
append_identifier(thd,packet,field->field_name, strlen(field->field_name));
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp)
type.set(tmp, sizeof(tmp), system_charset_info);
else
type.set_charset(system_charset_info);
type.set(tmp, sizeof(tmp), system_charset_info);
field->sql_type(type);
packet->append(type.ptr(), type.length(), system_charset_info);
@@ -1943,6 +1927,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" NULL"));
}
def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info);
if (get_field_default_value(thd, field, &def_value, 1))
{
packet->append(STRING_WITH_LEN(" DEFAULT "));

View File

@@ -9670,8 +9670,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
Old fields keep their current values, and therefore should not be
present in the set of autoupdate fields.
*/
if ((*ptr)->default_value ||
((*ptr)->has_insert_default_function()))
if ((*ptr)->default_value)
{
*(dfield_ptr++)= *ptr;
++to->s->default_fields;

View File

@@ -66,7 +66,7 @@ LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
Keyword added as a prefix when parsing the defining expression for a
virtual column read from the column definition saved in the frm file
*/
LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
static LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
static int64 last_table_id;
@@ -1551,6 +1551,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
LEX_STRING comment;
Virtual_column_info *vcol_info= 0;
uint gis_length, gis_decimals, srid= 0;
Field::utype unireg_check;
if (new_frm_ver >= 3)
{
@@ -1766,22 +1767,36 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
swap_variables(uint, null_bit_pos, mysql57_vcol_null_bit_pos);
}
/* Convert pre-10.2.2 timestamps to use Field::default_value */
unireg_check= (Field::utype) MTYP_TYPENR(unireg_type);
if (unireg_check == Field::TIMESTAMP_DNUN_FIELD)
unireg_check= Field::TIMESTAMP_UN_FIELD;
if (unireg_check == Field::TIMESTAMP_DN_FIELD)
unireg_check= Field::NONE;
*field_ptr= reg_field=
make_field(share, &share->mem_root, record+recpos,
(uint32) field_length,
null_pos, null_bit_pos,
pack_flag,
field_type,
charset,
geom_type, srid,
(Field::utype) MTYP_TYPENR(unireg_type),
(interval_nr ?
share->intervals+interval_nr-1 :
(TYPELIB*) 0),
make_field(share, &share->mem_root, record+recpos, (uint32) field_length,
null_pos, null_bit_pos, pack_flag, field_type, charset,
geom_type, srid, unireg_check,
(interval_nr ? share->intervals+interval_nr-1 : NULL),
share->fieldnames.type_names[i]);
if (!reg_field) // Not supported field type
goto err;
if (unireg_check != (Field::utype) MTYP_TYPENR(unireg_type))
{
char buf[32];
if (reg_field->decimals())
my_snprintf(buf, sizeof(buf), "CURRENT_TIMESTAMP(%d)", reg_field->decimals());
else
strmov(buf, "CURRENT_TIMESTAMP");
reg_field->default_value= new (&share->mem_root) Virtual_column_info();
reg_field->default_value->stored_in_db= 1;
thd->make_lex_string(&reg_field->default_value->expr_str, buf, strlen(buf));
share->default_expressions++;
}
reg_field->field_index= i;
reg_field->comment=comment;
reg_field->vcol_info= vcol_info;
@@ -1821,13 +1836,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (share->stored_rec_length>=recpos)
share->stored_rec_length= recpos-1;
}
if (reg_field->has_insert_default_function())
has_insert_default_function= 1;
if (reg_field->has_update_default_function())
{
has_update_default_function= 1;
if (reg_field->has_insert_default_function() ||
reg_field->has_update_default_function())
share->default_fields++;
if (!reg_field->default_value)
share->default_fields++;
}
}
*field_ptr=0; // End marker
/* Sanity checks: */
@@ -2213,16 +2227,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
case 1: // Generated stored field
vcol_info->stored_in_db= 1;
DBUG_ASSERT(!reg_field->vcol_info);
reg_field->vcol_info= vcol_info;
share->virtual_fields++;
share->virtual_stored_fields++; // For insert/load data
break;
case 2: // Default expression
vcol_info->stored_in_db= 1;
DBUG_ASSERT(!reg_field->default_value);
reg_field->default_value= vcol_info;
share->default_expressions++;
break;
case 3: // Field check constraint
DBUG_ASSERT(!reg_field->check_constraint);
reg_field->check_constraint= vcol_info;
share->field_check_constraints++;
break;
@@ -2693,14 +2710,10 @@ Virtual_column_info *unpack_vcol_info_from_frm(THD *thd,
vcol_expr->length +
parse_vcol_keyword.length + 3)))
DBUG_RETURN(0);
memcpy(vcol_expr_str,
(char*) parse_vcol_keyword.str,
parse_vcol_keyword.length);
memcpy(vcol_expr_str, parse_vcol_keyword.str, parse_vcol_keyword.length);
str_len= parse_vcol_keyword.length;
vcol_expr_str[str_len++]= '(';
memcpy(vcol_expr_str + str_len,
(char*) vcol_expr->str,
vcol_expr->length);
memcpy(vcol_expr_str + str_len, vcol_expr->str, vcol_expr->length);
str_len+= vcol_expr->length;
vcol_expr_str[str_len++]= ')';
vcol_expr_str[str_len++]= 0;
@@ -3045,8 +3058,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
*(dfield_ptr++)= *field_ptr;
}
else
if ((field->has_insert_default_function() ||
field->has_update_default_function()))
if (field->has_update_default_function())
*(dfield_ptr++)= *field_ptr;
}
@@ -6275,7 +6287,7 @@ void TABLE::mark_columns_needed_for_update()
to compare records and detect data change.
*/
if ((file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
default_field && has_default_function(true))
default_field && s->has_update_default_function)
bitmap_union(read_set, write_set);
DBUG_VOID_RETURN;
}
@@ -6573,17 +6585,13 @@ void TABLE::mark_default_fields_for_write(bool is_insert)
for (field_ptr= default_field; *field_ptr; field_ptr++)
{
field= (*field_ptr);
if (field->default_value)
if (is_insert && field->default_value)
{
if (is_insert)
{
bitmap_set_bit(write_set, field->field_index);
field->default_value->expr_item->
walk(&Item::register_field_in_read_map, 1, 0);
}
bitmap_set_bit(write_set, field->field_index);
field->default_value->expr_item->
walk(&Item::register_field_in_read_map, 1, 0);
}
else if ((is_insert && field->has_insert_default_function()) ||
(!is_insert && field->has_update_default_function()))
else if (!is_insert && field->has_update_default_function())
bitmap_set_bit(write_set, field->field_index);
}
DBUG_VOID_RETURN;

View File

@@ -685,7 +685,6 @@ struct TABLE_SHARE
bool virtual_stored_fields;
bool check_set_initialized;
bool has_update_default_function;
bool has_insert_default_function;
ulong table_map_id; /* for row-based replication */
/*
@@ -1311,18 +1310,6 @@ public:
void mark_columns_used_by_check_constraints(void);
void mark_check_constraint_columns_for_read(void);
int verify_constraints(bool ignore_failure);
/**
Check if a table has a default function either for INSERT or UPDATE-like
operation
@retval true there is a default function
@retval false there is no default function
*/
inline bool has_default_function(bool is_update)
{
return (is_update ?
s->has_update_default_function :
s->has_insert_default_function);
}
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{

View File

@@ -1039,7 +1039,10 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
field->sql_type,
field->charset,
field->geom_type, field->srid,
field->unireg_check,
field->unireg_check == Field::TIMESTAMP_DNUN_FIELD
? Field::TIMESTAMP_UN_FIELD
: field->unireg_check == Field::TIMESTAMP_DN_FIELD
? Field::NONE : field->unireg_check,
field->save_interval ? field->save_interval :
field->interval,
field->field_name);