summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2003-05-03 01:16:56 +0200
committerunknown <serg@serg.mylan>2003-05-03 01:16:56 +0200
commitb33115ecf9f99c1ffee158d193cafa53b438e52c (patch)
tree467d41e9c8504f3a06fc667f9a989394e4a6bce7
parenta20b167cae50d938914f0a024bf31546305d17cb (diff)
downloadmariadb-git-b33115ecf9f99c1ffee158d193cafa53b438e52c.tar.gz
INSERT ... UPDATE ... VALUES()
-rw-r--r--mysql-test/r/insert_update.result8
-rw-r--r--mysql-test/t/insert_update.test2
-rw-r--r--sql/field.cc4
-rw-r--r--sql/field.h4
-rw-r--r--sql/item.cc57
-rw-r--r--sql/item.h29
-rw-r--r--sql/item_sum.cc4
-rw-r--r--sql/sql_acl.cc26
-rw-r--r--sql/sql_insert.cc28
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_select.cc18
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_udf.cc2
-rw-r--r--sql/sql_update.cc8
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/table.cc6
-rw-r--r--sql/table.h7
-rw-r--r--sql/unireg.h12
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> &not_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 */