Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions mysql-test/main/tablesample.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
DROP TABLE IF EXISTS t1, t2;
DROP VIEW IF EXISTS v1;
CREATE TABLE t1 (a INT, b INT, KEY idx_b(b));
CREATE TABLE t2 (a INT, c INT);
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 TABLESAMPLE SYSTEM (10);
a b
SELECT * FROM t1 TABLESAMPLE BERNOULLI (50);
a b
SELECT * FROM t1 TABLESAMPLE SYSTEM (12.5);
a b
SELECT * FROM t1 TABLESAMPLE BERNOULLI (0.5);
a b
SELECT * FROM t1 TABLESAMPLE BERNOULLI (NULL);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL)' at line 1
SELECT * FROM t1 TABLESAMPLE NONEXISTENTMETHOD (12.5);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NONEXISTENTMETHOD (12.5)' at line 1
SELECT * FROM t1 TABLESAMPLE SYSTEM (-12.5);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '-12.5)' at line 1
SELECT * FROM t1 TABLESAMPLE SYSTEM (10) JOIN t2 ON t1.a = t2.a;
a b a c
SELECT * FROM v1 TABLESAMPLE SYSTEM (20);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
PREPARE stmt2 FROM 'SELECT * FROM t1 TABLESAMPLE BERNOULLI (?)';
SET @pct = 30;
EXECUTE stmt2 USING @pct;
a b
SET @pct = 300;
EXECUTE stmt2 USING @pct;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
DEALLOCATE PREPARE stmt2;
DROP PROCEDURE IF EXISTS p1;
Warnings:
Note 1305 PROCEDURE test.p1 does not exist
CREATE PROCEDURE p1(IN sample_pct INT)
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
CALL p1(40);
a b
CALL p1(101);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
DROP PROCEDURE p1;
CREATE PROCEDURE p1(IN sample_pct DECIMAL)
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
CALL p1(40.11);
a b
Warnings:
Note 1265 Data truncated for column 'sample_pct' at row 0
DROP PROCEDURE p1;
DROP PROCEDURE IF EXISTS p_char;
Warnings:
Note 1305 PROCEDURE test.p_char does not exist
CREATE PROCEDURE p_char(IN sample_pct CHAR(10))
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
ERROR HY000: A variable of a non-numeric based type in TABLESAMPLE clause
DROP PROCEDURE IF EXISTS p_date;
Warnings:
Note 1305 PROCEDURE test.p_date does not exist
CREATE PROCEDURE p_date(IN sample_pct DATE)
BEGIN
SELECT * FROM t1 TABLESAMPLE BERNOULLI (sample_pct);
END//
ERROR HY000: A variable of a non-numeric based type in TABLESAMPLE clause
SELECT * FROM information_schema.tables TABLESAMPLE BERNOULLI (5);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
SELECT * FROM mysql.user TABLESAMPLE SYSTEM (10);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
SELECT * FROM (SELECT * FROM t1) AS derived_tbl TABLESAMPLE SYSTEM (50);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'TABLESAMPLE SYSTEM (50)' at line 1
WITH cte_tbl AS (SELECT * FROM t1)
SELECT * FROM cte_tbl TABLESAMPLE BERNOULLI (10);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
DROP TABLE t1, t2;
DROP VIEW v1;
133 changes: 133 additions & 0 deletions mysql-test/main/tablesample.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#
# MDEV-38992 SQL Standard TABLESAMPLE clause
#
# For now, there are tests just for checking syntax
#

--disable_warnings
DROP TABLE IF EXISTS t1, t2;
DROP VIEW IF EXISTS v1;
--enable_warnings

CREATE TABLE t1 (a INT, b INT, KEY idx_b(b));
CREATE TABLE t2 (a INT, c INT);
CREATE VIEW v1 AS SELECT * FROM t1;

#
# Basic Syntax Validation
#
SELECT * FROM t1 TABLESAMPLE SYSTEM (10);
SELECT * FROM t1 TABLESAMPLE BERNOULLI (50);

SELECT * FROM t1 TABLESAMPLE SYSTEM (12.5);
SELECT * FROM t1 TABLESAMPLE BERNOULLI (0.5);

--error ER_PARSE_ERROR
SELECT * FROM t1 TABLESAMPLE BERNOULLI (NULL);

--error ER_PARSE_ERROR
SELECT * FROM t1 TABLESAMPLE NONEXISTENTMETHOD (12.5);

