Skip to content

Commit

Permalink
fix(tianmu): fix query syntax (WHERE NOT IN ) is not supported. (ston…
Browse files Browse the repository at this point in the history
…eatom#767)

[summary]
1 'sub_select' item is the left argument,not the right argument of 'item_func';
2 5.7 use 'item_func_not' class to represent the meaning of the syntax "not", while 8.0 use a variable 'value_transform';
  • Loading branch information
lujiashun committed Nov 11, 2022
1 parent 6669693 commit f566a1b
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
9 changes: 9 additions & 0 deletions mysql-test/suite/tianmu/r/issue767.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use test;
create table tt(val int) ENGINE=TIANMU;
insert into tt values (12);
select * from tt where 42 not in (select * from tt where val > 42);
val
12
select * from tt where 42 in (select * from tt where val > 42);
val
drop table tt;
7 changes: 7 additions & 0 deletions mysql-test/suite/tianmu/t/issue767.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--source include/have_tianmu.inc
use test;
create table tt(val int) ENGINE=TIANMU;
insert into tt values (12);
select * from tt where 42 not in (select * from tt where val > 42);
select * from tt where 42 in (select * from tt where val > 42);
drop table tt;
1 change: 1 addition & 0 deletions storage/tianmu/core/compiled_query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ void CompiledQuery::CQStep::Print(Query *query) {
case StepType::TMP_TABLE: {
std::sprintf(buf, "T:%d = TMP_TABLE(", N(t1.n));
for (auto ele : tables1) std::sprintf(buf + std::strlen(buf), "T:%d,", N(ele.n));
std::sprintf(buf + std::strlen(buf), ")");
} break;
case StepType::CREATE_VC:
if (mysql_expr.size() == 1) {
Expand Down
42 changes: 32 additions & 10 deletions storage/tianmu/core/query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,16 @@ void Query::ExtractOperatorType(Item *&conds, common::Operator &op, bool &negati
conds = cond_func->arguments()[0];
break;
}
case Item_func::UNKNOWN_FUNC:
case Item_func::UNKNOWN_FUNC: {
op = common::Operator::O_UNKNOWN_FUNC;
if (cond_func->arg_count == 2) {
auto subselect_item = dynamic_cast<Item_in_subselect *>(cond_func->arguments()[1]);
if (subselect_item != nullptr && subselect_item->value_transform == Item::BOOL_IS_FALSE) {
negative = true;
}
}
break;
}
default:
op = common::Operator::O_ERROR; // unknown function type
break;
Expand Down Expand Up @@ -1644,7 +1651,8 @@ bool Query::ClearSubselectTransformation(common::Operator &oper_for_subselect, I
Item *left_expr_for_subselect) {
cond_to_reinsert = nullptr;
list_to_reinsert = nullptr;
Item *cond_removed;
Item *cond_removed = nullptr;
Item *left_ref = nullptr;
if (having &&
(having->type() == Item::COND_ITEM ||
(having->type() == Item::FUNC_ITEM && ((Item_func *)having)->functype() != Item_func::ISNOTNULLTEST_FUNC &&
Expand Down Expand Up @@ -1685,6 +1693,9 @@ bool Query::ClearSubselectTransformation(common::Operator &oper_for_subselect, I
if (dynamic_cast<Item_ref_null_helper *>(((Item_func *)cond_removed)->arguments()[1]) == nullptr)
return false;
field_for_subselect = nullptr;
// the left side of equality should be the left side of the original
// expression with subselect
left_ref = ((Item_func *)cond_removed)->arguments()[0];
} else if (!having || (having->type() == Item::FUNC_ITEM &&
(((Item_func *)having)->functype() == Item_func::ISNOTNULLTEST_FUNC ||
((Item_func *)having)->functype() == Item_func::TRIG_COND_FUNC))) {
Expand Down Expand Up @@ -1730,18 +1741,29 @@ bool Query::ClearSubselectTransformation(common::Operator &oper_for_subselect, I
// check if the extra condition is a comparison
if (cond_removed->type() != Item::FUNC_ITEM || ((Item_func *)cond_removed)->arg_count != 2)
return false;
// the right side of equality is the field of the original subselect
field_for_subselect = ((Item_func *)cond_removed)->arguments()[1];

if (((Item_func *)cond_removed)->arguments()[0]->type() == Item::REF_ITEM) {
// the right side of equality is the field of the original subselect
field_for_subselect = ((Item_func *)cond_removed)->arguments()[1];
// the left side of equality should be the left side of the original
// expression with subselect
left_ref = ((Item_func *)cond_removed)->arguments()[0];
} else if (((Item_func *)cond_removed)->arguments()[1]->type() == Item::REF_ITEM) {
// ref #767
// the left side of equality is the field of the original subselect
field_for_subselect = ((Item_func *)cond_removed)->arguments()[0];
// the right side of equality should be the left side of the original
// expression with subselect
left_ref = ((Item_func *)cond_removed)->arguments()[1];
} else {
return false;
}
} else
return false;
// the left side of equality should be the left side of the original
// expression with subselect
Item *left_ref = ((Item_func *)cond_removed)->arguments()[0];

if (dynamic_cast<Item_int_with_ref *>(left_ref) != nullptr)
left_ref = ((Item_int_with_ref *)left_ref)->real_item();
if (left_ref->type() != Item::REF_ITEM ||
/*((Item_ref *)left_ref)->ref_type() != Item_ref::DIRECT_REF ||*/ // stonedb8 DIRECT_REF is deleted
((Item_ref *)left_ref)->real_item() != left_expr_for_subselect)
if (left_ref->type() != Item::REF_ITEM || ((Item_ref *)left_ref)->real_item() != left_expr_for_subselect)
return false;
// set the operation type
switch (((Item_func *)cond_removed)->functype()) {
Expand Down

0 comments on commit f566a1b

Please sign in to comment.