Commit e2f70d6e authored by Aleksey Midenkov's avatar Aleksey Midenkov Committed by Sergei Golubchik

Vers SQL: Refactoring: better init of vers_conditions

Unit-based history point (vers_history_point_t; Vers_history_point).
parent df0e1817
...@@ -677,53 +677,37 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd) ...@@ -677,53 +677,37 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd)
{ {
vers_asof_timestamp_t &in= thd->variables.vers_asof_timestamp; vers_asof_timestamp_t &in= thd->variables.vers_asof_timestamp;
type= (vers_system_time_t) in.type; type= (vers_system_time_t) in.type;
unit_start= VERS_TIMESTAMP; start.unit= VERS_TIMESTAMP;
from_query= false; from_query= false;
if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL) if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL)
{ {
DBUG_ASSERT(type == SYSTEM_TIME_AS_OF); DBUG_ASSERT(type == SYSTEM_TIME_AS_OF);
start= new (thd->mem_root) start.item= new (thd->mem_root)
Item_datetime_literal(thd, &in.ltime, TIME_SECOND_PART_DIGITS); Item_datetime_literal(thd, &in.ltime, TIME_SECOND_PART_DIGITS);
if (!start) if (!start.item)
return true; return true;
} }
else else
start= NULL; start.item= NULL;
end= NULL; end.empty();
return false; return false;
} }
void vers_select_conds_t::print(String *str, enum_query_type query_type) void vers_select_conds_t::print(String *str, enum_query_type query_type)
{ {
const static LEX_CSTRING unit_type[]=
{
{ STRING_WITH_LEN("") },
{ STRING_WITH_LEN("TIMESTAMP ") },
{ STRING_WITH_LEN("TRANSACTION ") }
};
switch (type) { switch (type) {
case SYSTEM_TIME_UNSPECIFIED: case SYSTEM_TIME_UNSPECIFIED:
break; break;
case SYSTEM_TIME_AS_OF: case SYSTEM_TIME_AS_OF:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME AS OF ")); start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME AS OF "));
str->append(unit_type + unit_start);
start->print(str, query_type);
break; break;
case SYSTEM_TIME_FROM_TO: case SYSTEM_TIME_FROM_TO:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME FROM ")); start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME FROM "));
str->append(unit_type + unit_start); end.print(str, query_type, STRING_WITH_LEN(" TO "));
start->print(str, query_type);
str->append(STRING_WITH_LEN(" TO "));
str->append(unit_type + unit_end);
end->print(str, query_type);
break; break;
case SYSTEM_TIME_BETWEEN: case SYSTEM_TIME_BETWEEN:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME BETWEEN ")); start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME BETWEEN "));
str->append(unit_type + unit_start); end.print(str, query_type, STRING_WITH_LEN(" AND "));
start->print(str, query_type);
str->append(STRING_WITH_LEN(" AND "));
str->append(unit_type + unit_end);
end->print(str, query_type);
break; break;
case SYSTEM_TIME_BEFORE: case SYSTEM_TIME_BEFORE:
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -871,8 +855,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr ...@@ -871,8 +855,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
vers_system_time_t/VERS_TRX_ID at stage of fix_fields() vers_system_time_t/VERS_TRX_ID at stage of fix_fields()
(this is large refactoring). */ (this is large refactoring). */
vers_conditions.resolve_units(timestamps_only); vers_conditions.resolve_units(timestamps_only);
if (timestamps_only && (vers_conditions.unit_start == VERS_TRX_ID || if (timestamps_only && (vers_conditions.start.unit == VERS_TRX_ID ||
vers_conditions.unit_end == VERS_TRX_ID)) vers_conditions.end.unit == VERS_TRX_ID))
{ {
my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), table->table_name.str); my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), table->table_name.str);
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -889,53 +873,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr ...@@ -889,53 +873,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
{ {
if (vers_conditions) if (vers_conditions)
{ {
if (vers_conditions.start) vers_conditions.start.add_typecast(thd, t->s->versioned);
{ vers_conditions.end.add_typecast(thd, t->s->versioned);
if (!vers_conditions.unit_start)
vers_conditions.unit_start= t->s->versioned;
switch (vers_conditions.unit_start)
{
case VERS_TIMESTAMP:
{
vers_conditions.start= newx Item_datetime_from_unixtime_typecast(
thd, vers_conditions.start, 6);
break;
}
case VERS_TRX_ID:
{
vers_conditions.start= newx Item_longlong_typecast(
thd, vers_conditions.start);
break;
}
default:
DBUG_ASSERT(0);
break;
}
}
if (vers_conditions.end)
{
if (!vers_conditions.unit_end)
vers_conditions.unit_end= t->s->versioned;
switch (vers_conditions.unit_end)
{
case VERS_TIMESTAMP:
{
vers_conditions.end= newx Item_datetime_from_unixtime_typecast(
thd, vers_conditions.end, 6);
break;
}
case VERS_TRX_ID:
{
vers_conditions.end= newx Item_longlong_typecast(
thd, vers_conditions.end);
break;
}
default:
DBUG_ASSERT(0);
break;
}
}
} }
switch (vers_conditions.type) switch (vers_conditions.type)
{ {
...@@ -957,26 +896,19 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr ...@@ -957,26 +896,19 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
cond1= or_items(thd, cond1, newx Item_func_isnull(thd, row_end)); cond1= or_items(thd, cond1, newx Item_func_isnull(thd, row_end));
break; break;
case SYSTEM_TIME_AS_OF: case SYSTEM_TIME_AS_OF:
cond1= newx Item_func_le(thd, row_start, cond1= newx Item_func_le(thd, row_start, vers_conditions.start.item);
vers_conditions.start); cond2= newx Item_func_gt(thd, row_end, vers_conditions.start.item);
cond2= newx Item_func_gt(thd, row_end,
vers_conditions.start);
break; break;
case SYSTEM_TIME_FROM_TO: case SYSTEM_TIME_FROM_TO:
cond1= newx Item_func_lt(thd, row_start, cond1= newx Item_func_lt(thd, row_start, vers_conditions.end.item);
vers_conditions.end); cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item);
cond2= newx Item_func_ge(thd, row_end,
vers_conditions.start);
break; break;
case SYSTEM_TIME_BETWEEN: case SYSTEM_TIME_BETWEEN:
cond1= newx Item_func_le(thd, row_start, cond1= newx Item_func_le(thd, row_start, vers_conditions.end.item);
vers_conditions.end); cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item);
cond2= newx Item_func_ge(thd, row_end,
vers_conditions.start);
break; break;
case SYSTEM_TIME_BEFORE: case SYSTEM_TIME_BEFORE:
cond1= newx Item_func_lt(thd, row_end, cond1= newx Item_func_lt(thd, row_end, vers_conditions.start.item);
vers_conditions.start);
break; break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -995,29 +927,29 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr ...@@ -995,29 +927,29 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
cond1= newx Item_func_eq(thd, row_end, curr); cond1= newx Item_func_eq(thd, row_end, curr);
break; break;
case SYSTEM_TIME_AS_OF: case SYSTEM_TIME_AS_OF:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ? trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID) : ? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID)
vers_conditions.start; : vers_conditions.start.item;
cond1= newx Item_func_vtq_trx_sees_eq(thd, trx_id0, row_start); cond1= newx Item_func_vtq_trx_sees_eq(thd, trx_id0, row_start);
cond2= newx Item_func_vtq_trx_sees(thd, row_end, trx_id0); cond2= newx Item_func_vtq_trx_sees(thd, row_end, trx_id0);
break; break;
case SYSTEM_TIME_FROM_TO: case SYSTEM_TIME_FROM_TO:
case SYSTEM_TIME_BETWEEN: case SYSTEM_TIME_BETWEEN:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ? trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID, true) : ? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID, true)
vers_conditions.start; : vers_conditions.start.item;
trx_id1= vers_conditions.unit_end == VERS_TIMESTAMP ? trx_id1= vers_conditions.end.unit == VERS_TIMESTAMP
newx Item_func_vtq_id(thd, vers_conditions.end, TR_table::FLD_TRX_ID, false) : ? newx Item_func_vtq_id(thd, vers_conditions.end.item, TR_table::FLD_TRX_ID, false)
vers_conditions.end; : vers_conditions.end.item;
cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO ? cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO
newx Item_func_vtq_trx_sees(thd, trx_id1, row_start) : ? newx Item_func_vtq_trx_sees(thd, trx_id1, row_start)
newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start); : newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start);
cond2= newx Item_func_vtq_trx_sees_eq(thd, row_end, trx_id0); cond2= newx Item_func_vtq_trx_sees_eq(thd, row_end, trx_id0);
break; break;
case SYSTEM_TIME_BEFORE: case SYSTEM_TIME_BEFORE:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ? trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID) : ? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID)
vers_conditions.start; : vers_conditions.start.item;
cond1= newx Item_func_lt(thd, row_end, trx_id0); cond1= newx Item_func_lt(thd, row_end, trx_id0);
break; break;
default: default:
......
...@@ -752,27 +752,6 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin) ...@@ -752,27 +752,6 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
} while(0) } while(0)
void vers_select_conds_t::init(vers_system_time_t t, vers_sys_type_t u_start,
Item *s, vers_sys_type_t u_end, Item *e)
{
type= t;
unit_start= u_start;
unit_end= u_end;
start= fix_dec(s);
end= fix_dec(e);
used= from_query= false;
}
Item *vers_select_conds_t::fix_dec(Item *item)
{
if (item && item->decimals == 0 && item->type() == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::NOW_FUNC)
item->decimals= 6;
return item;
}
Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
{ {
Virtual_column_info *v= new (thd->mem_root) Virtual_column_info(); Virtual_column_info *v= new (thd->mem_root) Virtual_column_info();
...@@ -813,6 +792,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) ...@@ -813,6 +792,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
LEX_CSTRING name; LEX_CSTRING name;
uint offset; uint offset;
} sp_cursor_name_and_offset; } sp_cursor_name_and_offset;
vers_history_point_t vers_history_point;
/* pointers */ /* pointers */
Create_field *create_field; Create_field *create_field;
...@@ -2046,7 +2026,8 @@ END_OF_INPUT ...@@ -2046,7 +2026,8 @@ END_OF_INPUT
%type <lex_str_list> opt_with_column_list %type <lex_str_list> opt_with_column_list
%type <vers_range_unit> opt_trans_or_timestamp %type <vers_range_unit> opt_history_unit
%type <vers_history_point> history_point
%type <vers_column_versioning> with_or_without_system %type <vers_column_versioning> with_or_without_system
%% %%
...@@ -9203,18 +9184,25 @@ select_options: ...@@ -9203,18 +9184,25 @@ select_options:
} }
; ;
opt_trans_or_timestamp: opt_history_unit:
/* empty */ /* empty*/
{ {
$$ = VERS_UNDEFINED; $$= VERS_UNDEFINED;
} }
| TRANSACTION_SYM | TRANSACTION_SYM
{ {
$$ = VERS_TRX_ID; $$= VERS_TRX_ID;
} }
| TIMESTAMP | TIMESTAMP
{ {
$$ = VERS_TIMESTAMP; $$= VERS_TIMESTAMP;
}
;
history_point:
opt_history_unit simple_expr
{
$$= Vers_history_point($1, $2);
} }
; ;
...@@ -9230,23 +9218,23 @@ opt_for_system_time_clause: ...@@ -9230,23 +9218,23 @@ opt_for_system_time_clause:
; ;
system_time_expr: system_time_expr:
AS OF_SYM opt_trans_or_timestamp simple_expr AS OF_SYM history_point
{ {
Lex->vers_conditions.init(SYSTEM_TIME_AS_OF, $3, $4); Lex->vers_conditions.init(SYSTEM_TIME_AS_OF, $3);
} }
| ALL | ALL
{ {
Lex->vers_conditions.init(SYSTEM_TIME_ALL); Lex->vers_conditions.init(SYSTEM_TIME_ALL);
} }
| FROM opt_trans_or_timestamp simple_expr | FROM history_point
TO_SYM opt_trans_or_timestamp simple_expr TO_SYM history_point
{ {
Lex->vers_conditions.init(SYSTEM_TIME_FROM_TO, $2, $3, $5, $6); Lex->vers_conditions.init(SYSTEM_TIME_FROM_TO, $2, $4);
} }
| BETWEEN_SYM opt_trans_or_timestamp simple_expr | BETWEEN_SYM history_point
AND_SYM opt_trans_or_timestamp simple_expr AND_SYM history_point
{ {
Lex->vers_conditions.init(SYSTEM_TIME_BETWEEN, $2, $3, $5, $6); Lex->vers_conditions.init(SYSTEM_TIME_BETWEEN, $2, $4);
} }
; ;
...@@ -13447,9 +13435,9 @@ opt_delete_system_time: ...@@ -13447,9 +13435,9 @@ opt_delete_system_time:
{ {
Lex->vers_conditions.init(SYSTEM_TIME_ALL); Lex->vers_conditions.init(SYSTEM_TIME_ALL);
} }
| BEFORE_SYM SYSTEM_TIME_SYM opt_trans_or_timestamp simple_expr | BEFORE_SYM SYSTEM_TIME_SYM history_point
{ {
Lex->vers_conditions.init(SYSTEM_TIME_BEFORE, $3, $4); Lex->vers_conditions.init(SYSTEM_TIME_BEFORE, $3);
} }
; ;
......
...@@ -8920,27 +8920,67 @@ bool TR_table::check(bool error) ...@@ -8920,27 +8920,67 @@ bool TR_table::check(bool error)
void vers_select_conds_t::resolve_units(bool timestamps_only) void vers_select_conds_t::resolve_units(bool timestamps_only)
{ {
DBUG_ASSERT(type != SYSTEM_TIME_UNSPECIFIED); DBUG_ASSERT(type != SYSTEM_TIME_UNSPECIFIED);
DBUG_ASSERT(start); DBUG_ASSERT(start.item);
if (unit_start == VERS_UNDEFINED) start.resolve_unit(timestamps_only);
end.resolve_unit(timestamps_only);
}
void Vers_history_point::resolve_unit(bool timestamps_only)
{
if (item && unit == VERS_UNDEFINED)
{ {
if (start->type() == Item::FIELD_ITEM) if (item->type() == Item::FIELD_ITEM || timestamps_only)
unit_start= VERS_TIMESTAMP; unit= VERS_TIMESTAMP;
else if (item->result_type() == INT_RESULT ||
item->result_type() == REAL_RESULT)
unit= VERS_TRX_ID;
else else
unit_start= (!timestamps_only && (start->result_type() == INT_RESULT || unit= VERS_TIMESTAMP;
start->result_type() == REAL_RESULT)) ?
VERS_TRX_ID : VERS_TIMESTAMP;
} }
if (end && unit_end == VERS_UNDEFINED) }
void Vers_history_point::fix_item()
{
if (item && item->decimals == 0 && item->type() == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::NOW_FUNC)
item->decimals= 6;
}
void Vers_history_point::add_typecast(THD *thd, enum vers_sys_type_t defunit)
{
if (item)
{ {
if (start->type() == Item::FIELD_ITEM) if (!unit)
unit_start= VERS_TIMESTAMP; unit= defunit;
else switch (unit)
unit_end= (!timestamps_only && (end->result_type() == INT_RESULT || {
end->result_type() == REAL_RESULT)) ? case VERS_TIMESTAMP:
VERS_TRX_ID : VERS_TIMESTAMP; item= new (thd->mem_root) Item_datetime_from_unixtime_typecast(
thd, item, MAX_DATETIME_PRECISION);
break;
case VERS_TRX_ID:
item= new (thd->mem_root) Item_longlong_typecast(thd, item);
break;
default:
DBUG_ASSERT(0);
break;
}
} }
} }
void Vers_history_point::print(String *str, enum_query_type query_type,
const char *prefix, size_t plen)
{
const static LEX_CSTRING unit_type[]=
{
{ STRING_WITH_LEN("") },
{ STRING_WITH_LEN("TIMESTAMP ") },
{ STRING_WITH_LEN("TRANSACTION ") }
};
str->append(prefix, plen);
str->append(unit_type + unit);
item->print(str, query_type);
}
Field *TABLE::find_field_by_name(LEX_CSTRING *str) const Field *TABLE::find_field_by_name(LEX_CSTRING *str) const
{ {
......
...@@ -1841,64 +1841,62 @@ class SJ_MATERIALIZATION_INFO; ...@@ -1841,64 +1841,62 @@ class SJ_MATERIALIZATION_INFO;
class Index_hint; class Index_hint;
class Item_in_subselect; class Item_in_subselect;
/* trivial class, for %union in sql_yacc.yy */
struct vers_history_point_t
{
vers_sys_type_t unit;
Item *item;
};
/* class Vers_history_point : public vers_history_point_t
Table reference in the FROM clause. {
void fix_item();
These table references can be of several types that correspond to
different SQL elements. Below we list all types of TABLE_LISTs with
the necessary conditions to determine when a TABLE_LIST instance
belongs to a certain type.
1) table (TABLE_LIST::view == NULL) public:
- base table Vers_history_point() { empty(); }
(TABLE_LIST::derived == NULL) Vers_history_point(vers_sys_type_t unit_arg, Item *item_arg)
- FROM-clause subquery - TABLE_LIST::table is a temp table {
(TABLE_LIST::derived != NULL) unit= unit_arg;
- information schema table item= item_arg;
(TABLE_LIST::schema_table != NULL) fix_item();
NOTICE: for schema tables TABLE_LIST::field_translation may be != NULL }
2) view (TABLE_LIST::view != NULL) Vers_history_point(vers_history_point_t p)
- merge (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_MERGE) {
also (TABLE_LIST::field_translation != NULL) unit= p.unit;
- tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE) item= p.item;
also (TABLE_LIST::field_translation == NULL) fix_item();
2.5) TODO: Add derived tables description here }
3) nested table reference (TABLE_LIST::nested_join != NULL) void empty() { unit= VERS_UNDEFINED; item= NULL; }
- table sequence - e.g. (t1, t2, t3) void print(String *str, enum_query_type, const char *prefix, size_t plen);
TODO: how to distinguish from a JOIN? void resolve_unit(bool timestamps_only);
- general JOIN void add_typecast(THD *thd, enum vers_sys_type_t defunit);
TODO: how to distinguish from a table sequence? };
- NATURAL JOIN
(TABLE_LIST::natural_join != NULL)
- JOIN ... USING
(TABLE_LIST::join_using_fields != NULL)
- semi-join nest (sj_on_expr!= NULL && sj_subq_pred!=NULL)
4) jtbm semi-join (jtbm_subselect != NULL)
*/
/** last_leaf_for_name_resolutioning support. */
struct vers_select_conds_t struct vers_select_conds_t
{ {
vers_system_time_t type; vers_system_time_t type;
vers_sys_type_t unit_start, unit_end;
bool from_query:1; bool from_query:1;
bool used:1; bool used:1;
Item *start, *end; Vers_history_point start;
Vers_history_point end;
void empty() void empty()
{ {
type= SYSTEM_TIME_UNSPECIFIED; type= SYSTEM_TIME_UNSPECIFIED;
unit_start= unit_end= VERS_UNDEFINED;
used= from_query= false; used= from_query= false;
start= end= NULL; start.empty();
end.empty();
} }
Item *fix_dec(Item *item); void init(vers_system_time_t _type,
Vers_history_point _start= Vers_history_point(),
void init(vers_system_time_t t, vers_sys_type_t u_start= VERS_UNDEFINED, Vers_history_point _end= Vers_history_point())
Item * s= NULL, vers_sys_type_t u_end= VERS_UNDEFINED, {
Item * e= NULL); type= _type;
used= from_query= false;
start= _start;
end= _end;
}
void print(String *str, enum_query_type query_type); void print(String *str, enum_query_type query_type);
...@@ -1923,6 +1921,43 @@ struct vers_select_conds_t ...@@ -1923,6 +1921,43 @@ struct vers_select_conds_t
} }
}; };
/*
Table reference in the FROM clause.
These table references can be of several types that correspond to
different SQL elements. Below we list all types of TABLE_LISTs with
the necessary conditions to determine when a TABLE_LIST instance
belongs to a certain type.
1) table (TABLE_LIST::view == NULL)
- base table
(TABLE_LIST::derived == NULL)
- FROM-clause subquery - TABLE_LIST::table is a temp table
(TABLE_LIST::derived != NULL)
- information schema table
(TABLE_LIST::schema_table != NULL)
NOTICE: for schema tables TABLE_LIST::field_translation may be != NULL
2) view (TABLE_LIST::view != NULL)
- merge (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_MERGE)
also (TABLE_LIST::field_translation != NULL)
- tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE)
also (TABLE_LIST::field_translation == NULL)
2.5) TODO: Add derived tables description here
3) nested table reference (TABLE_LIST::nested_join != NULL)
- table sequence - e.g. (t1, t2, t3)
TODO: how to distinguish from a JOIN?
- general JOIN
TODO: how to distinguish from a table sequence?
- NATURAL JOIN
(TABLE_LIST::natural_join != NULL)
- JOIN ... USING
(TABLE_LIST::join_using_fields != NULL)
- semi-join nest (sj_on_expr!= NULL && sj_subq_pred!=NULL)
4) jtbm semi-join (jtbm_subselect != NULL)
*/
/** last_leaf_for_name_resolutioning support. */
struct LEX; struct LEX;
class Index_hint; class Index_hint;
struct TABLE_LIST struct TABLE_LIST
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment