Skip to content

Commit

Permalink
feat(sql): left join support for request mode
Browse files Browse the repository at this point in the history
- POC version, may requires some refactor.
- Requires more tests.
  • Loading branch information
aceforeverd committed Oct 29, 2023
1 parent 08ad04e commit 9ec4768
Show file tree
Hide file tree
Showing 21 changed files with 2,083 additions and 1,610 deletions.
67 changes: 64 additions & 3 deletions cases/plan/join_query.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,70 @@ cases:
mode: physical-plan-unsupport
- id: 2
desc: 简单SELECT LEFT JOIN
mode: runner-unsupport
sql: SELECT t1.COL1, t1.COL2, t2.COL1, t2.COL2 FROM t1 left join t2 on t1.col1 = t2.col2;
expect:
node_tree_str: |
+-node[kQuery]: kQuerySelect
+-distinct_opt: false
+-where_expr: null
+-group_expr_list: null
+-having_expr: null
+-order_expr_list: null
+-limit: null
+-select_list[list]:
| +-0:
| | +-node[kResTarget]
| | +-val:
| | | +-expr[column ref]
| | | +-relation_name: t1
| | | +-column_name: COL1
| | +-name: <nil>
| +-1:
| | +-node[kResTarget]
| | +-val:
| | | +-expr[column ref]
| | | +-relation_name: t1
| | | +-column_name: COL2
| | +-name: <nil>
| +-2:
| | +-node[kResTarget]
| | +-val:
| | | +-expr[column ref]
| | | +-relation_name: t2
| | | +-column_name: COL1
| | +-name: <nil>
| +-3:
| +-node[kResTarget]
| +-val:
| | +-expr[column ref]
| | +-relation_name: t2
| | +-column_name: COL2
| +-name: <nil>
+-tableref_list[list]:
| +-0:
| +-node[kTableRef]: kJoin
| +-join_type: LeftJoin
| +-left:
| | +-node[kTableRef]: kTable
| | +-table: t1
| | +-alias: <nil>
| +-right:
| +-node[kTableRef]: kTable
| +-table: t2
| +-alias: <nil>
| +-order_expressions: null
| +-on:
| +-expr[binary]
| +-=[list]:
| +-0:
| | +-expr[column ref]
| | +-relation_name: t1
| | +-column_name: col1
| +-1:
| +-expr[column ref]
| +-relation_name: t2
| +-column_name: col2
+-window_list: []
- id: 3
desc: 简单SELECT LAST JOIN
sql: SELECT t1.COL1, t1.COL2, t2.COL1, t2.COL2 FROM t1 last join t2 order by t2.col5 on t1.col1 = t2.col2;
Expand All @@ -31,7 +93,6 @@ cases:
- id: 5
desc: LeftJoin有不等式条件
sql: SELECT t1.col1 as t1_col1, t2.col2 as t2_col2 FROM t1 left join t2 on t1.col1 = t2.col2 and t2.col5 >= t1.col5;
mode: runner-unsupport
- id: 6
desc: LastJoin有不等式条件
sql: SELECT t1.col1 as t1_col1, t2.col2 as t2_col2 FROM t1 last join t2 order by t2.col5 on t1.col1 = t2.col2 and t2.col5 >= t1.col5;
Expand Down Expand Up @@ -162,4 +223,4 @@ cases:
col1 as id,
sum(col2) OVER w2 as w2_col2_sum FROM t1 WINDOW
w2 AS (PARTITION BY col1 ORDER BY col5 ROWS_RANGE BETWEEN 1d OPEN PRECEDING AND CURRENT ROW)
) as out1 ON out0.id = out1.id;
) as out1 ON out0.id = out1.id;
50 changes: 50 additions & 0 deletions cases/query/left_join.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
cases:
- id: 0
desc: last join to a left join subquery
inputs:
- name: t1
columns: ["c1 string","c2 int","c4 timestamp"]
indexs: ["index1:c1:c4"]
rows:
- ["aa",20,1000]
- ["bb",30,1000]
- ["cc",40,1000]
- ["dd",50,1000]
- name: t2
columns: ["c1 string","c4 timestamp"]
indexs: ["index1:c1:c4"]
rows:
- ["aa",2000]
- ["bb",2000]
- ["cc",3000]
- name: t3
columns: ["c1 string","c2 int","c3 bigint","c4 timestamp"]
indexs: ["index1:c1:c4"]
rows:
- ["aa",19,13,3000]
- ["aa",21,13,3000]
- ["bb",34,131,3000]
- ["bb",21,131,3000]
sql: |
select
t1.c1,
tx.c1 as c1l,
tx.c1r,
tx.c2r
from t1 last join
(
select t2.c1 as c1,
t3.c1 as c1r,
t3.c2 as c2r
from t2 left join t3
on t2.c1 = t3.c1
) tx
on t1.c1 = tx.c1 and t1.c2 > tx.c2r
expect:
order: c1
columns: ["c1 string", "c1l string", "c1r string", "c2r int"]
data: |
aa, aa, aa, 19
bb, bb, bb, 21
cc, NULL, NULL, NULL
dd, NULL, NULL, NULL
2 changes: 1 addition & 1 deletion hybridse/include/node/node_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ enum JoinType {
kJoinTypeRight,
kJoinTypeInner,
kJoinTypeConcat,
kJoinTypeComma
kJoinTypeCross, // AKA commma join
};

