2022-08-23 09:50:02 +00:00
|
|
|
#pragma once
|
|
|
|
|
2022-08-31 15:21:17 +00:00
|
|
|
#include <Core/NamesAndTypes.h>
|
|
|
|
#include <Core/Field.h>
|
|
|
|
|
2022-08-23 09:50:02 +00:00
|
|
|
#include <Analyzer/Identifier.h>
|
|
|
|
#include <Analyzer/IQueryTreeNode.h>
|
|
|
|
#include <Analyzer/ListNode.h>
|
2022-09-04 15:20:59 +00:00
|
|
|
#include <Analyzer/TableExpressionModifiers.h>
|
2022-08-23 09:50:02 +00:00
|
|
|
|
|
|
|
#include <Parsers/SelectUnionMode.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2022-09-06 15:25:52 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int UNSUPPORTED_METHOD;
|
|
|
|
}
|
|
|
|
|
2022-08-23 09:50:02 +00:00
|
|
|
/** Union node represents union of queries in query tree.
|
2022-10-17 17:46:30 +00:00
|
|
|
*
|
|
|
|
* Example: (SELECT id FROM test_table) UNION ALL (SELECT id FROM test_table_2);
|
|
|
|
* Example: (SELECT id FROM test_table) UNION DISTINCT (SELECT id FROM test_table_2);
|
|
|
|
* Example: (SELECT id FROM test_table) EXCEPT ALL (SELECT id FROM test_table_2);
|
|
|
|
* Example: (SELECT id FROM test_table) EXCEPT DISTINCT (SELECT id FROM test_table_2);
|
|
|
|
* Example: (SELECT id FROM test_table) INTERSECT ALL (SELECT id FROM test_table_2);
|
|
|
|
* Example: (SELECT id FROM test_table) INTERSECT DISTINCT (SELECT id FROM test_table_2);
|
|
|
|
*
|
2022-10-19 10:25:27 +00:00
|
|
|
* Union node can be used as CTE.
|
|
|
|
* Example: WITH cte_subquery AS ((SELECT id FROM test_table) UNION ALL (SELECT id FROM test_table_2)) SELECT * FROM cte_subquery;
|
|
|
|
*
|
|
|
|
* Union node can be used as scalar subquery.
|
|
|
|
* Example: SELECT (SELECT 1 UNION DISTINCT SELECT 1);
|
|
|
|
*
|
2022-10-17 17:46:30 +00:00
|
|
|
* During query analysis pass union node queries must be resolved.
|
2022-08-23 09:50:02 +00:00
|
|
|
*/
|
|
|
|
class UnionNode;
|
|
|
|
using UnionNodePtr = std::shared_ptr<UnionNode>;
|
|
|
|
|
|
|
|
class UnionNode final : public IQueryTreeNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit UnionNode();
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Returns true if union node is subquery, false otherwise
|
2022-08-23 09:50:02 +00:00
|
|
|
bool isSubquery() const
|
|
|
|
{
|
|
|
|
return is_subquery;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Set union node is subquery value
|
2022-08-23 09:50:02 +00:00
|
|
|
void setIsSubquery(bool is_subquery_value)
|
|
|
|
{
|
|
|
|
is_subquery = is_subquery_value;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Returns true if union node is CTE, false otherwise
|
2022-08-23 09:50:02 +00:00
|
|
|
bool isCTE() const
|
|
|
|
{
|
|
|
|
return is_cte;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Set union node is CTE
|
2022-08-23 09:50:02 +00:00
|
|
|
void setIsCTE(bool is_cte_value)
|
|
|
|
{
|
|
|
|
is_cte = is_cte_value;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union node CTE name
|
2022-08-23 09:50:02 +00:00
|
|
|
const std::string & getCTEName() const
|
|
|
|
{
|
|
|
|
return cte_name;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Set union node CTE name
|
2022-08-23 09:50:02 +00:00
|
|
|
void setCTEName(std::string cte_name_value)
|
|
|
|
{
|
|
|
|
cte_name = std::move(cte_name_value);
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union mode
|
2022-08-23 09:50:02 +00:00
|
|
|
SelectUnionMode getUnionMode() const
|
|
|
|
{
|
|
|
|
return union_mode;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Set union mode value
|
2022-08-23 09:50:02 +00:00
|
|
|
void setUnionMode(SelectUnionMode union_mode_value)
|
|
|
|
{
|
|
|
|
union_mode = union_mode_value;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union modes
|
2022-08-23 09:50:02 +00:00
|
|
|
const SelectUnionModes & getUnionModes() const
|
|
|
|
{
|
|
|
|
return union_modes;
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Set union modes value
|
2022-08-23 09:50:02 +00:00
|
|
|
void setUnionModes(const SelectUnionModes & union_modes_value)
|
|
|
|
{
|
|
|
|
union_modes = union_modes_value;
|
|
|
|
union_modes_set = SelectUnionModesSet(union_modes.begin(), union_modes.end());
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union node queries
|
|
|
|
const ListNode & getQueries() const
|
2022-08-23 09:50:02 +00:00
|
|
|
{
|
2022-10-17 17:46:30 +00:00
|
|
|
return children[queries_child_index]->as<const ListNode &>();
|
2022-08-23 09:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union node queries
|
|
|
|
ListNode & getQueries()
|
2022-08-23 09:50:02 +00:00
|
|
|
{
|
2022-10-17 17:46:30 +00:00
|
|
|
return children[queries_child_index]->as<ListNode &>();
|
2022-08-23 09:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union node queries node
|
|
|
|
const QueryTreeNodePtr & getQueriesNode() const
|
2022-08-23 09:50:02 +00:00
|
|
|
{
|
2022-10-17 17:46:30 +00:00
|
|
|
return children[queries_child_index];
|
2022-08-23 09:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Get union node queries node
|
|
|
|
QueryTreeNodePtr & getQueriesNode()
|
2022-08-23 09:50:02 +00:00
|
|
|
{
|
2022-10-17 17:46:30 +00:00
|
|
|
return children[queries_child_index];
|
2022-08-23 09:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-09-04 15:20:59 +00:00
|
|
|
/// Return true if union node has table expression modifiers, false otherwise
|
|
|
|
bool hasTableExpressionModifiers() const
|
|
|
|
{
|
|
|
|
return table_expression_modifiers.has_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get table expression modifiers
|
2022-10-19 10:25:27 +00:00
|
|
|
const std::optional<TableExpressionModifiers> & getTableExpressionModifiers() const
|
2022-09-04 15:20:59 +00:00
|
|
|
{
|
|
|
|
return table_expression_modifiers;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set table expression modifiers
|
|
|
|
void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value)
|
|
|
|
{
|
|
|
|
table_expression_modifiers = std::move(table_expression_modifiers_value);
|
|
|
|
}
|
|
|
|
|
2022-10-17 17:46:30 +00:00
|
|
|
/// Compute union node projection columns
|
2022-08-31 15:21:17 +00:00
|
|
|
NamesAndTypes computeProjectionColumns() const;
|
2022-08-23 09:50:02 +00:00
|
|
|
|
|
|
|
QueryTreeNodeType getNodeType() const override
|
|
|
|
{
|
|
|
|
return QueryTreeNodeType::UNION;
|
|
|
|
}
|
|
|
|
|
2022-08-31 15:21:17 +00:00
|
|
|
DataTypePtr getResultType() const override
|
|
|
|
{
|
|
|
|
if (constant_value)
|
|
|
|
return constant_value->getType();
|
|
|
|
|
|
|
|
throw Exception(ErrorCodes::UNSUPPORTED_METHOD, "Method getResultType is not supported for non scalar union node");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Perform constant folding for scalar union node
|
|
|
|
void performConstantFolding(ConstantValuePtr constant_folded_value)
|
|
|
|
{
|
|
|
|
constant_value = std::move(constant_folded_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantValuePtr getConstantValueOrNull() const override
|
|
|
|
{
|
|
|
|
return constant_value;
|
|
|
|
}
|
|
|
|
|
2022-08-23 09:50:02 +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-23 09:50:02 +00:00
|
|
|
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
|
|
|
|
|
|
|
|
void updateTreeHashImpl(HashState &) const override;
|
|
|
|
|
|
|
|
QueryTreeNodePtr cloneImpl() const override;
|
|
|
|
|
2022-10-10 10:25:58 +00:00
|
|
|
ASTPtr toASTImpl() const override;
|
|
|
|
|
2022-08-23 09:50:02 +00:00
|
|
|
private:
|
|
|
|
bool is_subquery = false;
|
|
|
|
bool is_cte = false;
|
|
|
|
std::string cte_name;
|
|
|
|
SelectUnionMode union_mode;
|
|
|
|
SelectUnionModes union_modes;
|
|
|
|
SelectUnionModesSet union_modes_set;
|
2022-08-31 15:21:17 +00:00
|
|
|
ConstantValuePtr constant_value;
|
2022-09-04 15:20:59 +00:00
|
|
|
std::optional<TableExpressionModifiers> table_expression_modifiers;
|
2022-08-23 09:50:02 +00:00
|
|
|
|
|
|
|
static constexpr size_t queries_child_index = 0;
|
|
|
|
static constexpr size_t children_size = queries_child_index + 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|