summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2005-06-22 20:59:34 +0200
committerunknown <msvensson@neptunus.(none)>2005-06-22 20:59:34 +0200
commit6a8945e33293b1091da9fd6b0232ca5a8af3a338 (patch)
treec494d9d92a94978236e21ab8bf4aa570bf161119 /sql
parent406673b0b320d66562e2778323c59034c22be225 (diff)
parent31d07866873631f79177fb1277bacfec62062c80 (diff)
downloadmariadb-git-6a8945e33293b1091da9fd6b0232ca5a8af3a338.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into neptunus.(none):/home/msvensson/mysql/mysql-4.1 sql/sql_base.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item.h11
-rw-r--r--sql/item_buff.cc4
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_parse.cc27
-rw-r--r--sql/sql_yacc.yy15
7 files changed, 64 insertions, 23 deletions
diff --git a/sql/item.cc b/sql/item.cc
index c96794ff482..9c5bf499d11 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -65,6 +65,7 @@ Item::Item():
place == IN_HAVING)
thd->lex->current_select->select_n_having_items++;
}
+ item_flags= 0;
}
/*
@@ -83,7 +84,8 @@ Item::Item(THD *thd, Item *item):
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
fixed(item->fixed),
- collation(item->collation)
+ collation(item->collation),
+ item_flags(item->item_flags)
{
next= thd->free_list; // Put in free list
thd->free_list= this;
diff --git a/sql/item.h b/sql/item.h
index 8de2adeb730..82ab5a66cfb 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -107,6 +107,11 @@ public:
typedef bool (Item::*Item_processor)(byte *arg);
+/*
+ See comments for sql_yacc.yy: insert_update_elem rule
+ */
+#define MY_ITEM_PREFER_1ST_TABLE 1
+
class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
@@ -142,6 +147,7 @@ public:
my_bool with_sum_func;
my_bool fixed; /* If item fixed with fix_fields */
DTCollation collation;
+ uint8 item_flags; /* Flags on how item should be processed */
// alloc & destruct is done as start of select using sql_alloc
Item();
@@ -327,6 +333,11 @@ public:
cleanup();
delete this;
}
+ virtual bool set_flags_processor(byte *args)
+ {
+ this->item_flags|= *((uint8*)args);
+ return false;
+ }
};
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index f5e77862e1d..8298ce2cfb7 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -51,8 +51,8 @@ bool Item_str_buff::cmp(void)
String *res;
bool tmp;
- res=item->val_str(&tmp_value);
- res->length(min(res->length(), value.alloced_length()));
+ if ((res=item->val_str(&tmp_value)))
+ res->length(min(res->length(), value.alloced_length()));
if (null_value != item->null_value)
{
if ((null_value= item->null_value))
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b4c212afb3f..e5d5e95cb5a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2096,7 +2096,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) 0;
}
bool allow_rowid= tables && !tables->next; // Only one table
- for (; tables ; tables=tables->next)
+ uint table_idx= 0;
+ for (; tables ; tables=tables->next, table_idx++)
{
if (!tables->table)
{
@@ -2124,7 +2125,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
name,thd->where);
return (Field*) 0;
}
- found=field;
+ found= field;
+ if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
+ break;
}
}
if (found)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b90de7e93cc..f09d3214c74 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1636,11 +1636,22 @@ bool select_insert::send_data(List<Item> &values)
store_values(values);
error=thd->net.report_error || write_record(table,&info);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
- if (!error && table->next_number_field) // Clear for next record
+
+ if (!error)
{
- table->next_number_field->reset();
- if (! last_insert_id && thd->insert_id_used)
- last_insert_id=thd->insert_id();
+ /*
+ Restore fields of the record since it is possible that they were
+ changed by ON DUPLICATE KEY UPDATE clause.
+ */
+ if (info.handle_duplicates == DUP_UPDATE)
+ restore_record(table, default_values);
+
+ if (table->next_number_field) // Clear for next record
+ {
+ table->next_number_field->reset();
+ if (! last_insert_id && thd->insert_id_used)
+ last_insert_id=thd->insert_id();
+ }
}
DBUG_RETURN(error);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index c107203b548..233104c9a90 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1943,6 +1943,16 @@ mysql_execute_command(THD *thd)
if (tables || &lex->select_lex != lex->all_selects_list)
mysql_reset_errors(thd);
+ /*
+ When subselects or time_zone info is used in a query
+ we create a new TABLE_LIST containing all referenced tables
+ and set local variable 'tables' to point to this list.
+ */
+ if ((&lex->select_lex != lex->all_selects_list ||
+ lex->time_zone_tables_used) &&
+ lex->unit.create_total_list(thd, lex, &tables))
+ DBUG_VOID_RETURN;
+
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
{
@@ -1993,14 +2003,6 @@ mysql_execute_command(THD *thd)
}
#endif /* !HAVE_REPLICATION */
- /* When subselects or time_zone info is used in a query
- * we create a new TABLE_LIST containing all referenced tables
- * and set local variable 'tables' to point to this list. */
- if ((&lex->select_lex != lex->all_selects_list ||
- lex->time_zone_tables_used) &&
- lex->unit.create_total_list(thd, lex, &tables))
- DBUG_VOID_RETURN;
-
/*
When option readonly is set deny operations which change tables.
Except for the replication thread and the 'super' users.
@@ -2854,17 +2856,14 @@ unsent_create_error:
if ((res= open_and_lock_tables(thd, tables)))
break;
- TABLE *table= tables->table;
/* Skip first table, which is the table we are inserting in */
select_lex->table_list.first= (byte*) first_local_table->next;
- tables= (TABLE_LIST *) select_lex->table_list.first;
- first_local_table->next= 0;
if (!(res= mysql_prepare_insert(thd, tables, first_local_table,
- table, lex->field_list, 0,
+ tables->table, lex->field_list, 0,
lex->update_list, lex->value_list,
lex->duplicates)) &&
- (result= new select_insert(table, &lex->field_list,
+ (result= new select_insert(tables->table, &lex->field_list,
&lex->update_list, &lex->value_list,
lex->duplicates, lex->ignore)))
{
@@ -2877,7 +2876,7 @@ unsent_create_error:
/* revert changes for SP */
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
delete result;
- table->insert_values= 0;
+ tables->table->insert_values= 0;
if (thd->net.report_error)
res= -1;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bc21649fe54..460234de156 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4239,9 +4239,24 @@ insert_update_elem:
simple_ident equal expr_or_default
{
LEX *lex= Lex;
+ uint8 tmp= MY_ITEM_PREFER_1ST_TABLE;
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3))
YYABORT;
+ /*
+ INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY
+ UPDATE a= a + b1.b
+
+ Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items
+ to prevent find_field_in_tables() doing further item searching
+ if it finds item occurence in first table in insert_table_list.
+ This allows to avoid ambiguity in resolving 'a' field in
+ example above.
+ */
+ $1->walk(&Item::set_flags_processor,
+ (byte *) &tmp);
+ $3->walk(&Item::set_flags_processor,
+ (byte *) &tmp);
};
opt_low_priority: