Skip to content

Commit 4f21323

Browse files
committed
feat: introduce apply operator for table-valued functions.
1 parent 9ded4ba commit 4f21323

File tree

10 files changed

+443
-2
lines changed

10 files changed

+443
-2
lines changed

include/takatori/relation/apply.h

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#pragma once
2+
3+
#include <initializer_list>
4+
#include <vector>
5+
6+
#include "expression.h"
7+
#include "expression_kind.h"
8+
#include "apply_kind.h"
9+
10+
#include <takatori/descriptor/function.h>
11+
#include <takatori/descriptor/variable.h>
12+
13+
#include <takatori/tree/tree_element_vector.h>
14+
15+
#include <takatori/scalar/expression.h>
16+
17+
#include <takatori/util/clone_tag.h>
18+
#include <takatori/util/meta_type.h>
19+
#include <takatori/util/reference_vector.h>
20+
#include <takatori/util/rvalue_initializer_list.h>
21+
22+
namespace takatori::relation {
23+
24+
/**
25+
* @brief represents a table-valued function application expression.
26+
*/
27+
class apply final : public expression {
28+
public:
29+
/// @brief the kind of this relation.
30+
static constexpr expression_kind tag = expression_kind::apply;
31+
32+
/// @brief the apply operator kind type.
33+
using operator_kind_type = apply_kind;
34+
35+
/**
36+
* @brief creates a new instance.
37+
* @param operator_kind the apply operator kind
38+
* @param function the descriptor of target function, must be a table-valued
39+
* @param arguments the function arguments
40+
* @param columns the output columns definition.
41+
* Each column position corresponds to the output columns of the function resulting table.
42+
*/
43+
explicit apply(
44+
operator_kind_type operator_kind,
45+
descriptor::function function,
46+
util::reference_vector<scalar::expression> arguments,
47+
std::vector<descriptor::variable> columns) noexcept;
48+
49+
/**
50+
* @brief creates a new instance.
51+
* @param function the descriptor of target function, must be a table-valued
52+
* @param arguments the function arguments
53+
* @param columns the output columns definition.
54+
* Each column position corresponds to the output columns of the function resulting table.
55+
* @param operator_kind the apply operator kind
56+
* @attention this may take copies of given expressions
57+
*/
58+
apply(
59+
descriptor::function function,
60+
util::rvalue_initializer_list<scalar::expression> arguments,
61+
std::initializer_list<descriptor::variable> columns,
62+
operator_kind_type operator_kind = operator_kind_type::cross);
63+
64+
/**
65+
* @brief creates a new object.
66+
* @param other the copy source
67+
*/
68+
explicit apply(util::clone_tag_t, apply const& other);
69+
70+
/**
71+
* @brief creates a new object.
72+
* @param other the move source
73+
*/
74+
explicit apply(util::clone_tag_t, apply&& other);
75+
76+
[[nodiscard]] expression_kind kind() const noexcept override;
77+
[[nodiscard]] util::sequence_view<input_port_type> input_ports() noexcept override;
78+
[[nodiscard]] util::sequence_view<input_port_type const> input_ports() const noexcept override;
79+
[[nodiscard]] util::sequence_view<output_port_type> output_ports() noexcept override;
80+
[[nodiscard]] util::sequence_view<output_port_type const> output_ports() const noexcept override;
81+
[[nodiscard]] apply* clone() const& override;
82+
[[nodiscard]] apply* clone() && override;
83+
84+
/**
85+
* @brief returns the input port.
86+
* @return the input port
87+
*/
88+
[[nodiscard]] input_port_type& input() noexcept;
89+
90+
/// @copydoc input()
91+
[[nodiscard]] input_port_type const& input() const noexcept;
92+
93+
/**
94+
* @brief returns the output port.
95+
* @return the output port
96+
*/
97+
[[nodiscard]] output_port_type& output() noexcept;
98+
99+
/// @copydoc output()
100+
[[nodiscard]] output_port_type const& output() const noexcept;
101+
102+
/**
103+
* @brief returns the kind of this apply expression.
104+
* @return the kind of this apply expression.
105+
*/
106+
[[nodiscard]] operator_kind_type operator_kind() const noexcept;
107+
108+
/**
109+
* @brief sets the operator kind of this apply expression.
110+
* @param kind the operator kind
111+
* @return the operator kind
112+
*/
113+
apply& operator_kind(operator_kind_type kind) noexcept;
114+
115+
/**
116+
* @brief returns the descriptor of target function.
117+
* @return the descriptor of target function.
118+
* @note the descriptor represents a table-valued function.
119+
*/
120+
[[nodiscard]] descriptor::function& function() noexcept;
121+
122+
/// @copydoc function()
123+
[[nodiscard]] descriptor::function const& function() const noexcept;
124+
125+
/**
126+
* @brief returns the function arguments.
127+
* @return the function arguments
128+
*/
129+
[[nodiscard]] tree::tree_element_vector<scalar::expression>& arguments() noexcept;
130+
131+
/// @copydoc arguments()
132+
[[nodiscard]] tree::tree_element_vector<scalar::expression> const& arguments() const noexcept;
133+
134+
/**
135+
* @brief returns the output columns definition.
136+
* @details each column position corresponds to the output columns of the function resulting table.
137+
* @return the output columns definition.
138+
*/
139+
[[nodiscard]] std::vector<descriptor::variable>& columns() noexcept;
140+
141+
/// @copydoc columns()
142+
[[nodiscard]] std::vector<descriptor::variable> const& columns() const noexcept;
143+
144+
/**
145+
* @brief returns whether the two elements are equivalent.
146+
* @param a the first element
147+
* @param b the second element
148+
* @return true if a == b
149+
* @return false otherwise
150+
*/
151+
friend bool operator==(apply const& a, apply const& b) noexcept;
152+
153+
/**
154+
* @brief returns whether the two elements are different.
155+
* @param a the first element
156+
* @param b the second element
157+
* @return true if a != b
158+
* @return false otherwise
159+
*/
160+
friend bool operator!=(apply const& a, apply const& b) noexcept;
161+
162+
/**
163+
* @brief appends string representation of the given value.
164+
* @param out the target output
165+
* @param value the target value
166+
* @return the output
167+
*/
168+
friend std::ostream& operator<<(std::ostream& out, apply const& value);
169+
170+
protected:
171+
[[nodiscard]] bool equals(expression const& other) const noexcept override;
172+
std::ostream& print_to(std::ostream& out) const override;
173+
174+
private:
175+
input_port_type input_;
176+
output_port_type output_;
177+
operator_kind_type operator_kind_;
178+
descriptor::function function_;
179+
tree::tree_element_vector<scalar::expression> arguments_;
180+
std::vector<descriptor::variable> columns_;
181+
};
182+
183+
/**
184+
* @brief type_of for apply.
185+
*/
186+
template<> struct type_of<apply::tag> : util::meta_type<apply> {};
187+
188+
189+
} // namespace takatori::relation
190+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <ostream>
4+
#include <string_view>
5+
6+
namespace takatori::relation {
7+
8+
/**
9+
* @brief represents a apply operator kind.
10+
*/
11+
enum class apply_kind {
12+
/**
13+
* @brief represents a CROSS APPLY (a.k.a. `INNER LATERAL JOIN`).
14+
*/
15+
cross,
16+
17+
/**
18+
* @brief represents an OUTER APPLY (a.k.a. `LEFT LATERAL JOIN`).
19+
*/
20+
outer,
21+
};
22+
23+
/**
24+
* @brief returns string representation of the value.
25+
* @param value the target value
26+
* @return the corresponded string representation
27+
*/
28+
constexpr std::string_view to_string_view(apply_kind value) noexcept {
29+
using namespace std::string_view_literals;
30+
using kind = apply_kind;
31+
switch (value) {
32+
case kind::cross: return "cross"sv;
33+
case kind::outer: return "outer"sv;
34+
}
35+
std::abort();
36+
}
37+
38+
/**
39+
* @brief appends string representation of the given value.
40+
* @param out the target output
41+
* @param value the target value
42+
* @return the output
43+
*/
44+
inline std::ostream& operator<<(std::ostream& out, apply_kind value) {
45+
return out << to_string_view(value);
46+
}
47+
48+
} // namespace takatori::relation

include/takatori/relation/expression_kind.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ enum class expression_kind {
2828
join_find,
2929
/// @brief join input with rows in storage.
3030
join_scan,
31+
/// @brief applies a table-valued function and correlated join with its result.
32+
apply,
3133

3234
// tuple by tuple operations
3335
/// @brief adds columns into relation.
@@ -122,6 +124,7 @@ constexpr inline std::string_view to_string_view(expression_kind value) noexcept
122124
case kind::join_relation: return "join_relation"sv;
123125
case kind::join_find: return "join_find"sv;
124126
case kind::join_scan: return "join_scan"sv;
127+
case kind::apply: return "apply"sv;
125128
case kind::project: return "project"sv;
126129
case kind::filter: return "filter"sv;
127130
case kind::buffer: return "buffer"sv;
@@ -174,6 +177,7 @@ inline constexpr bool is_available_in_intermediate_plan(expression_kind value) {
174177
case kind::join_relation:
175178
case kind::join_find:
176179
case kind::join_scan:
180+
case kind::apply:
177181
case kind::project:
178182
case kind::filter:
179183
case kind::buffer:
@@ -221,6 +225,7 @@ inline constexpr bool is_available_in_step_plan(expression_kind value) {
221225
case kind::scan:
222226
case kind::join_find:
223227
case kind::join_scan:
228+
case kind::apply:
224229
case kind::project:
225230
case kind::filter:
226231
case kind::buffer:

include/takatori/relation/intermediate/dispatch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "../scan.h"
1111
#include "../join_find.h"
1212
#include "../join_scan.h"
13+
#include "../apply.h"
1314
#include "../project.h"
1415
#include "../filter.h"
1516
#include "../buffer.h"
@@ -53,6 +54,7 @@ inline auto dispatch_expression(Callback&& callback, E&& object, Args&&... args)
5354
case scan::tag: return util::polymorphic_callback<scan>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5455
case join_find::tag: return util::polymorphic_callback<join_find>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5556
case join_scan::tag: return util::polymorphic_callback<join_scan>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
57+
case apply::tag: return util::polymorphic_callback<apply>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5658
case project::tag: return util::polymorphic_callback<project>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5759
case filter::tag: return util::polymorphic_callback<filter>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5860
case buffer::tag: return util::polymorphic_callback<buffer>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);

include/takatori/relation/step/dispatch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "../scan.h"
1010
#include "../join_find.h"
1111
#include "../join_scan.h"
12+
#include "../apply.h"
1213
#include "../project.h"
1314
#include "../filter.h"
1415
#include "../buffer.h"
@@ -53,6 +54,7 @@ inline auto dispatch_expression(Callback&& callback, E&& object, Args&&... args)
5354
case scan::tag: return util::polymorphic_callback<scan>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5455
case join_find::tag: return util::polymorphic_callback<join_find>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5556
case join_scan::tag: return util::polymorphic_callback<join_scan>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
57+
case apply::tag: return util::polymorphic_callback<apply>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5658
case project::tag: return util::polymorphic_callback<project>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5759
case filter::tag: return util::polymorphic_callback<filter>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);
5860
case buffer::tag: return util::polymorphic_callback<buffer>(std::forward<Callback>(callback), std::forward<E>(object), std::forward<Args>(args)...);

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ add_library(takatori
131131
takatori/relation/intermediate/join.cpp
132132
takatori/relation/join_find.cpp
133133
takatori/relation/join_scan.cpp
134+
takatori/relation/apply.cpp
134135

135136
# relation - tuple by tuple operations
136137
takatori/relation/project.cpp

0 commit comments

Comments
 (0)