Skip to content

Commit 0bbad43

Browse files
author
Mattias Jonsson
committed
WL#4443
Changed Item according to second reviewers comments. (checking can_be_evaluated_now in const_item) Also fixed a bug found by first reviewer: INSERT INTO t VALUES ((subselect)) evaluated selects before locking.
1 parent ade8d83 commit 0bbad43

19 files changed

+240
-85
lines changed

mysql-test/r/func_if.result

-1
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,3 @@ foo
225225
0.1
226226
Warnings:
227227
Warning 1292 Truncated incorrect DOUBLE value: 'a'
228-
Warning 1292 Truncated incorrect DOUBLE value: 'a'

mysql-test/r/partition_locking.result

+82-1
Original file line numberDiff line numberDiff line change
@@ -3364,7 +3364,88 @@ DROP TABLE t1;
33643364
# Test of subqueries in INSERT
33653365
#
33663366
CREATE TABLE t1 (a INT, b VARCHAR(64));
3367+
CREATE TABLE t2 (a INT, b VARCHAR(64)) PARTITION BY HASH (a) PARTITIONS 3;
33673368
INSERT INTO t1 VALUES (1, "test 1");
3368-
INSERT INTO t1 VALUES (SELECT * FROM t1);
3369+
INSERT INTO t2 VALUES (SELECT * FROM t1);
33693370
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT * FROM t1)' at line 1
3371+
FLUSH STATUS;
3372+
INSERT INTO t2 VALUES ((SELECT a FROM t1), (SELECT b FROM t1));
3373+
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
3374+
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
3375+
VARIABLE_NAME VARIABLE_VALUE
3376+
HANDLER_COMMIT 1
3377+
HANDLER_EXTERNAL_LOCK 12
3378+
HANDLER_READ_FIRST 2
3379+
HANDLER_READ_KEY 2
3380+
HANDLER_READ_RND_NEXT 4
3381+
HANDLER_WRITE 18
3382+
# 12 locks (3 tables + 3 partitions) x lock/unlock
3383+
# I.e. No lock pruning possible
3384+
DROP TABLE t1, t2;
3385+
CREATE TABLE t1 (a INT, b INT);
3386+
CREATE TABLE t2 (a INT, b INT) PARTITION BY HASH (a) PARTITIONS 3;
3387+
INSERT INTO t1 VALUES (1, 1), (2, 0), (4, -1), (5, 2), (7, -3), (8, -9),
3388+
(10, 5), (11, 9);
3389+
FLUSH STATUS;
3390+
INSERT INTO t2 VALUES ((SELECT max(a) FROM t1), (SELECT min(a) FROM t1));
3391+
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
3392+
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
3393+
VARIABLE_NAME VARIABLE_VALUE
3394+
HANDLER_COMMIT 1
3395+
HANDLER_EXTERNAL_LOCK 12
3396+
HANDLER_READ_FIRST 2
3397+
HANDLER_READ_KEY 2
3398+
HANDLER_READ_RND_NEXT 18
3399+
HANDLER_WRITE 18
3400+
# 12 locks (3 tables + 3 partitions) x lock/unlock
3401+
# I.e. No lock pruning possible
3402+
FLUSH STATUS;
3403+
EXPLAIN PARTITIONS INSERT INTO t2 VALUES ((SELECT max(a) FROM t1),
3404+
(SELECT min(a) FROM t1));
3405+
id select_type table partitions type possible_keys key key_len ref rows Extra
3406+
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3407+
3 SUBQUERY t1 NULL ALL NULL NULL NULL NULL 8 NULL
3408+
2 SUBQUERY t1 NULL ALL NULL NULL NULL NULL 8 NULL
3409+
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
3410+
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
3411+
VARIABLE_NAME VARIABLE_VALUE
3412+
HANDLER_COMMIT 1
3413+
HANDLER_EXTERNAL_LOCK 12
3414+
HANDLER_WRITE 17
3415+
# 12 locks (3 tables + 3 partitions) x lock/unlock
3416+
# I.e. No lock pruning possible
3417+
FLUSH STATUS;
3418+
INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
3419+
(SELECT b FROM t1 WHERE a = 2));
3420+
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
3421+
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
3422+
VARIABLE_NAME VARIABLE_VALUE
3423+
HANDLER_COMMIT 1
3424+
HANDLER_EXTERNAL_LOCK 12
3425+
HANDLER_READ_FIRST 2
3426+
HANDLER_READ_KEY 2
3427+
HANDLER_READ_RND_NEXT 18
3428+
HANDLER_WRITE 18
3429+
# 12 locks (3 tables + 3 partitions) x lock/unlock
3430+
# I.e. No lock pruning possible
3431+
FLUSH STATUS;
3432+
EXPLAIN PARTITIONS INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
3433+
(SELECT b FROM t1 WHERE a = 2));
3434+
id select_type table partitions type possible_keys key key_len ref rows Extra
3435+
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3436+
3 SUBQUERY t1 NULL ALL NULL NULL NULL NULL 8 Using where
3437+
2 SUBQUERY t1 NULL ALL NULL NULL NULL NULL 8 Using where
3438+
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
3439+
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
3440+
VARIABLE_NAME VARIABLE_VALUE
3441+
HANDLER_COMMIT 1
3442+
HANDLER_EXTERNAL_LOCK 12
3443+
HANDLER_WRITE 17
3444+
# 12 locks (3 tables + 3 partitions) x lock/unlock
3445+
# I.e. No lock pruning possible
3446+
SELECT * FROM t2 ORDER BY a, b;
3447+
a b
3448+
1 0
3449+
11 1
33703450
DROP TABLE t1;
3451+
DROP TABLE t2;