--error ER_PARSE_ERROR
SELECT * FROM t1 TABLESAMPLE SYSTEM (-12.5);

SELECT * FROM t1 TABLESAMPLE SYSTEM (10) JOIN t2 ON t1.a = t2.a;

--error ER_SYNTAX_ERROR
SELECT * FROM v1 TABLESAMPLE SYSTEM (20);

#
# Testing Prepared statements
#
PREPARE stmt2 FROM 'SELECT * FROM t1 TABLESAMPLE BERNOULLI (?)';

SET @pct = 30;
EXECUTE stmt2 USING @pct;

SET @pct = 300;
--error ER_SYNTAX_ERROR
EXECUTE stmt2 USING @pct;

DEALLOCATE PREPARE stmt2;

#
# Testing stored procedures
#
DROP PROCEDURE IF EXISTS p1;

DELIMITER //;
CREATE PROCEDURE p1(IN sample_pct INT)
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
DELIMITER ;//

CALL p1(40);

--error ER_SYNTAX_ERROR
CALL p1(101);

DROP PROCEDURE p1;

DELIMITER //;
CREATE PROCEDURE p1(IN sample_pct DECIMAL)
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
DELIMITER ;//

CALL p1(40.11);

DROP PROCEDURE p1;

DROP PROCEDURE IF EXISTS p_char;

DELIMITER //;
--error ER_WRONG_SPVAR_TYPE_IN_TABLESAMPLE
CREATE PROCEDURE p_char(IN sample_pct CHAR(10))
BEGIN
SELECT * FROM t1 TABLESAMPLE SYSTEM (sample_pct);
END//
DELIMITER ;//

DROP PROCEDURE IF EXISTS p_date;

DELIMITER //;
--error ER_WRONG_SPVAR_TYPE_IN_TABLESAMPLE
CREATE PROCEDURE p_date(IN sample_pct DATE)
BEGIN
SELECT * FROM t1 TABLESAMPLE BERNOULLI (sample_pct);
END//
DELIMITER ;//

#
# TABLESAMPLE should not work on system tables
#
--error ER_SYNTAX_ERROR
SELECT * FROM information_schema.tables TABLESAMPLE BERNOULLI (5);

--error ER_SYNTAX_ERROR
SELECT * FROM mysql.user TABLESAMPLE SYSTEM (10);

#
# TABLESAMPLE should not work on derived tables
#
--error ER_PARSE_ERROR
SELECT * FROM (SELECT * FROM t1) AS derived_tbl TABLESAMPLE SYSTEM (50);

--error ER_SYNTAX_ERROR
WITH cte_tbl AS (SELECT * FROM t1)
SELECT * FROM cte_tbl TABLESAMPLE BERNOULLI (10);

# INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10);
# INSERT INTO t2 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10);

# SELECT * FROM t1 TABLESAMPLE BERNOULLI (50);

# SELECT * FROM t1 TABLESAMPLE BERNOULLI (50) JOIN t2 TABLESAMPLE BERNOULLI (50) ON t1.a = t2.a;

#
# Cleanup
#
DROP TABLE t1, t2;
DROP VIEW v1;
1 change: 1 addition & 0 deletions sql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ SET (SQL_SOURCE
sql_type_string.cc
sql_type_geom.cc sql_type_vector.cc
item_windowfunc.cc sql_window.cc
sql_tablesample.cc
sql_cte.cc
item_vers.cc
sql_sequence.cc sql_sequence.h ha_sequence.h
Expand Down
16 changes: 16 additions & 0 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,22 @@ bool Item_param::set_from_item(THD *thd, Item *item)
DBUG_RETURN(set_limit_clause_param(val));
}
}
if (tablesample_clause_param)
{
double val= item->val_real();
if (item->null_value)
{
set_null(DTCollation_numeric());
set_handler(&type_handler_null);
DBUG_RETURN(false);
}
else
{
unsigned_flag= item->unsigned_flag;
set_handler(item->type_handler());
DBUG_RETURN(set_tablesample_clause_param(val));
}
}
st_value tmp;
item->save_in_value(thd, &tmp);
DBUG_RETURN(set_from_value(thd, tmp, item->type_handler(), *item));
Expand Down
26 changes: 23 additions & 3 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,11 @@ class Rewritable_query_parameter
uint len_in_query;

bool limit_clause_param;
bool tablesample_clause_param;

Rewritable_query_parameter(uint pos_in_q= 0, uint len_in_q= 0)
: pos_in_query(pos_in_q), len_in_query(len_in_q),
limit_clause_param(false)
limit_clause_param(false), tablesample_clause_param(false)
{ }

