2022-08-15 16:34:10 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Core/Joins.h>
|
|
|
|
|
|
|
|
#include <Storages/IStorage_fwd.h>
|
|
|
|
#include <Storages/TableLockHolder.h>
|
|
|
|
#include <Storages/StorageSnapshot.h>
|
|
|
|
|
|
|
|
#include <Interpreters/Context_fwd.h>
|
|
|
|
#include <Interpreters/StorageID.h>
|
|
|
|
|
|
|
|
#include <Analyzer/IQueryTreeNode.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2022-10-07 10:44:28 +00:00
|
|
|
/** Join node represents join in query tree.
|
|
|
|
*
|
|
|
|
* For JOIN without join expression, JOIN expression is null.
|
|
|
|
* Example: SELECT id FROM test_table_1 AS t1, test_table_2 AS t2;
|
|
|
|
*
|
|
|
|
* For JOIN with USING, JOIN expression contains list of identifier nodes. These nodes must be resolved
|
|
|
|
* during query analysis pass.
|
|
|
|
* Example: SELECT id FROM test_table_1 AS t1 INNER JOIN test_table_2 AS t2 USING (id);
|
|
|
|
*
|
|
|
|
* For JOIN with ON, JOIN expression contains single expression.
|
2022-10-19 10:25:27 +00:00
|
|
|
* Example: SELECT id FROM test_table_1 AS t1 INNER JOIN test_table_2 AS t2 ON t1.id = t2.id;
|
2022-08-15 16:34:10 +00:00
|
|
|
*/
|
|
|
|
class JoinNode;
|
|
|
|
using JoinNodePtr = std::shared_ptr<JoinNode>;
|
|
|
|
|
|
|
|
class JoinNode final : public IQueryTreeNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Construct join node with left table expression, right table expression and join expression.
|
|
|
|
* Example: SELECT id FROM test_table_1 INNER JOIN test_table_2 ON expression.
|
|
|
|
*
|
|
|
|
* test_table_1 - left table expression.
|
|
|
|
* test_table_2 - right table expression.
|
2022-10-19 10:25:27 +00:00
|
|
|
* expression - join expression.
|
2022-08-15 16:34:10 +00:00
|
|
|
*/
|
|
|
|
JoinNode(QueryTreeNodePtr left_table_expression_,
|
|
|
|
QueryTreeNodePtr right_table_expression_,
|
|
|
|
QueryTreeNodePtr join_expression_,
|
|
|
|
JoinLocality locality_,
|
|
|
|
JoinStrictness strictness_,
|
|
|
|
JoinKind kind_);
|
|
|
|
|
|
|
|
/// Get left table expression
|
|
|
|
const QueryTreeNodePtr & getLeftTableExpression() const
|
|
|
|
{
|
|
|
|
return children[left_table_expression_child_index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get left table expression
|
|
|
|
QueryTreeNodePtr & getLeftTableExpression()
|
|
|
|
{
|
|
|
|
return children[left_table_expression_child_index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get right table expression
|
|
|
|
const QueryTreeNodePtr & getRightTableExpression() const
|
|
|
|
{
|
|
|
|
return children[right_table_expression_child_index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get right table expression
|
|
|
|
QueryTreeNodePtr & getRightTableExpression()
|
|
|
|
{
|
|
|
|
return children[right_table_expression_child_index];
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Returns true if join has join expression, false otherwise
|
|
|
|
bool hasJoinExpression() const
|
|
|
|
{
|
|
|
|
return children[join_expression_child_index] != nullptr;
|
|
|
|
}
|
|
|
|
|
2022-08-15 16:34:10 +00:00
|
|
|
/// Get join expression
|
|
|
|
const QueryTreeNodePtr & getJoinExpression() const
|
|
|
|
{
|
|
|
|
return children[join_expression_child_index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get join expression
|
|
|
|
QueryTreeNodePtr & getJoinExpression()
|
|
|
|
{
|
|
|
|
return children[join_expression_child_index];
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Returns true if join has USING join expression, false otherwise
|
2022-08-15 16:34:10 +00:00
|
|
|
bool isUsingJoinExpression() const
|
|
|
|
{
|
2022-10-19 10:25:27 +00:00
|
|
|
return hasJoinExpression() && getJoinExpression()->getNodeType() == QueryTreeNodeType::LIST;
|
2022-08-15 16:34:10 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Returns true if join has ON join expression, false otherwise
|
2022-08-15 16:34:10 +00:00
|
|
|
bool isOnJoinExpression() const
|
|
|
|
{
|
2022-10-19 10:25:27 +00:00
|
|
|
return hasJoinExpression() && getJoinExpression()->getNodeType() != QueryTreeNodeType::LIST;
|
2022-08-15 16:34:10 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Get join locality
|
2022-08-15 16:34:10 +00:00
|
|
|
JoinLocality getLocality() const
|
|
|
|
{
|
|
|
|
return locality;
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Get join strictness
|
2022-08-15 16:34:10 +00:00
|
|
|
JoinStrictness getStrictness() const
|
|
|
|
{
|
|
|
|
return strictness;
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Get join kind
|
2022-08-15 16:34:10 +00:00
|
|
|
JoinKind getKind() const
|
|
|
|
{
|
|
|
|
return kind;
|
|
|
|
}
|
|
|
|
|
2022-10-19 10:25:27 +00:00
|
|
|
/// Convert join node to ASTTableJoin
|
2022-08-15 16:34:10 +00:00
|
|
|
ASTPtr toASTTableJoin() const;
|
|
|
|
|
|
|
|
QueryTreeNodeType getNodeType() const override
|
|
|
|
{
|
|
|
|
return QueryTreeNodeType::JOIN;
|
|
|
|
}
|
|
|
|
|
2023-02-20 11:49:57 +00:00
|
|
|
/*
|
|
|
|
* Convert CROSS to INNER JOIN - changes JOIN kind and sets a new join expression
|
|
|
|
* (that was moved from WHERE clause).
|
|
|
|
* Expects the current kind to be CROSS (and join expression to be null because of that).
|
|
|
|
*/
|
2023-02-13 17:41:39 +00:00
|
|
|
void crossToInner(const QueryTreeNodePtr & join_expression_);
|
|
|
|
|
2022-08-15 16:34:10 +00:00
|
|
|
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
|
|
|
|
|
2022-10-10 10:25:58 +00:00
|
|
|
protected:
|
2022-08-15 16:34:10 +00:00
|
|
|
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
|
|
|
|
|
|
|
|
void updateTreeHashImpl(HashState & state) const override;
|
|
|
|
|
|
|
|
QueryTreeNodePtr cloneImpl() const override;
|
|
|
|
|
2022-10-10 10:25:58 +00:00
|
|
|
ASTPtr toASTImpl() const override;
|
|
|
|
|
2022-08-15 16:34:10 +00:00
|
|
|
private:
|
|
|
|
JoinLocality locality = JoinLocality::Unspecified;
|
|
|
|
JoinStrictness strictness = JoinStrictness::Unspecified;
|
|
|
|
JoinKind kind = JoinKind::Inner;
|
|
|
|
|
|
|
|
static constexpr size_t left_table_expression_child_index = 0;
|
|
|
|
static constexpr size_t right_table_expression_child_index = 1;
|
|
|
|
static constexpr size_t join_expression_child_index = 2;
|
|
|
|
static constexpr size_t children_size = join_expression_child_index + 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|