split column expression into separate classes

This commit is contained in:
2026-03-02 16:20:54 +01:00
parent 85c56584be
commit d9eaa2009f
31 changed files with 876 additions and 189 deletions
-102
View File
@@ -1,102 +0,0 @@
#ifndef MATADOR_COLUMN_EXPRESSION_HPP
#define MATADOR_COLUMN_EXPRESSION_HPP
#include "matador/query/table_column.hpp"
#include "matador/query/abstract_column_expression.hpp"
#include "matador/utils/placeholder.hpp"
#include "matador/utils/types.hpp"
namespace matador::query {
class binary_column_expression;
class table_column_expression;
class value_expression;
class placeholder_expression;
class expression_visitor {
public:
virtual ~expression_visitor() = default;
virtual void visit(const binary_column_expression& node) = 0;
virtual void visit(const table_column_expression& node) = 0;
virtual void visit(const value_expression& node) = 0;
virtual void visit(const placeholder_expression& node) = 0;
};
enum class binary_expression_operator {
Plus,
Minus,
Multiply,
Divide,
Modulo
};
class binary_column_expression : public abstract_column_expression {
public:
binary_column_expression() = delete;
binary_column_expression(column_expression_ptr left_column, binary_expression_operator operand, column_expression_ptr right_column);
void accept(expression_visitor& visitor) const override;
private:
column_expression_ptr left_column_;
binary_expression_operator operand_;
column_expression_ptr right_column_;
};
class table_column_expression : public abstract_column_expression {
public:
table_column_expression() = delete;
table_column_expression(table_column col);
void accept(expression_visitor& visitor) const override;
private:
table_column column_;
};
class value_expression : public abstract_column_expression {
public:
value_expression() = delete;
value_expression(utils::database_type value);
void accept(expression_visitor& visitor) const override;
private:
utils::database_type value_;
};
class placeholder_expression : public abstract_column_expression {
public:
placeholder_expression() = default;
void accept(expression_visitor& visitor) const override;
};
template<typename Type>
column_expression_ptr operator+(const table_column& col, Type val) {
return std::make_unique<binary_column_expression>(std::make_unique<table_column_expression>(col), binary_expression_operator::Plus, std::make_unique<value_expression>(val));
}
template<typename Type>
column_expression_ptr operator+(Type val, const table_column& col) {
return std::make_unique<binary_column_expression>(std::make_unique<value_expression>(val), binary_expression_operator::Plus, std::make_unique<table_column_expression>(col));
}
column_expression_ptr operator+(const table_column& col, utils::placeholder /*val*/);
column_expression_ptr operator+(utils::placeholder /*val*/, const table_column& col);
template<typename Type>
column_expression_ptr operator-(const table_column& col, Type val) {
return std::make_unique<binary_column_expression>(std::make_unique<table_column_expression>(col), binary_expression_operator::Minus, std::make_unique<value_expression>(val));
}
template<typename Type>
column_expression_ptr operator-(Type val, const table_column& col) {
return std::make_unique<binary_column_expression>(std::make_unique<value_expression>(val), binary_expression_operator::Minus, std::make_unique<table_column_expression>(col));
}
column_expression_ptr operator-(const table_column& col, utils::placeholder /*val*/);
column_expression_ptr operator-(utils::placeholder /*val*/, const table_column& col);
}
#endif //MATADOR_COLUMN_EXPRESSION_HPP
@@ -0,0 +1,31 @@
#ifndef MATADOR_BINARY_COLUMN_EXPRESSION_HPP
#define MATADOR_BINARY_COLUMN_EXPRESSION_HPP
#include "matador/query/expression/abstract_column_expression.hpp"
namespace matador::query {
enum class binary_expression_operator {
Plus,
Minus,
Multiply,
Divide,
Modulo
};
class binary_column_expression : public abstract_column_expression {
public:
binary_column_expression() = delete;
binary_column_expression(column_expression_ptr left_column, binary_expression_operator operand, column_expression_ptr right_column);
void accept(expression_visitor& visitor) const override;
[[nodiscard]] const column_expression_ptr& left_column() const;
[[nodiscard]] binary_expression_operator operand() const;
[[nodiscard]] const column_expression_ptr& right_column() const;
private:
column_expression_ptr left_column_;
binary_expression_operator operand_;
column_expression_ptr right_column_;
};
}
#endif //MATADOR_BINARY_COLUMN_EXPRESSION_HPP
@@ -0,0 +1,55 @@
#ifndef MATADOR_COLUMN_EXPRESSION_HPP
#define MATADOR_COLUMN_EXPRESSION_HPP
#include "matador/query/expression/table_column_expression.hpp"
#include "matador/query/expression/value_expression.hpp"
#include "matador/query/expression/placeholder_expression.hpp"
#include "matador/utils/placeholder.hpp"
#include "matador/utils/types.hpp"
namespace matador::query {
class column_expression {
public:
column_expression() = default;
explicit column_expression(column_expression_ptr expr) noexcept;
template<typename Type, typename = std::enable_if_t<std::is_convertible_v<Type, utils::database_type>>>
column_expression(Type&& value)
: column_expression(std::make_unique<value_expression>(std::forward<Type>(value))){
}
column_expression(const column_expression&) = delete;
column_expression& operator=(const column_expression&) = delete;
column_expression(column_expression&&) noexcept = default;
column_expression& operator=(column_expression&&) noexcept = default;
[[nodiscard]] bool empty() const noexcept;
[[nodiscard]] const abstract_column_expression* get() const noexcept;
[[nodiscard]] const column_expression_ptr& ptr() const noexcept;
column_expression_ptr release() noexcept;
// Move out for APIs that still take column_expression_ptr
operator column_expression_ptr() && noexcept;
// The feature you want: turn an expression into a SELECT-able column with alias
[[nodiscard]] table_column as(const std::string& alias) &&;
private:
column_expression_ptr expression_{};
};
// Helper constructors (optional but convenient)
inline column_expression make_column_expression(const table_column& col) {
return column_expression{std::make_unique<table_column_expression>(col)};
}
inline column_expression make_column_expression(utils::database_type v) {
return column_expression{std::make_unique<value_expression>(std::move(v))};
}
inline column_expression make_column_expression(utils::placeholder) {
return column_expression{std::make_unique<placeholder_expression>()};
}
}
#endif //MATADOR_COLUMN_EXPRESSION_HPP
@@ -0,0 +1,118 @@
#ifndef MATADOR_EXPRESSION_OPERATORS_HPP
#define MATADOR_EXPRESSION_OPERATORS_HPP
#include "matador/query/expression/binary_column_expression.hpp"
#include "matador/query/expression/table_column_expression.hpp"
#include "matador/query/expression/value_expression.hpp"
#include "matador/query/expression/column_expression.hpp"
#include "matador/utils/placeholder.hpp"
namespace matador::query {
template<typename Type>
column_expression operator+(const table_column& col, Type&& val) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<table_column_expression>(col),
binary_expression_operator::Plus,
std::make_unique<value_expression>(std::forward<Type>(val))
)};
}
template<typename Type>
column_expression operator+(Type&& val, const table_column& col) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<value_expression>(std::forward<Type>(val)),
binary_expression_operator::Plus,
std::make_unique<table_column_expression>(col)
)};
}
column_expression operator+(const table_column& col, utils::placeholder /*val*/);
column_expression operator+(utils::placeholder /*val*/, const table_column& col);
template<typename Type>
column_expression operator-(const table_column& col, Type&& val) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<table_column_expression>(col),
binary_expression_operator::Minus,
std::make_unique<value_expression>(std::forward<Type>(val))
)};
}
template<typename Type>
column_expression operator-(Type&& val, const table_column& col) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<value_expression>(std::forward<Type>(val)),
binary_expression_operator::Minus,
std::make_unique<table_column_expression>(col)
)};
}
column_expression operator-(const table_column& col, utils::placeholder /*val*/);
column_expression operator-(utils::placeholder /*val*/, const table_column& col);
template<typename Type>
column_expression operator*(const table_column& col, Type&& val) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<table_column_expression>(col),
binary_expression_operator::Multiply,
std::make_unique<value_expression>(std::forward<Type>(val))
)};
}
template<typename Type>
column_expression operator*(Type&& val, const table_column& col) {
return std::make_unique<binary_column_expression>(
std::make_unique<value_expression>(std::forward<Type>(val)),
binary_expression_operator::Multiply,
std::make_unique<table_column_expression>(col)
);
}
column_expression operator*(const table_column& col, utils::placeholder /*val*/);
column_expression operator*(utils::placeholder /*val*/, const table_column& col);
column_expression operator*(column_expression&& left, column_expression&& right);
template<typename Type>
column_expression operator/(const table_column& col, Type&& val) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<table_column_expression>(col),
binary_expression_operator::Divide,
std::make_unique<value_expression>(std::forward<Type>(val))
)};
}
template<typename Type>
column_expression operator/(Type&& val, const table_column& col) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<value_expression>(std::forward<Type>(val)),
binary_expression_operator::Divide,
std::make_unique<table_column_expression>(col)
)};
}
column_expression operator/(const table_column& col, utils::placeholder /*val*/);
column_expression operator/(utils::placeholder /*val*/, const table_column& col);
template<typename Type>
column_expression operator%(const table_column& col, Type&& val) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<table_column_expression>(col),
binary_expression_operator::Modulo,
std::make_unique<value_expression>(std::forward<Type>(val))
)};
}
template<typename Type>
column_expression operator%(Type&& val, const table_column& col) {
return column_expression{std::make_unique<binary_column_expression>(
std::make_unique<value_expression>(std::forward<Type>(val)),
binary_expression_operator::Modulo,
std::make_unique<table_column_expression>(col)
)};
}
column_expression operator%(const table_column& col, utils::placeholder /*val*/);
column_expression operator%(utils::placeholder /*val*/, const table_column& col);
}
#endif //MATADOR_EXPRESSION_OPERATORS_HPP
@@ -0,0 +1,20 @@
#ifndef MATADOR_EXPRESSION_VISITOR_HPP
#define MATADOR_EXPRESSION_VISITOR_HPP
namespace matador::query {
class binary_column_expression;
class table_column_expression;
class value_expression;
class placeholder_expression;
class expression_visitor {
public:
virtual ~expression_visitor() = default;
virtual void visit(const binary_column_expression& node) = 0;
virtual void visit(const table_column_expression& node) = 0;
virtual void visit(const value_expression& node) = 0;
virtual void visit(const placeholder_expression& node) = 0;
};
}
#endif //MATADOR_EXPRESSION_VISITOR_HPP
@@ -0,0 +1,14 @@
#ifndef MATADOR_PLACEHOLDER_EXPRESSION_HPP
#define MATADOR_PLACEHOLDER_EXPRESSION_HPP
#include "matador/query/expression/abstract_column_expression.hpp"
namespace matador::query {
class placeholder_expression : public abstract_column_expression {
public:
placeholder_expression() = default;
void accept(expression_visitor& visitor) const override;
};
}
#endif //MATADOR_PLACEHOLDER_EXPRESSION_HPP
@@ -0,0 +1,21 @@
#ifndef MATADOR_TABLE_COLUMN_EXPRESSION_HPP
#define MATADOR_TABLE_COLUMN_EXPRESSION_HPP
#include "matador/query/expression/abstract_column_expression.hpp"
#include "matador/query/table_column.hpp"
namespace matador::query {
class table_column_expression : public abstract_column_expression {
public:
table_column_expression() = delete;
explicit table_column_expression(table_column col);
void accept(expression_visitor& visitor) const override;
[[nodiscard]] const table_column& col() const;
private:
table_column column_;
};
}
#endif //MATADOR_TABLE_COLUMN_EXPRESSION_HPP
@@ -0,0 +1,22 @@
#ifndef MATADOR_VALUE_EXPRESSION_HPP
#define MATADOR_VALUE_EXPRESSION_HPP
#include "matador/query/expression/abstract_column_expression.hpp"
#include "matador/utils/types.hpp"
namespace matador::query {
class value_expression : public abstract_column_expression {
public:
value_expression() = delete;
explicit value_expression(utils::database_type value);
void accept(expression_visitor& visitor) const override;
[[nodiscard]] const utils::database_type& value() const;
private:
utils::database_type value_;
};
}
#endif //MATADOR_VALUE_EXPRESSION_HPP
@@ -0,0 +1,28 @@
#ifndef MATADOR_EXPRESSION_EVALUATOR_HPP
#define MATADOR_EXPRESSION_EVALUATOR_HPP
#include "matador/query/expression/expression_visitor.hpp"
#include <string>
namespace matador::sql {
class dialect;
struct query_context;
}
namespace matador::query {
class expression_evaluator final : public expression_visitor {
public:
expression_evaluator(const sql::dialect &d, sql::query_context &query);
void visit(const binary_column_expression& node) override;
void visit(const table_column_expression& node) override;
void visit(const value_expression& node) override;
void visit(const placeholder_expression& node) override;
private:
const sql::dialect &dialect_;
sql::query_context &query_;
std::string expression_;
};
}
#endif //MATADOR_EXPRESSION_EVALUATOR_HPP
@@ -4,20 +4,20 @@
#include "matador/query/intermediates/query_intermediate.hpp"
#include "matador/query/intermediates/query_set_intermediate.hpp"
#include "matador/query/column_expression.hpp"
#include "matador/query/expression/column_expression.hpp"
#include "matador/query/key_value_generator.hpp"
#include "matador/query/internal/column_value_pair.hpp"
namespace matador::query {
class query_update_intermediate : public query_intermediate {
class query_update_intermediate : public executable_query {
public:
explicit query_update_intermediate(const table& tab);
// query_set_intermediate set(std::initializer_list<internal::column_value_pair> columns);
// query_set_intermediate set(std::vector<internal::column_value_pair> &&columns);
query_update_intermediate& set(const table_column& col, column_expression_ptr expression);
query_update_intermediate& set(const table_column& col, column_expression&& expression);
template<class Type>
query_set_intermediate set(const Type &obj) {
return set(key_value_generator::generate(obj));
@@ -2,7 +2,7 @@
#define QUERY_KEY_VALUE_PAIR_HPP
#include "matador/query/table_column.hpp"
#include "matador/query/column_expression.hpp"
#include "../expression/column_expression.hpp"
#include "matador/utils/placeholder.hpp"
#include "matador/utils/types.hpp"
+2
View File
@@ -8,10 +8,12 @@
namespace matador::sql {
class dialect;
struct query_context;
}
namespace matador::query {
class table_column;
void prepare_column(sql::query_context& ctx, const sql::dialect& d, const table_column& col);
void prepare_column(std::string &out, const sql::dialect& d, const table_column &col);
[[nodiscard]] std::string prepare_identifier(const sql::dialect& d, const table_column &col);
[[nodiscard]] std::string prepare_criteria(const sql::dialect& d, const table_column &col);
+7 -1
View File
@@ -1,7 +1,7 @@
#ifndef QUERY_COLUMN_HPP
#define QUERY_COLUMN_HPP
#include "matador/query/abstract_column_expression.hpp"
#include "expression/abstract_column_expression.hpp"
#include "matador/sql/sql_functions.hpp"
@@ -94,6 +94,10 @@ public:
[[nodiscard]] const class table* table() const;
void table(const query::table* tab);
// New: expression-backed column support
[[nodiscard]] bool is_expression() const;
[[nodiscard]] const column_expression_ptr& expression() const;
// ReSharper disable once CppNonExplicitConversionOperator
operator const std::string&() const; // NOLINT(*-explicit-constructor)
@@ -111,6 +115,8 @@ private:
utils::field_attributes attributes_{};
sql::sql_function_t function_{sql::sql_function_t::None};
column_expression_ptr expression_{};
};
table_column operator ""_col(const char *name, size_t len);