diff options
author | unknown <serg@serg.mylan> | 2003-05-03 01:16:56 +0200 |
---|---|---|
committer | unknown <serg@serg.mylan> | 2003-05-03 01:16:56 +0200 |
commit | b33115ecf9f99c1ffee158d193cafa53b438e52c (patch) | |
tree | 467d41e9c8504f3a06fc667f9a989394e4a6bce7 | |
parent | a20b167cae50d938914f0a024bf31546305d17cb (diff) | |
download | mariadb-git-b33115ecf9f99c1ffee158d193cafa53b438e52c.tar.gz |
INSERT ... UPDATE ... VALUES()
-rw-r--r-- | mysql-test/r/insert_update.result | 8 | ||||
-rw-r--r-- | mysql-test/t/insert_update.test | 2 | ||||
-rw-r--r-- | sql/field.cc | 4 | ||||
-rw-r--r-- | sql/field.h | 4 | ||||
-rw-r--r-- | sql/item.cc | 57 | ||||
-rw-r--r-- | sql/item.h | 29 | ||||
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 26 | ||||
-rw-r--r-- | sql/sql_insert.cc | 28 | ||||
-rw-r--r-- | sql/sql_load.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_show.cc | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_udf.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 8 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 | ||||
-rw-r--r-- | sql/table.cc | 6 | ||||
-rw-r--r-- | sql/table.h | 7 | ||||
-rw-r--r-- | sql/unireg.h | 12 |
19 files changed, 166 insertions, 67 deletions
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 8cc79564679..068f7c68286 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -48,4 +48,12 @@ a b c 3 4 120 5 0 30 8 9 60 +INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a); +SELECT *, VALUES(a) FROM t1; +a b c VALUES(a) +1 2 10 NULL +3 4 127 NULL +5 0 30 NULL +8 9 60 NULL +2 1 11 NULL DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index f40391554cc..4f19aca8738 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -21,4 +21,6 @@ INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100; SELECT * FROM t1; INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; +INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a); +SELECT *, VALUES(a) FROM t1; DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 0ea206a4fa7..3695268a888 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5462,9 +5462,9 @@ create_field::create_field(Field *old_field,Field *orig_field) char buff[MAX_FIELD_WIDTH],*pos; String tmp(buff,sizeof(buff), charset); - /* Get the value from record[2] (the default value row) */ + /* Get the value from default_values */ my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2); - orig_field->move_field(diff); // Points now at record[2] + orig_field->move_field(diff); // Points now at default_values bool is_null=orig_field->is_real_null(); orig_field->val_str(&tmp,&tmp); orig_field->move_field(-diff); // Back to record[0] diff --git a/sql/field.h b/sql/field.h index 7334ff66dd8..80bfc516ef7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -57,7 +57,7 @@ public: GEOM_GEOMETRYCOLLECTION = 7 }; enum imagetype { itRAW, itMBR}; - + utype unireg_check; uint32 field_length; // Length of field uint16 flags; @@ -83,7 +83,7 @@ public: virtual void reset_fields() {} virtual void set_default() { - my_ptrdiff_t offset = table->default_values() - table->record[0]; + my_ptrdiff_t offset = table->default_values - table->record[0]; memcpy(ptr, ptr + offset, pack_length()); if (null_ptr) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | diff --git a/sql/item.cc b/sql/item.cc index 7dd8392b695..bc6d32731c4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1389,8 +1389,8 @@ bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, if (!def_field) return 1; memcpy(def_field, field_arg->field, field_arg->field->size_of()); - def_field->move_field(def_field->table->default_values() - - def_field->table->record[0]); + def_field->move_field(def_field->table->default_values - + def_field->table->record[0]); set_field(def_field); return 0; } @@ -1407,6 +1407,59 @@ void Item_default_value::print(String *str) str->append(')'); } +bool Item_insert_value::eq(const Item *item, bool binary_cmp) const +{ + return item->type() == INSERT_VALUE_ITEM && + ((Item_default_value *)item)->arg->eq(arg, binary_cmp); +} + + +bool Item_insert_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) +{ + bool res= arg->fix_fields(thd, table_list, items); + if (res) + return res; + /* + arg->type() can be only REF_ITEM or FIELD_ITEM as arg is + a simple_ident in sql_yacc.yy + */ + if (arg->type() == REF_ITEM) + { + Item_ref *ref= (Item_ref *)arg; + if (ref->ref[0]->type() != FIELD_ITEM) + { + return 1; + } + arg= ref->ref[0]; + } + Item_field *field_arg= (Item_field *)arg; + if (field_arg->field->table->insert_values) + { + Field *def_field= (Field*) sql_alloc(field_arg->field->size_of()); + if (!def_field) + return 1; + memcpy(def_field, field_arg->field, field_arg->field->size_of()); + def_field->move_field(def_field->table->insert_values - + def_field->table->record[0]); + set_field(def_field); + } + else + { + Field *field=field_arg->field; + /* charset doesn't matter here, it's to avoid sigsegv only */ + set_field(new Field_null(0,0,Field::NONE,field->field_name,field->table, + default_charset_info)); + } + return 0; +} + +void Item_insert_value::print(String *str) +{ + str->append("VALUE("); + arg->print(str); + str->append(')'); +} + /* If item is a const function, calculate it and return a const item The original item is freed if not returned diff --git a/sql/item.h b/sql/item.h index 4862ad21fbe..3a5a06c3af3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -34,13 +34,13 @@ public: enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, - PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, - FIELD_VARIANCE_ITEM, CONST_ITEM, + PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, + FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; - enum coercion { COER_COERCIBLE=3, COER_IMPLICIT=2, - COER_NOCOLL=1, COER_EXPLICIT=0 }; + enum coercion { COER_COERCIBLE=3, COER_IMPLICIT=2, + COER_NOCOLL=1, COER_EXPLICIT=0 }; String str_value; /* used to store value */ my_string name; /* Name from select */ @@ -201,6 +201,7 @@ public: bool is_null() { return field->is_null(); } Item *get_tmp_table_item(THD *thd); friend class Item_default_value; + friend class Item_insert_value; }; class Item_null :public Item @@ -734,7 +735,7 @@ public: Item *arg; Item_default_value() : Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {} - Item_default_value(Item *a) : + Item_default_value(Item *a) : Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } bool eq(const Item *item, bool binary_cmp) const; @@ -754,6 +755,24 @@ public: table_map used_tables() const { return (table_map)0L; } }; +class Item_insert_value : public Item_field +{ +public: + Item *arg; + Item_insert_value(Item *a) : + Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} + bool eq(const Item *item, bool binary_cmp) const; + bool fix_fields(THD *, struct st_table_list *, Item **); + void set_outer_resolving() { arg->set_outer_resolving(); } + void print(String *str); + virtual bool basic_const_item() const { return true; } + int save_in_field(Field *field, bool no_conversions) + { + return Item_field::save_in_field(field, no_conversions); + } + table_map used_tables() const { return (table_map)0L; } +}; + class Item_cache: public Item { table_map used_table_map; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 653f71e3d79..befcb312164 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -993,7 +993,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), int error; /* The first item->rec_offset bytes are taken care of with - restore_record(table,2) in setup() + restore_record(table,default_values) in setup() */ memcpy(buf + item->rec_offset, key, item->tree->size_of_element); if ((error = item->table->file->write_row(buf))) @@ -1075,7 +1075,7 @@ bool Item_sum_count_distinct::setup(THD *thd) void* cmp_arg; // to make things easier for dump_leaf if we ever have to dump to MyISAM - restore_record(table,2); + restore_record(table,default_values); if (table->fields == 1) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4bed99489de..5ac52032a5f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1281,7 +1281,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user, my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */ DBUG_RETURN(1); /* purecov: deadcode */ } - store_record(table,1); + store_record(table,record[1]); table->field[2]->store(new_password,(uint) strlen(new_password), &my_charset_latin1); if ((error=table->file->update_row(table->record[1],table->record[0]))) { @@ -1372,7 +1372,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, goto end; } old_row_exists = 0; - restore_record(table,2); // cp empty row from record[2] + restore_record(table,default_values); // cp empty row from default_values table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1); table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1); @@ -1380,7 +1380,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, else { old_row_exists = 1; - store_record(table,1); // Save copy for update + store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1); } @@ -1455,7 +1455,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, We should NEVER delete from the user table, as a uses can still use mysqld even if he doesn't have any privileges in the user table! */ - if (cmp_record(table,1) && + if (cmp_record(table,record[1]) && (error=table->file->update_row(table->record[1],table->record[0]))) { // This should never happen table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -1539,7 +1539,7 @@ static int replace_db_table(TABLE *table, const char *db, goto abort; } old_row_exists = 0; - restore_record(table,2); // cp empty row from record[2] + restore_record(table,default_values); // cp empty row from default_values table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); @@ -1547,7 +1547,7 @@ static int replace_db_table(TABLE *table, const char *db, else { old_row_exists = 1; - store_record(table,1); + store_record(table,record[1]); } store_rights=get_rights_for_db(rights); @@ -1827,7 +1827,7 @@ static int replace_column_table(GRANT_TABLE *g_t, continue; /* purecov: inspected */ } old_row_exists = 0; - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record key_restore(table,key,0,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), &my_charset_latin1); } @@ -1841,7 +1841,7 @@ static int replace_column_table(GRANT_TABLE *g_t, else privileges |= tmp; old_row_exists = 1; - store_record(table,1); // copy original row + store_record(table,record[1]); // copy original row } table->field[6]->store((longlong) get_rights_for_column(privileges)); @@ -1895,7 +1895,7 @@ static int replace_column_table(GRANT_TABLE *g_t, { ulong privileges = (ulong) table->field[6]->val_int(); privileges=fix_rights_for_column(privileges); - store_record(table,1); + store_record(table,record[1]); if (privileges & rights) // is in this record the priv to be revoked ?? { @@ -1970,12 +1970,12 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, DBUG_RETURN(-1); /* purecov: deadcode */ } - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); - store_record(table,1); // store at pos 1 + store_record(table,record[1]); // store at pos 1 if (table->file->index_read_idx(table->record[0],0, (byte*) table->field[0]->ptr,0, @@ -1995,7 +1995,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, DBUG_RETURN(-1); /* purecov: deadcode */ } old_row_exists = 0; - restore_record(table,1); // Get saved record + restore_record(table,record[1]); // Get saved record } store_table_rights= get_rights_for_table(rights); @@ -2003,7 +2003,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, if (old_row_exists) { ulong j,k; - store_record(table,1); + store_record(table,record[1]); j = (ulong) table->field[6]->val_int(); k = (ulong) table->field[7]->val_int(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index dcb39f8526f..7418140517c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -184,6 +184,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->proc_info="init"; thd->used_tables=0; values= its++; + + if (duplic == DUP_UPDATE && !table->insert_values) + { + /* it should be allocated before Item::fix_fields() */ + table->insert_values=alloc_root(&table->mem_root, table->rec_buff_length); + if (!table->insert_values) + goto abort; + } + if (check_insert_fields(thd,table,fields,*values,1) || setup_tables(insert_table_list) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) || @@ -248,7 +257,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, { if (fields.elements || !value_count) { - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record if (fill_record(fields,*values)|| thd->net.report_error || check_null_fields(thd,table)) { @@ -264,9 +273,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, else { if (thd->used_tables) // Column used in values() - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record else - table->record[0][0]=table->record[2][0]; // Fix delete marker + table->record[0][0]=table->default_values[0]; // Fix delete marker if (fill_record(table->field,*values) || thd->net.report_error) { if (values_list.elements != 1 && ! thd->net.report_error) @@ -333,7 +342,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->insert_id(id); // For update log else if (table->next_number_field) id=table->next_number_field->val_int(); // Return auto_increment value - + transactional_table= table->file->has_transactions(); log_delayed= (transactional_table || table->tmp_table); if ((info.copied || info.deleted) && (error <= 0 || !transactional_table)) @@ -383,7 +392,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, char buff[160]; if (duplic == DUP_IGNORE) sprintf(buff,ER(ER_INSERT_INFO),info.records, - (lock_type == TL_WRITE_DELAYED) ? 0 : + (lock_type == TL_WRITE_DELAYED) ? 0 : info.records-info.copied, thd->cuted_fields); else @@ -392,12 +401,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff); } free_underlaid_joins(thd, &thd->lex.select_lex); + table->insert_values=0; DBUG_RETURN(0); abort: if (lock_type == TL_WRITE_DELAYED) end_delayed_insert(thd); free_underlaid_joins(thd, &thd->lex.select_lex); + table->insert_values=0; DBUG_RETURN(-1); } @@ -482,7 +493,8 @@ int write_record(TABLE *table,COPY_INFO *info) that matches, is updated. If update causes a conflict again, an error is returned */ - restore_record(table,1); + store_record(table,insert_values); + restore_record(table,record[1]); if (fill_record(*info->update_fields,*info->update_values)) goto err; if ((error=table->file->update_row(table->record[1],table->record[0]))) @@ -1349,7 +1361,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) if (check_insert_fields(thd,table,*fields,values,1)) DBUG_RETURN(1); - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record table->next_number_field=table->found_next_number_field; thd->count_cuted_fields=1; // calc cuted fields thd->cuted_fields=0; @@ -1480,7 +1492,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } table->next_number_field=table->found_next_number_field; - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record thd->count_cuted_fields=1; // count warnings thd->cuted_fields=0; if (info.handle_duplicates == DUP_IGNORE || diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 3c43c3d9e3a..a68eada0025 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -238,7 +238,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, lf_info.log_delayed= log_delayed; read_info.set_io_cache_arg((void*) &lf_info); } - restore_record(table,2); + restore_record(table,default_values); thd->count_cuted_fields=1; /* calc cuted fields */ thd->cuted_fields=0L; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 18768099f0f..5cf48793510 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4376,7 +4376,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME)))) goto err; table->record[1]= table->record[0]+alloc_length; - table->record[2]= table->record[1]+alloc_length; + table->default_values= table->record[1]+alloc_length; } copy_func[0]=0; // End marker @@ -4450,7 +4450,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, param->copy_field_end=copy; param->recinfo=recinfo; - store_record(table,2); // Make empty default record + store_record(table,default_values); // Make empty default record if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit table->max_rows= ~(ha_rows) 0; @@ -5053,7 +5053,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) if (!found && on_expr) { // OUTER JOIN - restore_record(join_tab->table,2); // Make empty record + restore_record(join_tab->table,default_values); // Make empty record mark_as_null_row(join_tab->table); // For group by without error if (!select_cond || select_cond->val_int()) { @@ -5199,10 +5199,10 @@ join_read_system(JOIN_TAB *tab) empty_record(table); // Make empty record return -1; } - store_record(table,1); + store_record(table,record[1]); } else if (!table->status) // Only happens with left join - restore_record(table,1); // restore old record + restore_record(table,record[1]); // restore old record table->null_row=0; return table->status ? -1 : 0; } @@ -5239,12 +5239,12 @@ join_read_const(JOIN_TAB *tab) } return -1; } - store_record(table,1); + store_record(table,record[1]); } else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join { table->status=0; - restore_record(table,1); // restore old record + restore_record(table,record[1]); // restore old record } table->null_row=0; return table->status ? -1 : 0; @@ -5841,7 +5841,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), join->tmp_table_param.group_buff,0, HA_READ_KEY_EXACT)) { /* Update old record */ - restore_record(table,1); + restore_record(table,record[1]); update_tmptable_sum_func(join->sum_funcs,table); if ((error=table->file->update_row(table->record[1], table->record[0]))) @@ -5910,7 +5910,7 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */ } - restore_record(table,1); + restore_record(table,record[1]); update_tmptable_sum_func(join->sum_funcs,table); if ((error=table->file->update_row(table->record[1], table->record[0]))) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8d6eccae87a..2b8982f2484 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -694,7 +694,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, if (protocol->send_records_num(&field_list, (ulonglong)file->records) || protocol->send_fields(&field_list,0)) DBUG_RETURN(1); - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record Field **ptr,*field; String *packet= &thd->packet; @@ -959,7 +959,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) !wild_case_compare(system_charset_info, field->field_name,wild)) field_list.push_back(new Item_field(field)); } - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record if (thd->protocol->send_fields(&field_list,2)) DBUG_VOID_RETURN; net_flush(&thd->net); @@ -1041,7 +1041,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) DBUG_ENTER("store_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record List<Item> field_list; char tmp[MAX_FIELD_WIDTH]; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8d216f121ab..9e8cefee223 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1762,7 +1762,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } /* Full alter table */ - restore_record(table,2); // Empty record for DEFAULT + restore_record(table,default_values); // Empty record for DEFAULT List_iterator<Alter_drop> drop_it(drop_list); List_iterator<create_field> def_it(fields); List_iterator<Alter_column> alter_it(alter_list); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 42f4dddea8d..d191550f396 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -429,7 +429,7 @@ int mysql_create_function(THD *thd,udf_func *udf) if (!(table = open_ltable(thd,&tables,TL_WRITE))) goto err; - restore_record(table,2); // Get default values for fields + restore_record(table,default_values); // Get default values for fields table->field[0]->store(u_d->name.str, u_d->name.length, system_charset_info); table->field[1]->store((longlong) u_d->returns); table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), system_charset_info); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 50fdfac7087..7c5983a0362 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -30,7 +30,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields); static bool compare_record(TABLE *table, ulong query_id) { if (!table->blob_fields) - return cmp_record(table,1); + return cmp_record(table,record[1]); /* Compare null bits */ if (memcmp(table->null_flags, table->null_flags+table->rec_buff_length, @@ -288,7 +288,7 @@ int mysql_update(THD *thd, { if (!(select && select->skipp_record())) { - store_record(table,1); + store_record(table,record[1]); if (fill_record(fields,values) || thd->net.report_error) break; /* purecov: inspected */ found++; @@ -731,7 +731,7 @@ bool multi_update::send_data(List<Item> ¬_used_values) if (table == table_to_update) { table->status|= STATUS_UPDATED; - store_record(table,1); + store_record(table,record[1]); if (fill_record(*fields_for_table[offset], *values_for_table[offset])) DBUG_RETURN(1); found++; @@ -863,7 +863,7 @@ int multi_update::do_updates(bool from_send_error) if ((local_error= table->file->rnd_pos(table->record[0], ref_pos))) goto err; table->status|= STATUS_UPDATED; - store_record(table,1); + store_record(table,record[1]); /* Copy data from temporary table to current table */ for (copy_field_ptr=copy_field; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 71035a75084..acbe07be332 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2174,12 +2174,12 @@ simple_expr: | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); - Lex->uncacheable();; + Lex->uncacheable(); } | '@' ident_or_text { $$= new Item_func_get_user_var($2); - Lex->uncacheable();; + Lex->uncacheable(); } | '@' '@' opt_var_ident_type ident_or_text { @@ -2227,6 +2227,8 @@ simple_expr: { $$= new Item_func_conv_charset3($3,$7,$5); } | DEFAULT '(' simple_ident ')' { $$= new Item_default_value($3); } + | VALUES '(' simple_ident ')' + { $$= new Item_insert_value($3); } | FUNC_ARG0 '(' ')' { $$= ((Item*(*)(void))($1.symbol->create_func))();} | FUNC_ARG1 '(' expr ')' @@ -2276,7 +2278,7 @@ simple_expr: | ENCRYPT '(' expr ')' { $$= new Item_func_encrypt($3); - Lex->uncacheable();; + Lex->uncacheable(); } | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } | DECODE_SYM '(' expr ',' TEXT_STRING_literal ')' diff --git a/sql/table.cc b/sql/table.cc index fda1fcb36e4..3aed75c7ac6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -267,6 +267,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, (ulong) (uint2korr(head+6)+uint2korr(head+14)), MYF(MY_NABP))) goto err_not_open; /* purecov: inspected */ + /* HACK: table->record[2] is used instead of table->default_values here */ for (i=0 ; i < records ; i++, record+=rec_buff_length) { outparam->record[i]=(byte*) record; @@ -276,11 +277,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (records == 2) { /* fix for select */ - outparam->record[2]=outparam->record[1]; + outparam->default_values=outparam->record[1]; if (db_stat & HA_READ_ONLY) outparam->record[1]=outparam->record[0]; /* purecov: inspected */ } - + outparam->insert_values=0; /* for INSERT ... UPDATE */ + VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open; if (crypted) diff --git a/sql/table.h b/sql/table.h index 55bc48db604..2aefe23cb2f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -65,7 +65,9 @@ struct st_table { Field **field; /* Pointer to fields */ Field_blob **blob_field; /* Pointer to blob fields */ HASH name_hash; /* hash of field names */ - byte *record[3]; /* Pointer to records */ + byte *record[2]; /* Pointer to records */ + byte *default_values; /* record with default values for INSERT */ + byte *insert_values; /* used by INSERT ... UPDATE */ uint fields; /* field count */ uint reclength; /* Recordlength */ uint rec_buff_length; @@ -144,10 +146,9 @@ struct st_table { struct st_table_list *pos_in_table_list; }; /* number of select if it is derived table */ - uint derived_select_number; + uint derived_select_number; THD *in_use; /* Which thread uses this */ struct st_table *next,*prev; - byte *default_values() { return record[2]; } }; diff --git a/sql/unireg.h b/sql/unireg.h index 9430329e67a..e89bc71eeb0 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -103,13 +103,13 @@ #define SPECIAL_SAFE_MODE 2048 /* Extern defines */ -#define store_record(A,B) bmove_allign((A)->record[B],(A)->record[0],(size_t) (A)->reclength) -#define restore_record(A,B) bmove_allign((A)->record[0],(A)->record[B],(size_t) (A)->reclength) -#define cmp_record(A,B) memcmp((A)->record[0],(A)->record[B],(size_t) (A)->reclength) +#define store_record(A,B) bmove_allign((A)->B,(A)->record[0],(size_t) (A)->reclength) +#define restore_record(A,B) bmove_allign((A)->record[0],(A)->B,(size_t) (A)->reclength) +#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->reclength) #define empty_record(A) { \ -bmove_allign((A)->record[0],(A)->record[2],(size_t) (A)->reclength); \ -bfill((A)->null_flags,(A)->null_bytes,255);\ -} + restore_record((A),default_values); \ + bfill((A)->null_flags,(A)->null_bytes,255);\ + } /* Defines for use with openfrm, openprt and openfrd */ |