8#ifndef QWPARITYSCHEMAROW_H_
9#define QWPARITYSCHEMAROW_H_
40#ifdef __USE_DATABASE__
42#include <QwParitySchema.h>
44#include <sqlpp11/sqlpp11.h>
47#include <sqlpp23/sqlpp23.h>
51#ifdef __USE_DATABASE__
53namespace QwParitySchema {
58 template<
typename Column>
59 using column_value_t = sqlpp::cpp_value_type_of<typename Column::_traits::_value_type>;
63 template<
typename Column>
64 using column_value_t = sqlpp::parameter_value_t<sqlpp::data_type_of_t<Column>>;
68 template<
typename Tuple>
69 struct extract_value_types;
71 template<
typename... Columns>
72 struct extract_value_types<std::tuple<Columns...>> {
73 using type = std::tuple<column_value_t<Columns>...>;
77 template<
typename Target>
78 constexpr std::size_t find_index_impl() {
79 static_assert(
sizeof(Target) == 0,
"Column type not found in table");
84 template<
typename Target,
typename First,
typename... Rest>
85 constexpr std::size_t find_index_impl() {
86 if constexpr (std::is_same_v<Target, First>) {
89 return 1 + find_index_impl<Target, Rest...>();
94 template<
typename TargetColumn,
typename Tuple>
97 template<
typename TargetColumn,
typename... Columns>
98 struct column_index<TargetColumn, std::tuple<Columns...>> {
99 static constexpr std::size_t value = find_index_impl<TargetColumn, Columns...>();
103 template<
typename ColumnOrColumnSpec>
104 constexpr bool is_insertable_column() {
105#ifdef __USE_SQLPP11__
106 using traits =
typename ColumnOrColumnSpec::_traits;
107 using tags =
typename traits::_tags;
108 return !sqlpp::detail::is_element_of<sqlpp::tag::must_not_insert, tags>::value;
110#ifdef __USE_SQLPP23__
112 return !sqlpp::has_default<ColumnOrColumnSpec>::value;
117 template<
typename ColumnSpec,
typename ValueType>
120 ValueType& value_ref;
123 column_proxy(ValueType& ref) : value_ref(ref) {}
126 operator const ValueType&()
const {
132 column_proxy& operator=(T&& val) {
133 static_assert(is_insertable_column<ColumnSpec>(),
134 "Cannot assign to auto-increment field (has must_not_insert trait). "
135 "Auto-increment fields are generated by the database.");
136 value_ref = std::forward<T>(val);
141#ifdef __USE_SQLPP11__
142 column_proxy& operator=(
const sqlpp::null_t& ) {
143 static_assert(is_insertable_column<ColumnSpec>(),
144 "Cannot assign to auto-increment field (has must_not_insert trait). "
145 "Auto-increment fields are generated by the database.");
148 using traits =
typename ColumnSpec::_traits;
149 using tags =
typename traits::_tags;
150 static_assert(sqlpp::detail::is_element_of<sqlpp::tag::can_be_null, tags>::value,
151 "Cannot assign null to non-nullable column");
154 value_ref = ValueType{};
159#ifdef __USE_SQLPP23__
162 struct is_optional_type : std::false_type {};
164 struct is_optional_type<std::optional<T>> : std::true_type {};
166 column_proxy& operator=(
const std::nullopt_t& ) {
167 static_assert(is_insertable_column<ColumnSpec>(),
168 "Cannot assign to auto-increment field (has has_default trait). "
169 "Auto-increment fields are generated by the database.");
172 static_assert(is_optional_type<ValueType>::value,
173 "Cannot assign null to non-nullable column");
176 value_ref = ValueType{};
182 const ValueType& get()
const {
189 struct column_spec_of {
194 template<
typename Table,
typename ColumnSpec>
195 struct column_spec_of<sqlpp::column_t<Table, ColumnSpec>> {
196 using type = ColumnSpec;
200 using column_spec_of_t =
typename column_spec_of<T>::type;
203 template<std::
size_t I,
typename Columns,
typename Values>
204 auto make_assignment_if_insertable(
const Columns& columns,
const Values& values) {
205 auto column = std::get<I>(columns);
206 using column_type = std::decay_t<
decltype(column)>;
207 using column_spec = column_spec_of_t<column_type>;
208 if constexpr (is_insertable_column<column_spec>()) {
209 return std::make_tuple(column = std::get<I>(values));
211 return std::make_tuple();
243template<
typename Table>
247 using column_tuple_t =
typename Table::_column_tuple_t;
248 using values_tuple_t =
typename detail::extract_value_types<column_tuple_t>::type;
251 using table_type = Table;
259 values_tuple_t values;
269 row(
const row&) =
default;
274 row(row&&) =
default;
279 row& operator=(
const row&) =
default;
284 row& operator=(row&&) =
default;
298 template<
typename ColumnSpec,
typename T>
299 void set(T&& value) {
300 static_assert(detail::is_insertable_column<ColumnSpec>(),
301 "Cannot set auto-increment field (has must_not_insert trait). "
302 "Auto-increment fields are generated by the database.");
303 using column_t = sqlpp::column_t<Table, ColumnSpec>;
304 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
305 std::get<idx>(values) = std::forward<T>(value);
314 template<
typename ColumnSpec>
315 const auto& get()
const {
316 using column_t = sqlpp::column_t<Table, ColumnSpec>;
317 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
318 return std::get<idx>(values);
327 template<
typename ColumnSpec>
329 using column_t = sqlpp::column_t<Table, ColumnSpec>;
330 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
331 return std::get<idx>(values);
342 template<
typename ColumnType,
typename T>
343 void set(
const ColumnType& , T&& value) {
344 using column_spec = detail::column_spec_of_t<ColumnType>;
345 static_assert(detail::is_insertable_column<column_spec>(),
346 "Cannot set auto-increment field. "
347 "Auto-increment fields are generated by the database.");
348 set<column_spec>(std::forward<T>(value));
358 template<
typename ColumnType>
359 const auto& get(
const ColumnType& )
const {
360 using column_spec = detail::column_spec_of_t<ColumnType>;
361 return get<column_spec>();
371 template<
typename ColumnType>
372 auto& get(
const ColumnType& ) {
373 using column_spec = detail::column_spec_of_t<ColumnType>;
374 return get<column_spec>();
387 template<
typename ColumnType>
388 auto operator[](
const ColumnType& ) {
389 using column_spec = detail::column_spec_of_t<ColumnType>;
390 constexpr auto idx = detail::column_index<ColumnType, column_tuple_t>::value;
391 using value_type = std::tuple_element_t<idx, values_tuple_t>;
392 return detail::column_proxy<column_spec, value_type>(std::get<idx>(values));
402 template<
typename ColumnType>
403 const auto& operator[](
const ColumnType& column)
const {
415 auto insert_into()
const {
417 return generate_insert_impl(table, std::make_index_sequence<std::tuple_size_v<values_tuple_t>>{});
424 values = values_tuple_t{};
432 static constexpr std::size_t column_count() {
433 return std::tuple_size_v<values_tuple_t>;
448 template<std::size_t... Is>
449 auto generate_insert_impl(Table& table, std::index_sequence<Is...>)
const {
450 auto columns = sqlpp::all_of(table);
453 auto assignments = std::tuple_cat(
454 detail::make_assignment_if_insertable<Is>(columns, values)...
458 return std::apply([&table](
auto&&... args) {
459 return sqlpp::insert_into(table).set(args...);
465using beam_optics_row = row<beam_optics>;
466using md_data_row = row<md_data>;
467using lumi_data_row = row<lumi_data>;
468using beam_row = row<beam>;
469using beam_errors_row = row<beam_errors>;
470using lumi_errors_row = row<lumi_errors>;
471using md_errors_row = row<md_errors>;
472using general_errors_row = row<general_errors>;