Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
diff --git a/sql/handler.h b/sql/handler.h
index d38c3da8da1..44255efab98 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3532,7 +3532,8 @@ class handler :public Sql_alloc
/* this is necessary in many places, e.g. in HANDLER command */
int ha_index_or_rnd_end()
{
- return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
+ return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() :
+ inited == SAMPLING? ha_sample_end(): 0;
}
/**
The cached_table_flags is set at ha_open and ha_external_lock
diff --git a/sql/lex.h b/sql/lex.h
index 4ce88ccc2ee..55589d888e6 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -659,6 +659,7 @@ SYMBOL symbols[] = {
{ "TABLE", SYM(TABLE_SYM)},
{ "TABLE_NAME", SYM(TABLE_NAME_SYM)},
{ "TABLES", SYM(TABLES)},
+ { "TABLESAMPLE", SYM(TABLESAMPLE)},
{ "TABLESPACE", SYM(TABLESPACE)},
{ "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)},
{ "TEMPORARY", SYM(TEMPORARY)},
diff --git a/sql/records.cc b/sql/records.cc
index b3b69f19665..9eadf788585 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -37,6 +37,7 @@
static int rr_quick(READ_RECORD *info);
int rr_sequential(READ_RECORD *info);
+int rr_sequential_sample(READ_RECORD *info);
static int rr_from_tempfile(READ_RECORD *info);
template<bool> static int rr_unpack_from_tempfile(READ_RECORD *info);
template<bool,bool> static int rr_unpack_from_buffer(READ_RECORD *info);
@@ -321,6 +322,14 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
DBUG_RETURN(1);
}
}
+ else if (table->tablesample)
+ {
+ double fract= table->tablesample->val_real() / 100.0;
+ info->sample_counter= (ha_rows)(table->file->records() * fract + 0.5);
+ info->read_record_func= rr_sequential_sample;
+ if (table->file->ha_sample_init())
+ DBUG_RETURN(1);
+ }
else
{
DBUG_PRINT("info",("using rr_sequential"));
@@ -524,6 +533,21 @@ int rr_sequential(READ_RECORD *info)
return tmp;
}
+int rr_sequential_sample(READ_RECORD *info)
+{
+ int tmp;
+ if (!info->sample_counter)
+ return -1; // End of file
+
+ info->sample_counter--;
+ while ((tmp= info->table->file->ha_sample_next(info->record())))
+ {
+ tmp= rr_handle_error(info, tmp);
+ break;
+ }
+ return tmp;
+}
+
static int rr_from_tempfile(READ_RECORD *info)
{
diff --git a/sql/records.h b/sql/records.h
index 9bc1b98fde4..579e0e2bf3a 100644
--- a/sql/records.h
+++ b/sql/records.h
@@ -61,6 +61,7 @@ struct READ_RECORD
SQL_SELECT *select;
uint ref_length, reclength, rec_cache_size, error_offset;
+ ha_rows sample_counter;
/**
Counting records when reading result from filesort().
Used when filesort leaves the result in the filesort buffer.
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 78d367e4005..4ced89e7c44 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7906,7 +7906,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
- if (table_list->process_index_hints(table))
+ if (table_list->process_index_hints(table) ||
+ table_list->process_table_sample(table))
DBUG_RETURN(1);
}
tablenr++;
@@ -7937,7 +7938,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
table_list->table->map= table_list->map_exec;
table_list->table->maybe_null= table_list->maybe_null_exec;
table_list->table->pos_in_table_list= table_list;
- if (table_list->process_index_hints(table_list->table))
+ if (table_list->process_index_hints(table_list->table) ||
+ table_list->process_table_sample(table_list->table))
DBUG_RETURN(1);
}
select_lex->leaf_tables.push_back(table_list);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c51345dcf26..88df2bc3d7a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -678,6 +678,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> SUM_SYM /* SQL-2003-N */
%token <kwd> SYSDATE
%token <kwd> TABLE_REF_PRIORITY
+%token <kwd> TABLESAMPLE /* SQL-2016-R */
%token <kwd> TABLE_SYM /* SQL-2003-R */
%token <kwd> TERMINATED
%token <kwd> THEN_SYM /* SQL-2003-R */
@@ -1498,7 +1499,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <item_param> param_marker
%type <item_num>
- NUM_literal
+ NUM_literal opt_table_sample
%type <item_basic_constant> text_literal
@@ -11700,10 +11701,19 @@ join_table_parens:
}
;
+/* psergey */
+opt_table_sample:
+ /* empty */ { $$=0; }
+ | TABLESAMPLE SYSTEM '(' NUM_literal ')'
+ {
+ $$=$4;
+ }
+ ;
table_primary_ident:
table_ident opt_use_partition opt_for_system_time_clause
opt_table_alias_clause opt_key_definition
+ opt_table_sample
{
if (!($$= Select->add_table_to_list(thd, $1, $4,
0,
@@ -11714,6 +11724,8 @@ table_primary_ident:
MYSQL_YYABORT;
if ($3)
$$->vers_conditions= Lex->vers_conditions;
+ if ($6)
+ $$->tablesample= $6;
}
;
diff --git a/sql/table.cc b/sql/table.cc
index 4e858cdb24c..4504e37dd7f 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5554,6 +5554,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
opt_range_condition_rows=0;
no_cache= false;
initialize_opt_range_structures();
+ tablesample= NULL;
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
master_had_triggers= 0;
@@ -8531,6 +8532,24 @@ bool TABLE_LIST::process_index_hints(TABLE *tbl)
return 0;
}
+bool TABLE_LIST::process_table_sample(TABLE *tbl)
+{
+ if (tablesample)
+ {
+ if (lock_type != TL_READ_DEFAULT)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Updates to tables using sampling");
+ return true;
+ }
+ tbl->keys_in_use_for_query.clear_all();
+ tbl->keys_in_use_for_group_by.clear_all();
+ tbl->keys_in_use_for_order_by.clear_all();
+ tbl->covering_keys.clear_all();
+ tbl->tablesample= tablesample;
+ }
+ return false;
+}
+
size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data)
{
diff --git a/sql/table.h b/sql/table.h
index 88216c788d4..5c0e7f9b51a 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1497,7 +1497,7 @@ struct TABLE
/* used in RBR Triggers */
bool master_had_triggers;
#endif
-
+ Item *tablesample;
REGINFO reginfo; /* field connections */
MEM_ROOT mem_root;
/**
@@ -2180,6 +2180,7 @@ struct TABLE_LIST
alias= (alias_arg ? *alias_arg : *table_name_arg);
lock_type= lock_type_arg;
updating= lock_type >= TL_FIRST_WRITE;
+ tablesample= NULL;
MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, db.str, table_name.str,
mdl_type, MDL_TRANSACTION);
}
@@ -2221,7 +2222,7 @@ struct TABLE_LIST
*last_ptr= &next_global;
for_insert_data= insert_data;
}
-
+ Item *tablesample;
/*
List of tables local to a subquery (used by SQL_I_List). Considers
@@ -2724,6 +2725,7 @@ struct TABLE_LIST
TABLE::force_index and TABLE::covering_keys.
*/
bool process_index_hints(TABLE *table);
+ bool process_table_sample(TABLE *tbl);
/**
Compare the version of metadata from the previous execution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment