1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into  mysql.com:/home/my/mysql-5.0


sql/ha_berkeley.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_derived.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/share/errmsg.txt:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/sql_class.cc:
  Manual merge
This commit is contained in:
unknown
2005-08-15 18:35:48 +03:00
108 changed files with 4317 additions and 2182 deletions

View File

@ -2019,7 +2019,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*/
bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
if (!thd->active_transaction())
thd->transaction.xid.null();
thd->transaction.xid_state.xid.null();
/* report error issued during command execution */
if (thd->killed_errno() && !thd->net.report_error)
@ -2146,6 +2146,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
{
TABLE_LIST **query_tables_last= lex->query_tables_last;
sel= new SELECT_LEX();
/* 'parent_lex' is used in init_query() so it must be before it. */
sel->parent_lex= lex;
sel->init_query();
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
(List<String> *) 0, (List<String> *) 0))
@ -2326,11 +2328,16 @@ mysql_execute_command(THD *thd)
/*
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated.
Exception is DROP TEMPORARY TABLE IF EXISTS: we always execute it
(otherwise we have stale files on slave caused by exclusion of one tmp
table).
Exceptions are:
- SET: we always execute it (e.g., SET ONE_SHOT TIME_ZONE = 'XYZ')
- DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
have stale files on slave caused by exclusion of one tmp table).
*/
if (!(lex->sql_command == SQLCOM_DROP_TABLE &&
if (lex->sql_command != SQLCOM_SET_OPTION &&
!(lex->sql_command == SQLCOM_DROP_TABLE &&
lex->drop_temporary && lex->drop_if_exists) &&
all_tables_not_ok(thd, all_tables))
{
@ -3249,19 +3256,26 @@ end_with_restore_list:
if (!(res= open_and_lock_tables(thd, all_tables)))
{
/* Skip first table, which is the table we are inserting in */
select_lex->table_list.first= (byte*)first_table->next_local;
TABLE_LIST *second_table= first_table->next_local;
select_lex->table_list.first= (byte*) second_table;
select_lex->context.table_list= second_table;
select_lex->context.first_name_resolution_table= second_table;
res= mysql_insert_select_prepare(thd);
lex->select_lex.context.table_list= first_table->next_local;
if (!res && (result= new select_insert(first_table, first_table->table,
&lex->field_list,
&lex->update_list,
&lex->value_list,
lex->duplicates, lex->ignore)))
{
/* Skip first table, which is the table we are inserting in */
/*
Skip first table, which is the table we are inserting in.
Below we set context.table_list again because the call above to
mysql_insert_select_prepare() calls resolve_in_table_list_only(),
which in turn resets context.table_list and
context.first_name_resolution_table.
*/
select_lex->context.table_list= first_table->next_local;
select_lex->context.first_name_resolution_table= first_table->next_local;
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
delete result;
}
@ -4507,14 +4521,15 @@ end_with_restore_list:
break;
}
case SQLCOM_XA_START:
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_RESUME)
{
if (! thd->transaction.xid.eq(thd->lex->xid))
if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
thd->transaction.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xa_state=XA_ACTIVE;
send_ok(thd);
break;
}
@ -4523,10 +4538,10 @@ end_with_restore_list:
my_error(ER_XAER_INVAL, MYF(0));
break;
}
if (thd->transaction.xa_state != XA_NOTR)
if (thd->transaction.xid_state.xa_state != XA_NOTR)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (thd->active_transaction() || thd->locked_tables)
@ -4534,9 +4549,15 @@ end_with_restore_list:
my_error(ER_XAER_OUTSIDE, MYF(0));
break;
}
DBUG_ASSERT(thd->transaction.xid.is_null());
thd->transaction.xa_state=XA_ACTIVE;
thd->transaction.xid.set(thd->lex->xid);
if (xid_cache_search(thd->lex->xid))
{
my_error(ER_XAER_DUPID, MYF(0));
break;
}
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
thd->transaction.xid_state.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xid.set(thd->lex->xid);
xid_cache_insert(&thd->transaction.xid_state);
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
@ -4549,28 +4570,28 @@ end_with_restore_list:
my_error(ER_XAER_INVAL, MYF(0));
break;
}
if (thd->transaction.xa_state != XA_ACTIVE)
if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
thd->transaction.xa_state=XA_IDLE;
thd->transaction.xid_state.xa_state=XA_IDLE;
send_ok(thd);
break;
case SQLCOM_XA_PREPARE:
if (thd->transaction.xa_state != XA_IDLE)
if (thd->transaction.xid_state.xa_state != XA_IDLE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
@ -4578,22 +4599,28 @@ end_with_restore_list:
if (ha_prepare(thd))
{
my_error(ER_XA_RBROLLBACK, MYF(0));
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
}
thd->transaction.xa_state=XA_PREPARED;
thd->transaction.xid_state.xa_state=XA_PREPARED;
send_ok(thd);
break;
case SQLCOM_XA_COMMIT:
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 1)))
XID_STATE *xs=xid_cache_search(thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
{
ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
xid_cache_delete(xs);
send_ok(thd);
}
break;
}
if (thd->transaction.xa_state == XA_IDLE &&
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
{
int r;
@ -4602,7 +4629,7 @@ end_with_restore_list:
else
send_ok(thd);
}
else if (thd->transaction.xa_state == XA_PREPARED &&
else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
thd->lex->xa_opt == XA_NONE)
{
if (wait_if_global_read_lock(thd, 0, 0))
@ -4622,27 +4649,33 @@ end_with_restore_list:
else
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_ROLLBACK:
if (!thd->transaction.xid.eq(thd->lex->xid))
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 0)))
XID_STATE *xs=xid_cache_search(thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
{
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
xid_cache_delete(xs);
send_ok(thd);
}
break;
}
if (thd->transaction.xa_state != XA_IDLE &&
thd->transaction.xa_state != XA_PREPARED)
if (thd->transaction.xid_state.xa_state != XA_IDLE &&
thd->transaction.xid_state.xa_state != XA_PREPARED)
{
my_error(ER_XAER_RMFAIL, MYF(0),
xa_state_names[thd->transaction.xa_state]);
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (ha_rollback(thd))
@ -4651,7 +4684,8 @@ end_with_restore_list:
send_ok(thd);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
thd->transaction.xa_state=XA_NOTR;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd);
@ -5211,9 +5245,9 @@ mysql_new_select(LEX *lex, bool move_down)
if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1);
select_lex->select_number= ++thd->select_number;
select_lex->parent_lex= lex; /* Used in init_query. */
select_lex->init_query();
select_lex->init_select();
select_lex->parent_lex= lex;
/*
Don't evaluate this subquery during statement prepare even if
it's a constant one. The flag is switched off in the end of
@ -5271,6 +5305,7 @@ mysql_new_select(LEX *lex, bool move_down)
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
fake->parent_lex= lex; /* Used in init_query. */
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= 0;
@ -5279,6 +5314,11 @@ mysql_new_select(LEX *lex, bool move_down)
/* allow item list resolving in fake select for ORDER BY */
fake->context.resolve_in_select_list= TRUE;
fake->context.select_lex= fake;
/*
Remove the name resolution context of the fake select from the
context stack.
*/
lex->pop_context();
}
select_lex->context.outer_context= outer_context;
}
@ -5972,6 +6012,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
LEX_STRING *option)
{
register TABLE_LIST *ptr;
TABLE_LIST *previous_table_ref; /* The table preceding the current one. */
char *alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
@ -6067,8 +6108,29 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
}
}
/* Link table in local list (list for current select) */
/* Store the table reference preceding the current one. */
if (table_list.elements > 0)
{
previous_table_ref= (TABLE_LIST*) table_list.next;
DBUG_ASSERT(previous_table_ref);
}
/*
Link the current table reference in a local list (list for current select).
Notice that as a side effect here we set the next_local field of the
previous table reference to 'ptr'. Here we also add one element to the
list 'table_list'.
*/
table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
/*
Set next_name_resolution_table of the previous table reference to point to
the current table reference. In effect the list
TABLE_LIST::next_name_resolution_table coincides with
TABLE_LIST::next_local. Later this may be changed in
store_top_level_join_columns() for NATURAL/USING joins.
*/
if (table_list.elements > 1)
previous_table_ref->next_name_resolution_table= ptr;
ptr->next_name_resolution_table= NULL;
/* Link table in global list (all used tables) */
lex->add_to_query_tables(ptr);
DBUG_RETURN(ptr);
@ -6197,6 +6259,19 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
table->join_list= embedded_list;
table->embedding= ptr;
embedded_list->push_back(table);
if (table->natural_join)
{
ptr->is_natural_join= TRUE;
/*
If this is a JOIN ... USING, move the list of joined fields to the
table reference that describes the join.
*/
if (table->join_using_fields)
{
ptr->join_using_fields= table->join_using_fields;
table->join_using_fields= NULL;
}
}
}
join_list->push_front(ptr);
nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
@ -6204,44 +6279,6 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
}
/*
Save names for a join with using clause
SYNOPSIS
save_names_for_using_list
tab1 left table in join
tab2 right table in join
DESCRIPTION
The function saves the full names of the tables in st_select_lex
to be able to build later an on expression to replace the using clause.
RETURN VALUE
None
*/
void st_select_lex::save_names_for_using_list(TABLE_LIST *tab1,
TABLE_LIST *tab2)
{
while (tab1->nested_join)
{
tab1= tab1->nested_join->join_list.head();
}
db1= tab1->db;
table1= tab1->alias;
while (tab2->nested_join)
{
TABLE_LIST *next;
List_iterator_fast<TABLE_LIST> it(tab2->nested_join->join_list);
tab2= it++;
while ((next= it++))
tab2= next;
}
db2= tab2->db;
table2= tab2->alias;
}
/*
Add a table to the current join list
@ -6345,16 +6382,71 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
}
void add_join_on(TABLE_LIST *b,Item *expr)
/*
Create a new name resolution context for a JOIN ... ON clause.
SYNOPSIS
make_join_on_context()
thd pointer to current thread
left_op lefto operand of the JOIN
right_op rigth operand of the JOIN
DESCRIPTION
Create a new name resolution context for a JOIN ... ON clause,
and set the first and last leaves of the list of table references
to be used for name resolution.
RETURN
A new context if all is OK
NULL - if a memory allocation error occured
*/
Name_resolution_context *
make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op)
{
Name_resolution_context *on_context;
if (!(on_context= (Name_resolution_context*)
thd->calloc(sizeof(Name_resolution_context))))
return NULL;
on_context->init();
on_context->first_name_resolution_table=
left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution();
return on_context;
}
/*
Add an ON condition to the second operand of a JOIN ... ON.
SYNOPSIS
add_join_on
b the second operand of a JOIN ... ON
expr the condition to be added to the ON clause
DESCRIPTION
Add an ON condition to the right operand of a JOIN ... ON clause.
RETURN
FALSE if there was some error
TRUE if all is OK
*/
void add_join_on(TABLE_LIST *b, Item *expr)
{
if (expr)
{
if (!b->on_expr)
b->on_expr=expr;
b->on_expr= expr;
else
{
/* This only happens if you have both a right and left join */
b->on_expr=new Item_cond_and(b->on_expr,expr);
/*
If called from the parser, this happens if you have both a
right and left join. If called later, it happens if we add more
than one condition to the ON clause.
*/
b->on_expr= new Item_cond_and(b->on_expr,expr);
}
b->on_expr->top_level_item();
}
@ -6362,28 +6454,49 @@ void add_join_on(TABLE_LIST *b,Item *expr)
/*
Mark that we have a NATURAL JOIN between two tables
Mark that there is a NATURAL JOIN or JOIN ... USING between two
tables.
SYNOPSIS
add_join_natural()
a Table to do normal join with
b Do normal join with this table
a Left join argument
b Right join argument
using_fields Field names from USING clause
IMPLEMENTATION
This function just marks that table b should be joined with a.
The function setup_cond() will create in b->on_expr a list
of equal condition between all fields of the same name.
This function marks that table b should be joined with a either via
a NATURAL JOIN or via JOIN ... USING. Both join types are special
cases of each other, so we treat them together. The function
setup_conds() creates a list of equal condition between all fields
of the same name for NATURAL JOIN or the fields in 'using_fields'
for JOIN ... USING. The list of equality conditions is stored
either in b->on_expr, or in JOIN::conds, depending on whether there
was an outer join.
EXAMPLE
SELECT * FROM t1 NATURAL LEFT JOIN t2
<=>
SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
<=>
SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
<=>
SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
RETURN
None
*/
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields)
{
b->natural_join=a;
b->natural_join= a;
b->join_using_fields= using_fields;
}
/*
Reload/resets privileges and the different caches.