virtual ~Rewritable_query_parameter() = default;
Expand Down Expand Up @@ -3405,20 +3406,28 @@ class Item_splocal :public Item_sp_variable,
Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table) override
{ return create_table_field_from_handler(root, table); }

bool is_valid_limit_clause_variable_with_error() const
bool is_valid_numeric_clause_variable_with_error() const
{
/*
In case if the variable has an anchored data type, e.g.:
DECLARE a TYPE OF t1.a;
type_handler() is set to &type_handler_null and this
function detects such variable as not valid in LIMIT.
*/
if (type_handler()->is_limit_clause_valid_type())
if (type_handler()->is_numeric_clause_valid_type())
return true;
my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
return false;
Comment on lines +3417 to 3420
}

bool is_valid_tablesample_clause_variable_with_error() const
{
if (type_handler()->is_tablesample_clause_valid_type())
return true;
my_error(ER_WRONG_SPVAR_TYPE_IN_TABLESAMPLE, MYF(0));
return false;
}

protected:
Item *shallow_copy(THD *thd) const override
{ return get_item_copy<Item_splocal>(thd, this); }
Expand Down Expand Up @@ -4746,6 +4755,12 @@ class Item_param final :public Item_basic_value,
set_int(nr, MY_INT64_NUM_DECIMAL_DIGITS);
return !unsigned_flag && value.integer < 0;
}
bool set_tablesample_clause_param(double d)
{
value.set_handler(&type_handler_double);
set_double(d);
return !unsigned_flag && value.real < 0;
}
const String *query_val_str(THD *thd, String *str) const;

bool convert_str_value(THD *thd);
Expand Down Expand Up @@ -4780,6 +4795,11 @@ class Item_param final :public Item_basic_value,
return state == SHORT_DATA_VALUE &&
value.type_handler()->cmp_type() == INT_RESULT;
}
bool has_double_value() const
{
return state == SHORT_DATA_VALUE &&
value.type_handler()->cmp_type() == REAL_RESULT;
}
bool is_stored_routine_parameter() const override { return true; }
/*
This method is used to make a copy of a basic constant item when
Expand Down
2 changes: 2 additions & 0 deletions sql/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ SYMBOL symbols[] = {
{ "BACKUP", SYM(BACKUP_SYM)},
{ "BEFORE", SYM(BEFORE_SYM)},
{ "BEGIN", SYM(BEGIN_MARIADB_SYM)},
{ "BERNOULLI", SYM(BERNOULLI)},
{ "BETWEEN", SYM(BETWEEN_SYM)},
{ "BIGINT", SYM(BIGINT)},
{ "BINARY", SYM(BINARY)},
Expand Down Expand Up @@ -663,6 +664,7 @@ SYMBOL symbols[] = {
{ "TABLE", SYM(TABLE_SYM)},
{ "TABLE_NAME", SYM(TABLE_NAME_SYM)},
{ "TABLES", SYM(TABLES)},
{ "TABLESAMPLE", SYM(TABLESAMPLE_SYM)},
{ "TABLESPACE", SYM(TABLESPACE)},
{ "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)},
{ "TEMPORARY", SYM(TEMPORARY)},
Expand Down
18 changes: 18 additions & 0 deletions sql/opt_hints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,24 @@ void Opt_hints_table::update_index_hint_map(Key_map *keys_to_use,

bool Opt_hints_table::update_index_hint_maps(THD *thd, TABLE *tbl)
{
/*
A TABLESAMPLE clause forces a sampling scan of the table and
index-based access can bias the result. Ignore any index hints
(old- or new-style) entirely and make sure no key is considered
usable, regardless of what the hints say.
*/
if (tbl->pos_in_table_list && tbl->pos_in_table_list->tablesample_clause)
{
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->keys_in_use_for_rowid_filter.clear_all();
tbl->covering_keys.clear_all();
tbl->force_index= tbl->force_index_join= tbl->force_index_group=
tbl->force_index_order= false;
return true; // handled: caller must not also run process_index_hints()
}

if (!is_fixed(INDEX_HINT_ENUM) && !is_fixed(JOIN_INDEX_HINT_ENUM) &&
!is_fixed(GROUP_INDEX_HINT_ENUM) && !is_fixed(ORDER_INDEX_HINT_ENUM) &&
!is_fixed(ROWID_FILTER_HINT_ENUM))
Expand Down
Loading
Loading