diff options
author | unknown <knielsen@knielsen-hq.org> | 2012-12-18 15:01:58 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2012-12-18 15:01:58 +0100 |
commit | 701419b02f12688188a7d4183523e0f5ee9ae09a (patch) | |
tree | 9cad9901bbf188c5ab30aeb31f10c71f61921312 /sql/field.cc | |
parent | 4923d19b7c3c4c034f70ac1411837afa75c4b6ad (diff) | |
parent | 6c3de76ad5cb8683ab8b049e0bbba670115d304a (diff) | |
download | mariadb-git-701419b02f12688188a7d4183523e0f5ee9ae09a.tar.gz |
Merge MariaDB 10.0-base to MariaDB 10.0
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 213 |
1 files changed, 116 insertions, 97 deletions
diff --git a/sql/field.cc b/sql/field.cc index e0ecd6ab74f..a18c72119be 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -50,11 +50,6 @@ Instansiate templates and static variables *****************************************************************************/ -#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION -template class List<Create_field>; -template class List_iterator<Create_field>; -#endif - static const char *zero_timestamp="0000-00-00 00:00:00.000000"; /* number of bytes to store second_part part of the TIMESTAMP(N) */ @@ -1817,6 +1812,10 @@ Field *Field::new_field(MEM_ROOT *root, TABLE *new_table, tmp->key_start.init(0); tmp->part_of_key.init(0); tmp->part_of_sortkey.init(0); + /* + TODO: it is not clear why this method needs to reset unireg_check. + Try not to reset it, or explain why it needs to be reset. + */ tmp->unireg_check= Field::NONE; tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); @@ -4369,16 +4368,10 @@ void Field_double::sql_type(String &res) const 2038-01-01 00:00:00 UTC stored as number of seconds since Unix Epoch in UTC. - Up to one of timestamps columns in the table can be automatically - set on row update and/or have NOW() as default value. - TABLE::timestamp_field points to Field object for such timestamp with - auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this - field, and is used by handler code which performs updates required. - Actually SQL-99 says that we should allow niladic functions (like NOW()) - as defaults for any field. Current limitations (only NOW() and only - for one TIMESTAMP field) are because of restricted binary .frm format - and should go away in the future. + as defaults for any field. The current limitation (only NOW() and only + for TIMESTAMP and DATETIME fields) are because of restricted binary .frm + format and should go away in the future. Also because of this limitation of binary .frm format we use 5 different unireg_check values with TIMESTAMP field to distinguish various cases of @@ -4419,10 +4412,12 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, { /* For 4.0 MYD and 4.0 InnoDB compatibility */ flags|= UNSIGNED_FLAG | BINARY_FLAG; - if (unireg_check != NONE && !share->timestamp_field) + if (unireg_check != NONE) { - /* This timestamp has auto-update */ - share->timestamp_field= this; + /* + We mark the flag with TIMESTAMP_FLAG to indicate to the client that + this field will be automaticly updated on insert. + */ flags|= TIMESTAMP_FLAG; if (unireg_check != TIMESTAMP_DN_FIELD) flags|= ON_UPDATE_NOW_FLAG; @@ -4430,40 +4425,6 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg, } -/** - Get auto-set type for TIMESTAMP field. - - Returns value indicating during which operations this TIMESTAMP field - should be auto-set to current timestamp. -*/ -timestamp_auto_set_type Field_timestamp::get_auto_set_type() const -{ - switch (unireg_check) - { - case TIMESTAMP_DN_FIELD: - return TIMESTAMP_AUTO_SET_ON_INSERT; - case TIMESTAMP_UN_FIELD: - return TIMESTAMP_AUTO_SET_ON_UPDATE; - case TIMESTAMP_OLD_FIELD: - /* - Although we can have several such columns in legacy tables this - function should be called only for first of them (i.e. the one - having auto-set property). - */ - DBUG_ASSERT(table->timestamp_field == this); - /* Fall-through */ - case TIMESTAMP_DNUN_FIELD: - return TIMESTAMP_AUTO_SET_ON_BOTH; - default: - /* - Normally this function should not be called for TIMESTAMPs without - auto-set property. - */ - DBUG_ASSERT(0); - return TIMESTAMP_NO_AUTO_SET; - } -} - my_time_t Field_timestamp::get_timestamp(ulong *sec_part) const { ASSERT_COLUMN_MARKED_FOR_READ; @@ -4713,6 +4674,34 @@ int Field_timestamp::set_time() return 0; } +/** + Mark the field as having an explicit default value. + + @param value if available, the value that the field is being set to + + @note + Fields that have an explicit default value should not be updated + automatically via the DEFAULT or ON UPDATE functions. The functions + that deal with data change functionality (INSERT/UPDATE/LOAD), + determine if there is an explicit value for each field before performing + the data change, and call this method to mark the field. + + For timestamp columns, the only case where a column is not marked + as been given a value are: + - It's explicitly assigned with DEFAULT + - We assign NULL to a timestamp field that is defined as NOT NULL. + This is how MySQL has worked since it's start. +*/ + +void Field_timestamp::set_explicit_default(Item *value) +{ + if (((value->type() == Item::DEFAULT_VALUE_ITEM && + !((Item_default_value*)value)->arg) || + (!maybe_null() && value->is_null()))) + return; + set_has_explicit_value(); +} + void Field_timestamp_hires::sql_type(String &res) const { CHARSET_INFO *cs=res.charset(); @@ -5834,6 +5823,20 @@ void Field_datetime::sql_type(String &res) const res.set_ascii(STRING_WITH_LEN("datetime")); } + +int Field_datetime::set_time() +{ + THD *thd= table->in_use; + MYSQL_TIME now_time; + thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start()); + now_time.second_part= thd->query_start_sec_part(); + set_notnull(); + store_TIME(&now_time); + thd->time_zone_used= 1; + return 0; +} + + void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime) { ulonglong packed= sec_part_shift(pack_time(ltime), dec); @@ -8855,16 +8858,37 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, { uint sign_len, allowed_type_modifier= 0; ulong max_field_charlength= MAX_FIELD_CHARLENGTH; + const bool on_update_is_function= + (fld_on_update_value != NULL && + fld_on_update_value->type() == Item::FUNC_ITEM); DBUG_ENTER("Create_field::init()"); field= 0; field_name= fld_name; - def= fld_default_value; flags= fld_type_modifier; option_list= create_opt; - unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ? - Field::NEXT_NUMBER : Field::NONE); + + if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM) + { + /* There is a function default for insertions. */ + def= NULL; + unireg_check= (on_update_is_function ? + Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates. + Field::TIMESTAMP_DN_FIELD); // only for insertions. + } + else + { + /* No function default for insertions. Either NULL or a constant. */ + def= fld_default_value; + if (on_update_is_function) + unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates + else + unireg_check= ((fld_type_modifier & AUTO_INCREMENT_FLAG) != 0 ? + Field::NEXT_NUMBER : // Automatic increment. + Field::NONE); + } + decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0; if (decimals >= NOT_FIXED_DEC) { @@ -9085,44 +9109,6 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, } length+= MAX_DATETIME_WIDTH + (length ? 1 : 0); flags|= UNSIGNED_FLAG; - - if (fld_default_value) - { - /* Grammar allows only NOW() value for ON UPDATE clause */ - if (fld_default_value->type() == Item::FUNC_ITEM && - ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC) - { - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD: - Field::TIMESTAMP_DN_FIELD); - /* - We don't need default value any longer moreover it is dangerous. - Everything handled by unireg_check further. - */ - def= 0; - } - else - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD: - Field::NONE); - } - else - { - /* - If we have default TIMESTAMP NOT NULL column without explicit DEFAULT - or ON UPDATE values then for the sake of compatiblity we should treat - this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't - have another TIMESTAMP column with auto-set option before this one) - or DEFAULT 0 (in other cases). - So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will - replace this value by TIMESTAMP_DNUN_FIELD or NONE later when - information about all TIMESTAMP fields in table will be availiable. - - If we have TIMESTAMP NULL column without explicit DEFAULT value - we treat it as having DEFAULT NULL attribute. - */ - unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD : - (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD : - Field::NONE)); - } break; case MYSQL_TYPE_DATE: /* We don't support creation of MYSQL_TYPE_DATE anymore */ @@ -9588,11 +9574,18 @@ Create_field::Create_field(Field *old_field,Field *orig_field) def=0; char_length= length; - if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && - old_field->ptr && orig_field && - (sql_type != MYSQL_TYPE_TIMESTAMP || /* set def only if */ - old_field->table->timestamp_field != old_field || /* timestamp field */ - unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */ + /* + Copy the default value from the column object orig_field, if: + 1) The column has a constant default value. + 2) The column type is not a BLOB type. + 3) The original column (old_field) was properly initialized with a record + buffer pointer. + 4) The original column doesn't have a default function to auto-initialize + the column on INSERT + */ + if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && // 1) 2) + old_field->ptr && orig_field && // 3) + !old_field->has_insert_default_function()) // 4) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff), charset); @@ -9776,3 +9769,29 @@ key_map Field::get_possible_keys() return (table->pos_in_table_list->is_materialized_derived() ? part_of_key : key_start); } + + +/** + Mark the field as having an explicit default value. + + @param value if available, the value that the field is being set to + + @note + Fields that have an explicit default value should not be updated + automatically via the DEFAULT or ON UPDATE functions. The functions + that deal with data change functionality (INSERT/UPDATE/LOAD), + determine if there is an explicit value for each field before performing + the data change, and call this method to mark the field. + + If the 'value' parameter is NULL, then the field is marked unconditionally + as having an explicit value. If 'value' is not NULL, then it can be further + analyzed to check if it really should count as a value. +*/ + +void Field::set_explicit_default(Item *value) +{ + if (value->type() == Item::DEFAULT_VALUE_ITEM && + !((Item_default_value*)value)->arg) + return; + set_has_explicit_value(); +} |