mysql-test/suite/opt_trace/r/range_no_prot.result

+18-12
Original file line numberDiff line numberDiff line change
@@ -3932,11 +3932,13 @@ EXPLAIN SELECT 1 FROM
39323932
"chosen": true
39333933
} /* best_covering_index_scan */,
39343934
"setup_range_conditions": [
3935+
{
3936+
"impossible_condition": {
3937+
"cause": "comparison_with_null_always_false"
3938+
} /* impossible_condition */
3939+
}
39353940
] /* setup_range_conditions */,
3936-
"group_index_range": {
3937-
"chosen": false,
3938-
"cause": "not_single_table"
3939-
} /* group_index_range */
3941+
"impossible_range": true
39403942
} /* range_analysis */
39413943
} /* rows_estimation_per_outer_row */
39423944
},
@@ -3963,11 +3965,13 @@ EXPLAIN SELECT 1 FROM
39633965
"chosen": true
39643966
} /* best_covering_index_scan */,
39653967
"setup_range_conditions": [
3968+
{
3969+
"impossible_condition": {
3970+
"cause": "comparison_with_null_always_false"
3971+
} /* impossible_condition */
3972+
}
39663973
] /* setup_range_conditions */,
3967-
"group_index_range": {
3968-
"chosen": false,
3969-
"cause": "not_single_table"
3970-
} /* group_index_range */
3974+
"impossible_range": true
39713975
} /* range_analysis */
39723976
} /* rows_estimation_per_outer_row */
39733977
}
@@ -4266,11 +4270,13 @@ EXPLAIN SELECT 1 FROM
42664270
"chosen": true
42674271
} /* best_covering_index_scan */,
42684272
"setup_range_conditions": [
4273+
{
4274+
"impossible_condition": {
4275+
"cause": "comparison_with_null_always_false"
4276+
} /* impossible_condition */
4277+
}
42694278
] /* setup_range_conditions */,
4270-
"group_index_range": {
4271-
"chosen": false,
4272-
"cause": "not_single_table"
4273-
} /* group_index_range */
4279+
"impossible_range": true
42744280
} /* range_analysis */
42754281
} /* rows_estimation_per_outer_row */
42764282
}

mysql-test/t/partition_locking.test

+37-2
Original file line numberDiff line numberDiff line change
@@ -1552,8 +1552,43 @@ DROP TABLE t1;
15521552
--echo # Test of subqueries in INSERT
15531553
--echo #
15541554
CREATE TABLE t1 (a INT, b VARCHAR(64));
1555+
CREATE TABLE t2 (a INT, b VARCHAR(64)) PARTITION BY HASH (a) PARTITIONS 3;
15551556
INSERT INTO t1 VALUES (1, "test 1");
15561557
--error ER_PARSE_ERROR
1557-
INSERT INTO t1 VALUES (SELECT * FROM t1);
1558+
INSERT INTO t2 VALUES (SELECT * FROM t1);
1559+
FLUSH STATUS;
1560+
INSERT INTO t2 VALUES ((SELECT a FROM t1), (SELECT b FROM t1));
1561+
eval $get_handler_status_counts;
1562+
--echo # 12 locks (3 tables + 3 partitions) x lock/unlock
1563+
--echo # I.e. No lock pruning possible
1564+
DROP TABLE t1, t2;
1565+
CREATE TABLE t1 (a INT, b INT);
1566+
CREATE TABLE t2 (a INT, b INT) PARTITION BY HASH (a) PARTITIONS 3;
1567+
INSERT INTO t1 VALUES (1, 1), (2, 0), (4, -1), (5, 2), (7, -3), (8, -9),
1568+
(10, 5), (11, 9);
1569+
FLUSH STATUS;
1570+
INSERT INTO t2 VALUES ((SELECT max(a) FROM t1), (SELECT min(a) FROM t1));
1571+
eval $get_handler_status_counts;
1572+
--echo # 12 locks (3 tables + 3 partitions) x lock/unlock
1573+
--echo # I.e. No lock pruning possible
1574+
FLUSH STATUS;
1575+
EXPLAIN PARTITIONS INSERT INTO t2 VALUES ((SELECT max(a) FROM t1),
1576+
(SELECT min(a) FROM t1));
1577+
eval $get_handler_status_counts;
1578+
--echo # 12 locks (3 tables + 3 partitions) x lock/unlock
1579+
--echo # I.e. No lock pruning possible
1580+
FLUSH STATUS;
1581+
INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
1582+
(SELECT b FROM t1 WHERE a = 2));
1583+
eval $get_handler_status_counts;
1584+
--echo # 12 locks (3 tables + 3 partitions) x lock/unlock
1585+
--echo # I.e. No lock pruning possible
1586+
FLUSH STATUS;
1587+
EXPLAIN PARTITIONS INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1),
1588+
(SELECT b FROM t1 WHERE a = 2));
1589+
eval $get_handler_status_counts;
1590+
--echo # 12 locks (3 tables + 3 partitions) x lock/unlock
1591+
--echo # I.e. No lock pruning possible
1592+
SELECT * FROM t2 ORDER BY a, b;
15581593
DROP TABLE t1;
1559-
1594+
DROP TABLE t2;