enum UnionType { kUnionTypeDistinct, kUnionTypeAll };
Expand Down
89 changes: 67 additions & 22 deletions hybridse/include/vm/physical_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ class PhysicalConstProjectNode : public PhysicalOpNode {
public:
explicit PhysicalConstProjectNode(const ColumnProjects &project)
: PhysicalOpNode(kPhysicalOpConstProject, true), project_(project) {
output_type_ = kSchemaTypeRow;
fn_infos_.push_back(&project_.fn_info());
}
virtual ~PhysicalConstProjectNode() {}
Expand Down Expand Up @@ -1183,23 +1184,25 @@ class PhysicalWindowAggrerationNode : public PhysicalProjectNode {

class PhysicalJoinNode : public PhysicalBinaryNode {
public:
static constexpr PhysicalOpType kConcreteNodeKind = kPhysicalOpJoin;

PhysicalJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const node::JoinType join_type)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();
}
PhysicalJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const node::JoinType join_type,
const node::OrderByNode *orders,
const node::ExprNode *condition)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, orders, condition),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();

RegisterFunctionInfo();
}
Expand All @@ -1208,11 +1211,11 @@ class PhysicalJoinNode : public PhysicalBinaryNode {
const node::ExprNode *condition,
const node::ExprListNode *left_keys,
const node::ExprListNode *right_keys)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, condition, left_keys, right_keys),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();

RegisterFunctionInfo();
}
Expand All @@ -1222,31 +1225,31 @@ class PhysicalJoinNode : public PhysicalBinaryNode {
const node::ExprNode *condition,
const node::ExprListNode *left_keys,
const node::ExprListNode *right_keys)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, orders, condition, left_keys, right_keys),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();

RegisterFunctionInfo();
}
PhysicalJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const Join &join)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();

RegisterFunctionInfo();
}
PhysicalJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const Join &join, const bool output_right_only)
: PhysicalBinaryNode(left, right, kPhysicalOpJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join),
joined_schemas_ctx_(this),
output_right_only_(output_right_only) {
output_type_ = left->GetOutputType();
InitOuptput();

RegisterFunctionInfo();
}
Expand Down Expand Up @@ -1275,37 +1278,59 @@ class PhysicalJoinNode : public PhysicalBinaryNode {
Join join_;
SchemasContext joined_schemas_ctx_;
const bool output_right_only_;

private:
void InitOuptput() {
switch (join_.join_type_) {
case node::kJoinTypeLast:
case node::kJoinTypeConcat: {
output_type_ = GetProducer(0)->GetOutputType();
break;
}
default: {
// standard SQL JOINs, always treat as a table output
if (GetProducer(0)->GetOutputType() == kSchemaTypeGroup) {
output_type_ = kSchemaTypeGroup;
} else {
output_type_ = kSchemaTypeTable;
}
break;
}
}
}
};

class PhysicalRequestJoinNode : public PhysicalBinaryNode {
public:
static constexpr PhysicalOpType kConcreteNodeKind = kPhysicalOpRequestJoin;

PhysicalRequestJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const node::JoinType join_type)
: PhysicalBinaryNode(left, right, kPhysicalOpRequestJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();
RegisterFunctionInfo();
}
PhysicalRequestJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const node::JoinType join_type,
const node::OrderByNode *orders,
const node::ExprNode *condition)
: PhysicalBinaryNode(left, right, kPhysicalOpRequestJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, orders, condition),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();
RegisterFunctionInfo();
}
PhysicalRequestJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
const Join &join, const bool output_right_only)
: PhysicalBinaryNode(left, right, kPhysicalOpRequestJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join),
joined_schemas_ctx_(this),
output_right_only_(output_right_only) {
output_type_ = left->GetOutputType();
InitOuptput();
RegisterFunctionInfo();
}

