1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

new lock for multiupdate:

- open and create derived tables
- detect which tables should be locked for write
- lock and fill derived tables
some unitialized variables fixed
This commit is contained in:
bell@sanja.is.com.ua
2004-11-05 17:29:47 +02:00
parent b2dd380beb
commit 064b02203f
15 changed files with 216 additions and 155 deletions

View File

@ -25,15 +25,15 @@
#include "sql_select.h"
#include "sql_acl.h"
static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
TABLE_LIST *t);
/*
Resolve derived tables in all queries
call given derived table processor (preparing or filling tables)
SYNOPSIS
mysql_handle_derived()
lex LEX for this thread
processor procedure of derived table processing
RETURN
0 ok
@ -42,7 +42,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
*/
int
mysql_handle_derived(LEX *lex)
mysql_handle_derived(LEX *lex, int (*processor)(THD*, LEX*, TABLE_LIST*))
{
if (lex->derived_tables)
{
@ -55,14 +55,8 @@ mysql_handle_derived(LEX *lex)
cursor= cursor->next_local)
{
int res;
if (cursor->derived && (res= mysql_derived(lex->thd, lex,
cursor->derived,
cursor)))
{
if ((res= (*processor)(lex->thd, lex, cursor)))
return res;
}
else if (cursor->ancestor)
cursor->set_ancestor();
}
if (lex->describe)
{
@ -80,20 +74,16 @@ mysql_handle_derived(LEX *lex)
/*
Resolve derived tables in all queries
Create temporary table structure (but do not fill it)
SYNOPSIS
mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
thd Thread handle
lex LEX for this thread
unit node that contains all SELECT's for derived tables
t TABLE_LIST for the upper SELECT
orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
Derived table is resolved with temporary table. It is created based on the
queries defined. After temporary table is created, if this is not EXPLAIN,
then the entire unit / node is deleted. unit is deleted if UNION is used
for derived table and node is deleted is it is a simple SELECT.
Derived table is resolved with temporary table.
After table creation, the above TABLE_LIST is updated with a new table.
@ -107,60 +97,126 @@ mysql_handle_derived(LEX *lex)
0 ok
1 Error
-1 Error and error message given
*/
*/
static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE_LIST *org_table_list)
int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
SELECT_LEX *first_select= unit->first_select();
TABLE *table;
int res;
select_union *derived_result;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived");
if (!(derived_result= new select_union(0)))
DBUG_RETURN(1); // out of memory
// st_select_lex_unit::prepare correctly work for single select
if ((res= unit->prepare(thd, derived_result, 0)))
goto exit;
derived_result->tmp_table_param.init();
derived_result->tmp_table_param.field_count= unit->types.elements;
/*
Temp table is created so that it hounours if UNION without ALL is to be
processed
*/
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
unit->types, (ORDER*) 0,
is_union && unit->union_distinct, 1,
(first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR,
org_table_list->alias)))
SELECT_LEX_UNIT *unit= orig_table_list->derived;
int res= 0;
if (unit)
{
res= -1;
goto exit;
SELECT_LEX *first_select= unit->first_select();
TABLE *table= 0;
select_union *derived_result;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
DBUG_ENTER("mysql_derived");
if (!(derived_result= new select_union(0)))
DBUG_RETURN(1); // out of memory
// st_select_lex_unit::prepare correctly work for single select
if ((res= unit->prepare(thd, derived_result, 0)))
goto exit;
derived_result->tmp_table_param.init();
derived_result->tmp_table_param.field_count= unit->types.elements;
/*
Temp table is created so that it hounours if UNION without ALL is to be
processed
*/
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
unit->types, (ORDER*) 0,
is_union && unit->union_distinct, 1,
(first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR,
orig_table_list->alias)))
{
res= -1;
goto exit;
}
derived_result->set_table(table);
exit:
/*
if it is preparation PS only or commands that need only VIEW structure
then we do not need real data and we can skip execution (and parameters
is not defined, too)
*/
if (res)
{
if (table)
free_tmp_table(thd, table);
delete derived_result;
}
else
{
if (!thd->fill_derived_tables())
delete derived_result;
orig_table_list->derived_result= derived_result;
orig_table_list->table= table;
orig_table_list->real_name= table->real_name;
table->derived_select_number= first_select->select_number;
table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.privilege= SELECT_ACL;
#endif
orig_table_list->db= (char *)"";
// Force read of table stats in the optimizer
table->file->info(HA_STATUS_VARIABLE);
/* Add new temporary table to list of open derived tables */
table->next= thd->derived_tables;
thd->derived_tables= table;
}
}
derived_result->set_table(table);
else if (orig_table_list->ancestor)
orig_table_list->set_ancestor();
return (res);
}
/*
if it is preparation PS only or commands that need only VIEW structure
then we do not need real data and we can skip execution (and parameters
is not defined, too)
/*
fill derived table
SYNOPSIS
mysql_derived_filling()
thd Thread handle
lex LEX for this thread
unit node that contains all SELECT's for derived tables
orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
Derived table is resolved with temporary table. It is created based on the
queries defined. After temporary table is filled, if this is not EXPLAIN,
then the entire unit / node is deleted. unit is deleted if UNION is used
for derived table and node is deleted is it is a simple SELECT.
RETURN
0 ok
1 Error
-1 Error and error message given
*/
if (!thd->only_prepare() && !lex->only_view_structure())
int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
TABLE *table= orig_table_list->table;
SELECT_LEX_UNIT *unit= orig_table_list->derived;
int res= 0;
/*check that table creation pass without problem and it is derived table */
if (table && unit)
{
SELECT_LEX *first_select= unit->first_select();
select_union *derived_result= orig_table_list->derived_result;
SELECT_LEX *save_current_select= lex->current_select;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
if (is_union)
{
// execute union without clean up
if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK)))
res= unit->exec();
res= unit->exec();
}
else
{
@ -173,7 +229,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
first_select->options&= ~OPTION_FOUND_ROWS;
lex->current_select= first_select;
res= mysql_select(thd, &first_select->ref_pointer_array,
res= mysql_select(thd, &first_select->ref_pointer_array,
(TABLE_LIST*) first_select->table_list.first,
first_select->with_wild,
first_select->item_list, first_select->where,
@ -186,49 +242,27 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
SELECT_NO_UNLOCK),
derived_result, unit, first_select);
}
}
if (!res)
{
/*
Here we entirely fix both TABLE_LIST and list of SELECT's as
there were no derived tables
*/
if (derived_result->flush())
res= 1;
if (!res)
{
/*
Here we entirely fix both TABLE_LIST and list of SELECT's as
there were no derived tables
*/
if (derived_result->flush())
res= 1;
if (!lex->describe)
unit->cleanup();
}
else
{
org_table_list->real_name= table->real_name;
org_table_list->table= table;
table->derived_select_number= first_select->select_number;
table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.privilege= SELECT_ACL;
#endif
org_table_list->db= (char *)"";
// Force read of table stats in the optimizer
table->file->info(HA_STATUS_VARIABLE);
}
if (!lex->describe)
free_tmp_table(thd, table);
unit->cleanup();
}
lex->current_select= save_current_select;
if (res)
free_tmp_table(thd, table);
else
{
/* Add new temporary table to list of open derived tables */
table->next= thd->derived_tables;
thd->derived_tables= table;
}
}
else
{
free_tmp_table(thd, table);
unit->cleanup();
}
exit:
delete derived_result;
lex->current_select= save_current_select;
DBUG_RETURN(res);
return res;
}