mysql-test/t/partition_pruning.test

-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,6 @@ insert into t3 values (5),(15);
622622
explain partitions select * from t3 where a=11;
623623
explain partitions select * from t3 where a=10;
624624
explain partitions select * from t3 where a=20;
625-
626625
explain partitions select * from t3 where a=30;
627626

628627
# LIST(expr) partitioning

mysys/my_bitmap.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ uint bitmap_get_first_set(const MY_BITMAP *map)
557557

558558
uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit)
559559
{
560-
uint word_pos, start_pos;
560+
uint word_pos;
561561
uint32 first_word;
562562
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
563563

@@ -567,7 +567,7 @@ uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit)
567567
bitmap_bit++;
568568
if (bitmap_bit >= map->n_bits)
569569
return MY_BIT_NONE;
570-
start_pos= word_pos= bitmap_bit / 32;
570+
word_pos= bitmap_bit / 32;
571571
data_ptr= map->bitmap + word_pos;
572572
first_word= *data_ptr & (0xFFFFFFFF << (bitmap_bit % 32));
573573
if (data_ptr == end)

sql/ha_partition.cc

+18-7
Original file line numberDiff line numberDiff line change
@@ -7067,18 +7067,29 @@ const char *ha_partition::index_type(uint inx)
70677067

70687068
enum row_type ha_partition::get_row_type() const
70697069
{
7070-
handler **file;
7071-
enum row_type type= (*m_file)->get_row_type();
7070+
uint i;
7071+
enum row_type type;
7072+
DBUG_ENTER("ha_partition::get_row_type");
70727073

7073-
DBUG_ASSERT(bitmap_is_set_all(&(m_part_info->read_partitions)));
7074-
for (file= m_file, file++; *file; file++)
7074+
i= bitmap_get_first_set(&m_part_info->read_partitions);
7075+
DBUG_ASSERT(i < m_tot_parts);
7076+
if (i >= m_tot_parts)
7077+
DBUG_RETURN(ROW_TYPE_NOT_USED);
7078+
7079+
type= m_file[i]->get_row_type();
7080+
DBUG_PRINT("info", ("partition %u, row_type: %d", i, type));
7081+
7082+
for (i= bitmap_get_next_set(&m_part_info->lock_partitions, i);
7083+
i < m_tot_parts;
7084+
i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
70757085
{
7076-
enum row_type part_type= (*file)->get_row_type();
7086+
enum row_type part_type= m_file[i]->get_row_type();
7087+
DBUG_PRINT("info", ("partition %u, row_type: %d", i, type));
70777088
if (part_type != type)
7078-
return ROW_TYPE_NOT_USED;
7089+
DBUG_RETURN(ROW_TYPE_NOT_USED);
70797090
}
70807091

7081-
return type;
7092+
DBUG_RETURN(type);
70827093
}
70837094

70847095

sql/item.cc

+28-40
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,8 @@ int Item::save_str_value_in_field(Field *field, String *result)
549549
Item::Item():
550550
is_expensive_cache(-1), rsize(0),
551551
marker(0), fixed(0),
552-
collation(&my_charset_bin, DERIVATION_COERCIBLE), with_subselect(false)
552+
collation(&my_charset_bin, DERIVATION_COERCIBLE), with_subselect(false),
553+
tables_locked_cache(false)
553554
{
554555
maybe_null=null_value=with_sum_func=unsigned_flag=0;
555556
decimals= 0; max_length= 0;
@@ -597,7 +598,8 @@ Item::Item(THD *thd, Item *item):
597598
fixed(item->fixed),
598599
collation(item->collation),
599600
cmp_context(item->cmp_context),
600-
with_subselect(item->with_subselect)
601+
with_subselect(item->with_subselect),
602+
tables_locked_cache(item->tables_locked_cache)
601603
{
602604
next= thd->free_list; // Put in free list
603605
thd->free_list= this;
@@ -5864,6 +5866,30 @@ bool Item::eq_by_collation(Item *item, bool binary_cmp,
58645866
}
58655867

58665868

5869+
/**
5870+
Check if it is OK to evaluate the item now.
5871+
5872+
@return true if the item can be evaluated in the current statement state.
5873+
@retval true The item can be evaluated now.
5874+
@retval false The item can not be evaluated now,
5875+
(i.e. depend on non locked table).
5876+
5877+
@note Help function to avoid optimize or exec call during prepare phase.
5878+
*/
5879+
5880+
bool Item::can_be_evaluated_now() const
5881+
{
5882+
if (tables_locked_cache)
5883+
return true;
5884+
if (has_subquery())
5885+
const_cast<Item*>(this)->tables_locked_cache=
5886+
current_thd->lex->is_query_tables_locked();
5887+
else
5888+
const_cast<Item*>(this)->tables_locked_cache= true;
5889+
return tables_locked_cache;
5890+
}
5891+
5892+
58675893
/**
58685894
Create a field to hold a string value from an item.
58695895
@@ -9390,41 +9416,3 @@ void view_error_processor(THD *thd, void *data)
93909416
{
93919417
((TABLE_LIST *)data)->hide_view_error(thd);
93929418
}
9393-
9394-
/*
9395-
Is the item a stored function which may need table access.
9396-
9397-
TODO: Either eliminate the execute of this during mysql_delete_prepare
9398-
or create a better/more accurate way to check if the sp may access tables;
9399-
*/
9400-
9401-
static bool is_stored_function_which_may_need_table(Item* item)
9402-
{
9403-
if (item->type() == Item::FUNC_ITEM &&
9404-
((Item_func*)item)->functype() == Item_func::FUNC_SP)
9405-
return true;
9406-
return false;
9407-
}
9408-
9409-
9410-
/**
9411-
Returns wether it is OK to evaluate the item now.
9412-
9413-
@param thd Thread object
9414-
@param item Item to check
9415-
9416-
@return true if only constant and is either locked or has no subquery.
9417-
9418-
@note After WL#4443 there must be no optimize or exec call during
9419-
prepare phase.
9420-
*/
9421-
9422-
bool can_evaluate_item_now(THD *thd, Item *item)
9423-
{
9424-
if (item->const_item() &&
9425-
((thd->lex->is_query_tables_locked() ||
9426-
(!item->has_subquery() &&
9427-
!is_stored_function_which_may_need_table(item)))))
9428-
return true;
9429-
return false;
9430-
}

sql/item.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ class Item
711711
subselect. Computed by fix_fields
712712
and updated by update_used_tables. */
713713

714+
bool tables_locked_cache;
714715
public:
715716
// alloc & destruct is done as start of select using sql_alloc
716717
Item();
@@ -1194,7 +1195,12 @@ class Item
11941195
When the default implementation of used_tables() is effective, this
11951196
function will always return true (because used_tables() is empty).
11961197
*/
1197-
virtual bool const_item() const { return used_tables() == 0; }
1198+
virtual bool const_item() const
1199+
{
1200+
if (used_tables() == 0)
1201+
return can_be_evaluated_now();
1202+
return false;
1203+
}
11981204
/*
11991205
Returns true if this is constant but its value may be not known yet.
12001206
(Can be used for parameters of prep. stmts or of stored procedures.)
@@ -1573,6 +1579,7 @@ class Item
15731579
is_expensive_cache= walk(&Item::is_expensive_processor, 0, (uchar*)0);
15741580
return test(is_expensive_cache);
15751581
}
1582+
virtual bool can_be_evaluated_now() const;
15761583
uint32 max_char_length() const
15771584
{ return max_length / collation.collation->mbmaxlen; }
15781585
void fix_length_and_charset(uint32 max_char_length_arg,
@@ -4322,7 +4329,6 @@ void mark_select_range_as_dependent(THD *thd,
43224329
st_select_lex *current_sel,
43234330
Field *found_field, Item *found_item,
43244331
Item_ident *resolved_item);
4325-
bool can_evaluate_item_now(THD *thd, Item *item);
43264332

43274333
extern Cached_item *new_Cached_item(THD *thd, Item *item,
43284334
bool use_result_field);

0 commit comments

Comments
 (0)