Expand All @@ -1315,11 +1340,11 @@ class PhysicalRequestJoinNode : public PhysicalBinaryNode {
const node::ExprNode *condition,
const node::ExprListNode *left_keys,
const node::ExprListNode *right_keys)
: PhysicalBinaryNode(left, right, kPhysicalOpRequestJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, condition, left_keys, right_keys),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();
RegisterFunctionInfo();
}
PhysicalRequestJoinNode(PhysicalOpNode *left, PhysicalOpNode *right,
Expand All @@ -1328,11 +1353,11 @@ class PhysicalRequestJoinNode : public PhysicalBinaryNode {
const node::ExprNode *condition,
const node::ExprListNode *left_keys,
const node::ExprListNode *right_keys)
: PhysicalBinaryNode(left, right, kPhysicalOpRequestJoin, false),
: PhysicalBinaryNode(left, right, kConcreteNodeKind, false),
join_(join_type, orders, condition, left_keys, right_keys),
joined_schemas_ctx_(this),
output_right_only_(false) {
output_type_ = left->GetOutputType();
InitOuptput();
RegisterFunctionInfo();
}

Expand Down Expand Up @@ -1363,6 +1388,26 @@ class PhysicalRequestJoinNode : public PhysicalBinaryNode {
Join join_;
SchemasContext joined_schemas_ctx_;
const bool output_right_only_;

private:
void InitOuptput() {
switch (join_.join_type_) {
case node::kJoinTypeLast:
case node::kJoinTypeConcat: {
output_type_ = GetProducer(0)->GetOutputType();
break;
}
default: {
// standard SQL JOINs, always treat as a table output
if (GetProducer(0)->GetOutputType() == kSchemaTypeGroup) {
output_type_ = kSchemaTypeGroup;
} else {
output_type_ = kSchemaTypeTable;
}
break;
}
}
}
};

class PhysicalUnionNode : public PhysicalBinaryNode {
Expand Down
11 changes: 7 additions & 4 deletions hybridse/src/planv2/ast_node_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1113,13 +1113,13 @@ base::Status ConvertTableExpressionNode(const zetasql::ASTTableExpression* root,
node::TableRefNode* right = nullptr;
node::OrderByNode* order_by = nullptr;
node::ExprNode* condition = nullptr;
node::JoinType join_type = node::JoinType::kJoinTypeInner;
CHECK_STATUS(ConvertTableExpressionNode(join->lhs(), node_manager, &left))
CHECK_STATUS(ConvertTableExpressionNode(join->rhs(), node_manager, &right))
CHECK_STATUS(ConvertOrderBy(join->order_by(), node_manager, &order_by))
if (nullptr != join->on_clause()) {
CHECK_STATUS(ConvertExprNode(join->on_clause()->expression(), node_manager, &condition))
}
node::JoinType join_type = node::JoinType::kJoinTypeInner;
switch (join->join_type()) {
case zetasql::ASTJoin::JoinType::FULL: {
join_type = node::JoinType::kJoinTypeFull;
Expand All @@ -1137,12 +1137,14 @@ base::Status ConvertTableExpressionNode(const zetasql::ASTTableExpression* root,
join_type = node::JoinType::kJoinTypeLast;
break;
}
case zetasql::ASTJoin::JoinType::INNER: {
case zetasql::ASTJoin::JoinType::INNER:
case zetasql::ASTJoin::JoinType::DEFAULT_JOIN_TYPE: {
join_type = node::JoinType::kJoinTypeInner;
break;
}
case zetasql::ASTJoin::JoinType::COMMA: {
join_type = node::JoinType::kJoinTypeComma;
case zetasql::ASTJoin::JoinType::COMMA:
case zetasql::ASTJoin::JoinType::CROSS: {
join_type = node::JoinType::kJoinTypeCross;
break;
}
default: {
Expand Down Expand Up @@ -1290,6 +1292,7 @@ base::Status ConvertQueryExpr(const zetasql::ASTQueryExpression* query_expressio
if (nullptr != select_query->from_clause()) {
CHECK_STATUS(ConvertTableExpressionNode(select_query->from_clause()->table_expression(), node_manager,
&table_ref_node))
// TODO(.): dont mark table ref as a list, it never happens
if (nullptr != table_ref_node) {
tableref_list_ptr = node_manager->MakeNodeList();
tableref_list_ptr->PushBack(table_ref_node);
Expand Down
Loading

0 comments on commit 9ec4768

Please sign in to comment.