6#include "utils/pfr.hpp"
8#if PG_MAJORVERSION_NUM < 16
9typedef bool (*tree_walker_callback)(Node *node,
void *context);
14using node_tag = ::NodeTag;
17concept node_tagged = std::is_standard_layout_v<T> &&
requires(T t) {
18 { t.type } -> std::convertible_to<node_tag>;
19} && (offsetof(T,
type) == 0);
23 { t.xpr } -> std::convertible_to<::Expr>;
24} && (offsetof(T, xpr) == 0);
33concept node_inherited = std::is_standard_layout_v<std::remove_cvref_t<T>> &&
requires(T t) {
35 node_xpr_tagged<std::remove_cvref_t<
decltype(boost::pfr::get<0>(t))>> ||
43 static inline bool is(
auto &
node) {
return false; }
48#define node_mapping(name) \
51 using underlying_type = ::name; \
52 static constexpr inline node_tag tag = T_##name; \
53 name(underlying_type v) : val(v) {} \
54 name() { reinterpret_cast<node_tag &>(val) = T_##name; } \
55 underlying_type &as_ref() { return val; } \
56 underlying_type *as_ptr() { return &val; } \
59 [[maybe_unused]] underlying_type val{}; \
62 static_assert((sizeof(name) == sizeof(::name)) && (alignof(name) == alignof(::name))); \
63 static_assert(std::is_standard_layout_v<name>); \
64 static_assert(std::is_aggregate_v<name>); \
65 template <> struct node_coverage<::name> { \
66 using type = nodes::name; \
68 template <> struct node_tag_traits<node_tag::T_##name> { \
69 using type = nodes::name; \
71 template <> struct node_traits<nodes::name> { \
72 static inline constexpr node_tag tag = node_tag::T_##name; \
73 static inline bool is(::Node *node) { \
74 return *reinterpret_cast<node_tag *>(node) == node_tag::T_##name; \
76 static inline bool is(::name *node) { \
77 return *reinterpret_cast<node_tag *>(node) == node_tag::T_##name; \
79 static inline bool is(void *node) { \
80 return *reinterpret_cast<node_tag *>(node) == node_tag::T_##name; \
82 static inline bool is(nodes::name *node) { return true; } \
83 static inline bool is(nodes::name &node) { return true; } \
84 static inline bool is(auto &node) { return false; } \
85 static inline nodes::name *allocate(abstract_memory_context &&ctx = memory_context()) { \
86 auto ptr = ctx.alloc<nodes::name>(); \
87 reinterpret_cast<node_tag &>(ptr) = tag; \
92#define node_mapping_no_node_traits(name) \
94 using name = node_coverage<::name>::type; \
96 template <> struct node_tag_traits<node_tag::T_##name> { \
97 using type = nodes::name; \
98 static_assert(::cppgres::node<name>); \
101#include "node_mapping_table.hpp"
110#define node_dispatch(name) \
113 covering_node<std::remove_pointer_t<decltype(reinterpret_cast<nodes::name *>(node))>>); \
114 visitor(*reinterpret_cast<nodes::name *>(node)); \
119 std::is_class_v<node_traits<T>> &&
requires {
typename T::underlying_type; };
121template <
typename Visitor>
void visit_node(
covering_node auto node, Visitor &&visitor) {
127 requires {
typename node_coverage<T>::type::underlying_type; };
129template <
typename Visitor>
void visit_node(
covered_node auto *
node, Visitor &&visitor) {
133template <
typename Visitor>
void visit_node(
void *node, Visitor &&visitor) {
134 switch (nodeTag(node)) {
135#include "node_dispatch_table.hpp"
139 if constexpr (
requires {
140 std::declval<Visitor>()(std::declval<nodes::unknown_node<
decltype(node)>>());
142 visitor(nodes::unknown_node<
decltype(node)>{node});
144 throw std::runtime_error(
"unknown node tag");
150 { t(
node, cb, ctx) } -> std::same_as<bool>;
157 auto *recasted_node =
reinterpret_cast<::Node *
>(
node.as_ptr());
158 (*this)(recasted_node, visitor, walker);
168 decltype(visitor) _visitor;
170 _ctx c{std::forward<decltype(visitor)>(visitor)};
173 [](::Node *
node,
void *ctx) {
174 if (
node ==
nullptr) {
177 _ctx *c =
reinterpret_cast<_ctx *
>(ctx);
178 if constexpr (std::is_pointer_v<std::remove_cvref_t<
decltype(visitor)>>) {
179 cppgres::visit_node(
node, *c->_visitor);
181 cppgres::visit_node(
node, c->_visitor);
191 if constexpr (std::is_pointer_v<std::remove_cvref_t<
decltype(visitor)>>) {
192 cppgres::visit_node(
node.as_ref().stmt, *visitor);
194 cppgres::visit_node(
node.as_ref().stmt, visitor);
202 ::List *node_p =
node.as_ptr();
203 if (nodeTag(node_p) == T_List) {
204 foreach (lc, node_p) {
205 void *
node = lfirst(lc);
206 if constexpr (std::is_pointer_v<std::remove_cvref_t<
decltype(visitor)>>) {
207 cppgres::visit_node(
node, *visitor);
209 cppgres::visit_node(
node, visitor);
217 void operator()(T &
node,
auto &&visitor) {
218 _walker(
node, std::forward<
decltype(visitor)>(visitor),
219#
if PG_MAJORVERSION_NUM < 16
220 reinterpret_cast<bool (*)(::Node *, ::tree_walker_callback,
void *)
>(
221 raw_expression_tree_walker)
223 ::raw_expression_tree_walker_impl
234 void operator()(T &
node,
auto &&visitor) {
235 _walker(
node, std::forward<
decltype(visitor)>(visitor),
236#
if PG_MAJORVERSION_NUM < 16
237 reinterpret_cast<bool (*)(::Node *, ::tree_walker_callback,
void *)
>(
238 ::expression_tree_walker)
240 ::expression_tree_walker_impl
252 void operator()(nodes::Query &
node,
auto &&visitor) {
253 _walker(
node, std::forward<
decltype(visitor)>(visitor),
254 [
this](
auto query,
auto cb,
auto ctx) ->
bool {
256#if PG_MAJORVERSION_NUM < 16
257 reinterpret_cast<bool (*)(::Query *, ::tree_walker_callback,
void *,
int)
>(
258 ::query_tree_walker)(
reinterpret_cast<::Query *
>(query), cb, ctx, _flags);
260 ::query_tree_walker_impl
261 (
reinterpret_cast<::Query *
>(query), cb, ctx, _flags);
268 int _flags = QTW_EXAMINE_SORTGROUP | QTW_EXAMINE_RTES_BEFORE;
void operator()(::Node *recasted_node, auto &&visitor, const walker_implementation auto &walker)
Definition: node.hpp:161
Postgres type.
Definition: type.hpp:20