summaryrefslogtreecommitdiff
path: root/sql/sql_derived.cc
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-02-09 12:10:12 +0200
committerunknown <bell@sanja.is.com.ua>2004-02-09 12:10:12 +0200
commit584ddfdab2316c0b0520c6903fe6bf4b8a435b0a (patch)
tree4b7dc051ca61468dc50e8f7ab046eb07b55e7c3a /sql/sql_derived.cc
parentfaa8a41b1db57e643617eda8c49803f6e1287f87 (diff)
parent1f739ca45eb009de8dadd4503374bc4a5c6bf5c0 (diff)
downloadmariadb-git-584ddfdab2316c0b0520c6903fe6bf4b8a435b0a.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-derived2-4.1 sql/sql_delete.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_update.cc: Auto merged
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r--sql/sql_derived.cc246
1 files changed, 119 insertions, 127 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 374e56ecdd4..a307b59b525 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -25,6 +25,58 @@
#include "sql_select.h"
#include "sql_acl.h"
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
+
+/*
+ Resolve derived tables in all queries
+
+ SYNOPSIS
+ mysql_handle_derived()
+ lex LEX for this thread
+
+ RETURN
+ 0 ok
+ -1 Error
+ 1 Error and error message given
+*/
+int
+mysql_handle_derived(LEX *lex)
+{
+ int res= 0;
+ if (lex->derived_tables)
+ {
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ for (TABLE_LIST *cursor= sl->get_table_list();
+ cursor;
+ cursor= cursor->next)
+ {
+ if (cursor->derived && (res=mysql_derived(lex->thd, lex,
+ cursor->derived,
+ cursor)))
+ {
+ if (res < 0 || lex->thd->net.report_error)
+ send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ return 1;
+ }
+ }
+ if (lex->describe)
+ {
+ /*
+ Force join->join_tmp creation, because we will use this JOIN
+ twice for EXPLAIN and we have to have unchanged join for EXPLAINing
+ */
+ sl->uncacheable|= UNCACHEABLE_EXPLAIN;
+ sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
+ }
+ }
+ }
+ return 0;
+}
+
+
/*
Resolve derived tables in all queries
@@ -49,9 +101,6 @@
Derived tables is stored in thd->derived_tables and freed in
close_thread_tables()
- TODO
- Move creation of derived tables in open_and_lock_tables()
-
RETURN
0 ok
1 Error
@@ -72,143 +121,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived");
-
- /*
- In create_total_list, derived tables have to be treated in case of
- EXPLAIN, This is because unit/node is not deleted in that
- case. Current code in this function has to be improved to
- recognize better when this function is called from derived tables
- and when from other functions.
- */
- if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
- DBUG_RETURN(-1);
+ 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;
/*
- We have to do access checks here as this code is executed before any
- sql command is started to execute.
+ Temp table is created so that it hounours if UNION without ALL is to be
+ processed
*/
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (tables)
- res= check_table_access(thd,SELECT_ACL, tables,0);
- else
- res= check_access(thd, SELECT_ACL, any_db,0,0,0);
- if (res)
- DBUG_RETURN(1);
-#endif
-
- if (!(res=open_and_lock_tables(thd,tables)))
+ if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
+ unit->types, (ORDER*) 0,
+ is_union && !unit->union_option, 1,
+ (first_select->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR,
+ org_table_list->alias)))
{
- if (is_union || is_subsel)
- {
- /*
- The following code is a re-do of fix_tables_pointers() found
- in sql_select.cc for UNION's within derived tables. The only
- difference is in navigation, as in derived tables we care for
- this level only.
-
- */
- fix_tables_pointers(unit);
- }
+ res= -1;
+ goto exit;
+ }
+ derived_result->set_table(table);
- 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;
+ if (is_union)
+ res= mysql_union(thd, lex, derived_result, unit);
+ else
+ {
+ unit->offset_limit_cnt= first_select->offset_limit;
+ unit->select_limit_cnt= first_select->select_limit+
+ first_select->offset_limit;
+ if (unit->select_limit_cnt < first_select->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR;
+ if (unit->select_limit_cnt == HA_POS_ERROR)
+ first_select->options&= ~OPTION_FOUND_ROWS;
+
+ lex->current_select= first_select;
+ 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,
+ (first_select->order_list.elements+
+ first_select->group_list.elements),
+ (ORDER *) first_select->order_list.first,
+ (ORDER *) first_select->group_list.first,
+ first_select->having, (ORDER*) NULL,
+ (first_select->options | thd->options |
+ SELECT_NO_UNLOCK),
+ derived_result, unit, first_select);
+ }
- /*
- This is done in order to redo all field optimisations when any of the
- involved tables is used in the outer query
- */
- if (tables)
- {
- for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
- cursor->table->clear_query_id= 1;
- }
-
- derived_result->tmp_table_param.init();
- derived_result->tmp_table_param.field_count= unit->types.elements;
+ if (!res)
+ {
/*
- Temp table is created so that it hounours if UNION without ALL is to be
- processed
+ Here we entirely fix both TABLE_LIST and list of SELECT's as
+ there were no derived tables
*/
- if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
- unit->types, (ORDER*) 0,
- is_union && !unit->union_option, 1,
- (first_select->options | thd->options |
- TMP_TABLE_ALL_COLUMNS),
- HA_POS_ERROR,
- org_table_list->alias)))
- {
- res= -1;
- goto exit;
- }
- derived_result->set_table(table);
-
- if (is_union)
- res= mysql_union(thd, lex, derived_result, unit);
+ if (derived_result->flush())
+ res= 1;
else
{
- unit->offset_limit_cnt= first_select->offset_limit;
- unit->select_limit_cnt= first_select->select_limit+
- first_select->offset_limit;
- if (unit->select_limit_cnt < first_select->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR;
- if (unit->select_limit_cnt == HA_POS_ERROR)
- first_select->options&= ~OPTION_FOUND_ROWS;
-
- lex->current_select= first_select;
- 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,
- (first_select->order_list.elements+
- first_select->group_list.elements),
- (ORDER *) first_select->order_list.first,
- (ORDER *) first_select->group_list.first,
- first_select->having, (ORDER*) NULL,
- (first_select->options | thd->options |
- 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;
- else
+ org_table_list->real_name= table->real_name;
+ org_table_list->table= table;
+ if (org_table_list->table_list)
{
- 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;
+ org_table_list->table_list->real_name= table->real_name;
+ org_table_list->table_list->table= table;
+ }
+ table->derived_select_number= first_select->select_number;
+ table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- org_table_list->grant.privilege= SELECT_ACL;
+ org_table_list->grant.privilege= SELECT_ACL;
#endif
- if (lex->describe)
- {
- // to fix a problem in EXPLAIN
- if (tables)
- {
- for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
- if (cursor->table_list)
- cursor->table_list->table=cursor->table;
- }
- }
- else
- {
- unit->exclude_tree();
- unit->cleanup();
- }
- org_table_list->db= (char *)"";
- // Force read of table stats in the optimizer
- table->file->info(HA_STATUS_VARIABLE);
- }
+ org_table_list->db= (char *)"";
+ // Force read of table stats in the optimizer
+ table->file->info(HA_STATUS_VARIABLE);
}
if (res)
@@ -223,7 +216,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
exit:
delete derived_result;
lex->current_select= save_current_select;
- close_thread_tables(thd, 0, 1);
}
DBUG_RETURN(res);
}