1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/parser/expression/operator_expression.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/parser/parsed_expression.hpp"
12#include "duckdb/common/vector.hpp"
13#include "duckdb/common/string_util.hpp"
14#include "duckdb/parser/qualified_name.hpp"
15
16namespace duckdb {
17//! Represents a built-in operator expression
18class OperatorExpression : public ParsedExpression {
19public:
20 static constexpr const ExpressionClass TYPE = ExpressionClass::OPERATOR;
21
22public:
23 DUCKDB_API explicit OperatorExpression(ExpressionType type, unique_ptr<ParsedExpression> left = nullptr,
24 unique_ptr<ParsedExpression> right = nullptr);
25 DUCKDB_API OperatorExpression(ExpressionType type, vector<unique_ptr<ParsedExpression>> children);
26
27 vector<unique_ptr<ParsedExpression>> children;
28
29public:
30 string ToString() const override;
31
32 static bool Equal(const OperatorExpression &a, const OperatorExpression &b);
33
34 unique_ptr<ParsedExpression> Copy() const override;
35
36 void Serialize(FieldWriter &writer) const override;
37 static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
38 void FormatSerialize(FormatSerializer &serializer) const override;
39 static unique_ptr<ParsedExpression> FormatDeserialize(ExpressionType type, FormatDeserializer &deserializer);
40
41public:
42 template <class T, class BASE>
43 static string ToString(const T &entry) {
44 auto op = ExpressionTypeToOperator(entry.type);
45 if (!op.empty()) {
46 // use the operator string to represent the operator
47 D_ASSERT(entry.children.size() == 2);
48 return entry.children[0]->ToString() + " " + op + " " + entry.children[1]->ToString();
49 }
50 switch (entry.type) {
51 case ExpressionType::COMPARE_IN:
52 case ExpressionType::COMPARE_NOT_IN: {
53 string op_type = entry.type == ExpressionType::COMPARE_IN ? " IN " : " NOT IN ";
54 string in_child = entry.children[0]->ToString();
55 string child_list = "(";
56 for (idx_t i = 1; i < entry.children.size(); i++) {
57 if (i > 1) {
58 child_list += ", ";
59 }
60 child_list += entry.children[i]->ToString();
61 }
62 child_list += ")";
63 return "(" + in_child + op_type + child_list + ")";
64 }
65 case ExpressionType::OPERATOR_NOT: {
66 string result = "(";
67 result += ExpressionTypeToString(entry.type);
68 result += " ";
69 result += StringUtil::Join(entry.children, entry.children.size(), ", ",
70 [](const unique_ptr<BASE> &child) { return child->ToString(); });
71 result += ")";
72 return result;
73 }
74 case ExpressionType::GROUPING_FUNCTION:
75 case ExpressionType::OPERATOR_COALESCE: {
76 string result = ExpressionTypeToString(entry.type);
77 result += "(";
78 result += StringUtil::Join(entry.children, entry.children.size(), ", ",
79 [](const unique_ptr<BASE> &child) { return child->ToString(); });
80 result += ")";
81 return result;
82 }
83 case ExpressionType::OPERATOR_IS_NULL:
84 return "(" + entry.children[0]->ToString() + " IS NULL)";
85 case ExpressionType::OPERATOR_IS_NOT_NULL:
86 return "(" + entry.children[0]->ToString() + " IS NOT NULL)";
87 case ExpressionType::ARRAY_EXTRACT:
88 return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + "]";
89 case ExpressionType::ARRAY_SLICE:
90 return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + ":" +
91 entry.children[2]->ToString() + "]";
92 case ExpressionType::STRUCT_EXTRACT: {
93 if (entry.children[1]->type != ExpressionType::VALUE_CONSTANT) {
94 return string();
95 }
96 auto child_string = entry.children[1]->ToString();
97 D_ASSERT(child_string.size() >= 3);
98 D_ASSERT(child_string[0] == '\'' && child_string[child_string.size() - 1] == '\'');
99 return StringUtil::Format("(%s).%s", entry.children[0]->ToString(),
100 SQLIdentifier(child_string.substr(1, child_string.size() - 2)));
101 }
102 case ExpressionType::ARRAY_CONSTRUCTOR: {
103 string result = "(ARRAY[";
104 result += StringUtil::Join(entry.children, entry.children.size(), ", ",
105 [](const unique_ptr<BASE> &child) { return child->ToString(); });
106 result += "])";
107 return result;
108 }
109 default:
110 throw InternalException("Unrecognized operator type");
111 }
112 }
113};
114
115} // namespace duckdb
116