summaryrefslogtreecommitdiff
path: root/sql/sql_select.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.h')
-rw-r--r--sql/sql_select.h171
1 files changed, 111 insertions, 60 deletions
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 54138712da4..80b5e3c4e68 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -2,7 +2,7 @@
#define SQL_SELECT_INCLUDED
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2008, 2013, Monty Program Ab.
+ Copyright (c) 2008, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,33 +29,10 @@
#endif
#include "procedure.h"
-#include <myisam.h>
#include "sql_array.h" /* Array */
#include "records.h" /* READ_RECORD */
#include "opt_range.h" /* SQL_SELECT, QUICK_SELECT_I */
-
-#if defined(WITH_ARIA_STORAGE_ENGINE)
-#include <maria.h>
-#endif
-#if defined(USE_ARIA_FOR_TMP_TABLES)
-#define TMP_ENGINE_HTON maria_hton
-inline uint tmp_table_max_key_length() {
- return maria_max_key_length();
-}
-
-inline uint tmp_table_max_key_parts() {
- return maria_max_key_segments();
-}
-#else
-#define TMP_ENGINE_HTON myisam_hton
-inline uint tmp_table_max_key_length() {
- return MI_MAX_KEY_LENGTH;
-}
-inline uint tmp_table_max_key_parts() {
- return MI_MAX_KEY_SEG;
-}
-#endif
/* Values in optimize */
#define KEY_OPTIMIZE_EXISTS 1
#define KEY_OPTIMIZE_REF_OR_NULL 2
@@ -114,6 +91,13 @@ typedef struct st_table_ref
uchar *key_buff; ///< value to look for with key
uchar *key_buff2; ///< key_buff+key_length
store_key **key_copy; //
+
+ /*
+ Bitmap of key parts which refer to constants. key_copy only has copiers for
+ non-const key parts.
+ */
+ key_part_map const_ref_part_map;
+
Item **items; ///< val()'s for each keypart
/*
Array of pointers to trigger variables. Some/all of the pointers may be
@@ -204,6 +188,12 @@ int rr_sequential(READ_RECORD *info);
int rr_sequential_and_unpack(READ_RECORD *info);
+#include "sql_explain.h"
+
+/**************************************************************************************
+ * New EXPLAIN structures END
+ *************************************************************************************/
+
class JOIN_CACHE;
class SJ_TMP_TABLE;
class JOIN_TAB_RANGE;
@@ -258,7 +248,8 @@ typedef struct st_join_table {
JOIN_TAB_RANGE *bush_children;
/* Special content for EXPLAIN 'Extra' column or NULL if none */
- const char *info;
+ enum explain_extra_tag info;
+
/*
Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
column, or 0 if there is no info.
@@ -295,8 +286,11 @@ typedef struct st_join_table {
*/
double read_time;
- /* psergey-todo: make the below have type double, like POSITION::records_read? */
- ha_rows records_read;
+ /* Copy of POSITION::records_read, set by get_best_combination() */
+ double records_read;
+
+ /* The selectivity of the conditions that can be pushed to the table */
+ double cond_selectivity;
/* Startup cost for execution */
double startup_cost;
@@ -529,7 +523,7 @@ typedef struct st_join_table {
ha_rows get_examined_rows();
bool preread_init();
- bool is_sjm_nest() { return test(bush_children); }
+ bool is_sjm_nest() { return MY_TEST(bush_children); }
bool access_from_tables_is_allowed(table_map used_tables,
table_map sjm_lookup_tables)
@@ -542,6 +536,7 @@ typedef struct st_join_table {
bool keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, KEYUSE *keyuse);
+ void remove_redundant_bnl_scan_conds();
} JOIN_TAB;
@@ -723,8 +718,7 @@ public:
struct st_position *pos,
struct st_position *loose_scan_pos);
friend bool get_best_combination(JOIN *join);
- friend int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
- uint no_jbuf_after);
+ friend int setup_semijoin_loosescan(JOIN *join);
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
};
@@ -781,6 +775,9 @@ typedef struct st_position :public Sql_alloc
*/
double records_read;
+ /* The selectivity of the pushed down conditions */
+ double cond_selectivity;
+
/*
Cost accessing the table in course of the entire complete join execution,
i.e. cost of one access method use (e.g. 'range' or 'ref' scan ) times
@@ -789,7 +786,7 @@ typedef struct st_position :public Sql_alloc
double read_time;
/* Cumulative cost and record count for the join prefix */
- COST_VECT prefix_cost;
+ Cost_estimate prefix_cost;
double prefix_record_count;
/*
@@ -913,7 +910,7 @@ protected:
enum enum_reopt_result {
REOPT_NEW_PLAN, /* there is a new reoptimized plan */
REOPT_OLD_PLAN, /* no new improved plan can be found, use the old one */
- REOPT_ERROR, /* an irrecovarable error occured during reoptimization */
+ REOPT_ERROR, /* an irrecovarable error occurred during reoptimization */
REOPT_NONE /* not yet reoptimized */
};
@@ -951,7 +948,7 @@ public:
*/
JOIN_TAB *table_access_tabs;
uint top_table_access_tabs_count;
-
+
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
@@ -1129,6 +1126,12 @@ public:
restore_no_rows_in_result() in ::reinit()
*/
bool no_rows_in_result_called;
+
+ /**
+ This is set if SQL_CALC_ROWS was calculated by filesort()
+ and should be taken from the appropriate JOIN_TAB
+ */
+ bool filesort_found_rows;
/**
Copy of this JOIN to be used with temporary tables.
@@ -1229,8 +1232,14 @@ public:
const char *zero_result_cause; ///< not 0 if exec must return zero result
bool union_part; ///< this subselect is part of union
+
+ enum join_optimization_state { NOT_OPTIMIZED=0,
+ OPTIMIZATION_IN_PROGRESS=1,
+ OPTIMIZATION_DONE=2};
bool optimized; ///< flag to avoid double optimization in EXPLAIN
bool initialized; ///< flag to avoid double init_execution calls
+
+ enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE, QEP_DELETED} have_query_plan;
/*
Additional WHERE and HAVING predicates to be considered for IN=>EXISTS
@@ -1298,7 +1307,7 @@ public:
lock= thd_arg->lock;
select_lex= 0; //for safety
tmp_join= 0;
- select_distinct= test(select_options & SELECT_DISTINCT);
+ select_distinct= MY_TEST(select_options & SELECT_DISTINCT);
no_order= 0;
simple_order= 0;
simple_group= 0;
@@ -1313,6 +1322,7 @@ public:
ref_pointer_array_size= 0;
zero_result_cause= 0;
optimized= 0;
+ have_query_plan= QEP_NOT_PRESENT_YET;
initialized= 0;
cleaned= 0;
cond_equal= 0;
@@ -1339,6 +1349,8 @@ public:
emb_sjm_nest= NULL;
sjm_lookup_tables= 0;
sjm_scan_tables= 0;
+
+ exec_saved_explain= false;
/*
The following is needed because JOIN::cleanup(true) may be called for
joins for which JOIN::optimize was aborted with an error before a proper
@@ -1347,15 +1359,24 @@ public:
table_access_tabs= NULL;
}
+ /*
+ TRUE <=> There was a JOIN::exec() call, which saved this JOIN's EXPLAIN.
+ The idea is that we also save at the end of JOIN::optimize(), but that
+ might not be the final plan.
+ */
+ bool exec_saved_explain;
+
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, bool skip_order_by,
ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select,
SELECT_LEX_UNIT *unit);
bool prepare_stage2();
int optimize();
+ int optimize_inner();
int reinit();
int init_execution();
void exec();
+ void exec_inner();
int destroy();
void restore_tmp();
bool alloc_func_list();
@@ -1431,7 +1452,7 @@ public:
void set_allowed_join_cache_types();
bool is_allowed_hash_join_access()
{
- return test(allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
+ return MY_TEST(allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT;
}
/*
@@ -1450,7 +1471,7 @@ public:
return ((const_tables != table_count &&
((select_distinct || !simple_order || !simple_group) ||
(group_list && order) ||
- test(select_options & OPTION_BUFFER_RESULT))) ||
+ MY_TEST(select_options & OPTION_BUFFER_RESULT))) ||
(rollup.state != ROLLUP::STATE_NONE && select_distinct));
}
bool choose_subquery_plan(table_map join_tables);
@@ -1469,6 +1490,11 @@ public:
{
return (unit->item && unit->item->is_in_predicate());
}
+ void save_explain_data(Explain_query *output, bool can_overwrite,
+ bool need_tmp_table, bool need_order, bool distinct);
+ int save_explain_data_intern(Explain_query *output, bool need_tmp_table,
+ bool need_order, bool distinct,
+ const char *message);
private:
/**
TRUE if the query contains an aggregate function but has no GROUP
@@ -1532,21 +1558,8 @@ public:
store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length)
:null_key(0), null_ptr(null), err(0)
{
- if (field_arg->type() == MYSQL_TYPE_BLOB
- || field_arg->type() == MYSQL_TYPE_GEOMETRY)
- {
- /*
- Key segments are always packed with a 2 byte length prefix.
- See mi_rkey for details.
- */
- to_field= new Field_varstring(ptr, length, 2, null, 1,
- Field::NONE, field_arg->field_name,
- field_arg->table->s, field_arg->charset());
- to_field->init(field_arg->table);
- }
- else
- to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
- ptr, null, 1);
+ to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
+ ptr, length, null, 1);
}
store_key(store_key &arg)
:Sql_alloc(), null_key(arg.null_key), to_field(arg.to_field),
@@ -1784,10 +1797,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
bool table_cant_handle_bit_fields,
bool make_copy_field,
uint convert_blob_length);
-bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
- ENGINE_COLUMNDEF *start_recinfo,
- ENGINE_COLUMNDEF **recinfo,
- ulonglong options, my_bool big_tables);
/*
General routine to change field->ptr of a NULL-terminated array of Field
@@ -1822,8 +1831,12 @@ inline bool optimizer_flag(THD *thd, uint flag)
return (thd->variables.optimizer_switch & flag);
}
+int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
+ SELECT_LEX *select_lex, uint8 select_options);
+
uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select,
- ha_rows limit, bool *need_sort, bool *reverse);
+ ha_rows limit, ha_rows *scanned_limit,
+ bool *need_sort, bool *reverse);
ORDER *simple_remove_const(ORDER *order, COND *where);
bool const_expression_in_where(COND *cond, Item *comp_item,
Field *comp_field= NULL,
@@ -1837,6 +1850,31 @@ void eliminate_tables(JOIN *join);
/* Index Condition Pushdown entry point function */
void push_index_cond(JOIN_TAB *tab, uint keyno);
+#define OPT_LINK_EQUAL_FIELDS 1
+
+/* EXPLAIN-related utility functions */
+int print_explain_message_line(select_result_sink *result,
+ uint8 options,
+ uint select_number,
+ const char *select_type,
+ ha_rows *rows,
+ const char *message);
+void explain_append_mrr_info(QUICK_RANGE_SELECT *quick, String *res);
+int print_explain_row(select_result_sink *result,
+ uint8 options,
+ uint select_number,
+ const char *select_type,
+ const char *table_name,
+ const char *partitions,
+ enum join_type jtype,
+ const char *possible_keys,
+ const char *index,
+ const char *key_len,
+ const char *ref,
+ ha_rows *rows,
+ const char *extra);
+void make_possible_keys_line(TABLE *table, key_map possible_keys, String *line);
+
/****************************************************************************
Temporary table support for SQL Runtime
***************************************************************************/
@@ -1853,17 +1891,30 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bool keep_row_order= FALSE);
void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
- ENGINE_COLUMNDEF *start_recinfo,
- ENGINE_COLUMNDEF **recinfo,
+ TMP_ENGINE_COLUMNDEF *start_recinfo,
+ TMP_ENGINE_COLUMNDEF **recinfo,
int error, bool ignore_last_dupp_key_error,
bool *is_duplicate);
bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
- ENGINE_COLUMNDEF *start_recinfo,
- ENGINE_COLUMNDEF **recinfo,
+ TMP_ENGINE_COLUMNDEF *start_recinfo,
+ TMP_ENGINE_COLUMNDEF **recinfo,
ulonglong options);
bool open_tmp_table(TABLE *table);
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
double prev_record_reads(POSITION *positions, uint idx, table_map found_ref);
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
+struct st_cond_statistic
+{
+ Item *cond;
+ Field *field_arg;
+ ulong positive;
+};
+typedef struct st_cond_statistic COND_STATISTIC;
+
+ulong check_selectivity(THD *thd,
+ ulong rows_to_read,
+ TABLE *table,
+ List<COND_STATISTIC> *conds);
+
#endif /* SQL_SELECT_INCLUDED */