8#ifndef QWPARITYSCHEMAROW_H_
9#define QWPARITYSCHEMAROW_H_
40#ifdef __USE_DATABASE__
41#include "QwParitySchema.h"
43#include <sqlpp11/sqlpp11.h>
46#include <sqlpp23/sqlpp23.h>
50#ifdef __USE_DATABASE__
52namespace QwParitySchema {
57 template<
typename Column>
58 using column_value_t = sqlpp::cpp_value_type_of<typename Column::_traits::_value_type>;
62 template<
typename Column>
63 using column_value_t = sqlpp::parameter_value_t<sqlpp::data_type_of_t<Column>>;
67 template<
typename Tuple>
68 struct extract_value_types;
70 template<
typename... Columns>
71 struct extract_value_types<std::tuple<Columns...>> {
72 using type = std::tuple<column_value_t<Columns>...>;
76 template<
typename Target>
77 constexpr std::size_t find_index_impl() {
78 static_assert(
sizeof(Target) == 0,
"Column type not found in table");
83 template<
typename Target,
typename First,
typename... Rest>
84 constexpr std::size_t find_index_impl() {
85 if constexpr (std::is_same_v<Target, First>) {
88 return 1 + find_index_impl<Target, Rest...>();
93 template<
typename TargetColumn,
typename Tuple>
96 template<
typename TargetColumn,
typename... Columns>
97 struct column_index<TargetColumn, std::tuple<Columns...>> {
98 static constexpr std::size_t value = find_index_impl<TargetColumn, Columns...>();
102 template<
typename ColumnOrColumnSpec>
103 constexpr bool is_insertable_column() {
104#ifdef __USE_SQLPP11__
105 using traits =
typename ColumnOrColumnSpec::_traits;
106 using tags =
typename traits::_tags;
107 return !sqlpp::detail::is_element_of<sqlpp::tag::must_not_insert, tags>::value;
109#ifdef __USE_SQLPP23__
111 return !sqlpp::has_default<ColumnOrColumnSpec>::value;
116 template<
typename ColumnSpec,
typename ValueType>
119 ValueType& value_ref;
122 column_proxy(ValueType& ref) : value_ref(ref) {}
125 operator const ValueType&()
const {
131 column_proxy& operator=(T&& val) {
132 static_assert(is_insertable_column<ColumnSpec>(),
133 "Cannot assign to auto-increment field (has must_not_insert trait). "
134 "Auto-increment fields are generated by the database.");
135 value_ref = std::forward<T>(val);
140#ifdef __USE_SQLPP11__
141 column_proxy& operator=(
const sqlpp::null_t& ) {
142 static_assert(is_insertable_column<ColumnSpec>(),
143 "Cannot assign to auto-increment field (has must_not_insert trait). "
144 "Auto-increment fields are generated by the database.");
147 using traits =
typename ColumnSpec::_traits;
148 using tags =
typename traits::_tags;
149 static_assert(sqlpp::detail::is_element_of<sqlpp::tag::can_be_null, tags>::value,
150 "Cannot assign null to non-nullable column");
153 value_ref = ValueType{};
158#ifdef __USE_SQLPP23__
161 struct is_optional_type : std::false_type {};
163 struct is_optional_type<std::optional<T>> : std::true_type {};
165 column_proxy& operator=(
const std::nullopt_t& ) {
166 static_assert(is_insertable_column<ColumnSpec>(),
167 "Cannot assign to auto-increment field (has has_default trait). "
168 "Auto-increment fields are generated by the database.");
171 static_assert(is_optional_type<ValueType>::value,
172 "Cannot assign null to non-nullable column");
175 value_ref = ValueType{};
181 const ValueType& get()
const {
188 struct column_spec_of {
193 template<
typename Table,
typename ColumnSpec>
194 struct column_spec_of<sqlpp::column_t<Table, ColumnSpec>> {
195 using type = ColumnSpec;
199 using column_spec_of_t =
typename column_spec_of<T>::type;
202 template<std::
size_t I,
typename Columns,
typename Values>
203 auto make_assignment_if_insertable(
const Columns& columns,
const Values& values) {
204 auto column = std::get<I>(columns);
205 using column_type = std::decay_t<
decltype(column)>;
206 using column_spec = column_spec_of_t<column_type>;
207 if constexpr (is_insertable_column<column_spec>()) {
208 return std::make_tuple(column = std::get<I>(values));
210 return std::make_tuple();
242template<
typename Table>
246 using column_tuple_t =
typename Table::_column_tuple_t;
247 using values_tuple_t =
typename detail::extract_value_types<column_tuple_t>::type;
250 using table_type = Table;
258 values_tuple_t values;
268 row(
const row&) =
default;
273 row(row&&) =
default;
278 row& operator=(
const row&) =
default;
283 row& operator=(row&&) =
default;
297 template<
typename ColumnSpec,
typename T>
298 void set(T&& value) {
299 static_assert(detail::is_insertable_column<ColumnSpec>(),
300 "Cannot set auto-increment field (has must_not_insert trait). "
301 "Auto-increment fields are generated by the database.");
302 using column_t = sqlpp::column_t<Table, ColumnSpec>;
303 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
304 std::get<idx>(values) = std::forward<T>(value);
313 template<
typename ColumnSpec>
314 const auto& get()
const {
315 using column_t = sqlpp::column_t<Table, ColumnSpec>;
316 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
317 return std::get<idx>(values);
326 template<
typename ColumnSpec>
328 using column_t = sqlpp::column_t<Table, ColumnSpec>;
329 constexpr auto idx = detail::column_index<column_t, column_tuple_t>::value;
330 return std::get<idx>(values);
341 template<
typename ColumnType,
typename T>
342 void set(
const ColumnType& , T&& value) {
343 using column_spec = detail::column_spec_of_t<ColumnType>;
344 static_assert(detail::is_insertable_column<column_spec>(),
345 "Cannot set auto-increment field. "
346 "Auto-increment fields are generated by the database.");
347 set<column_spec>(std::forward<T>(value));
357 template<
typename ColumnType>
358 const auto& get(
const ColumnType& )
const {
359 using column_spec = detail::column_spec_of_t<ColumnType>;
360 return get<column_spec>();
370 template<
typename ColumnType>
371 auto& get(
const ColumnType& ) {
372 using column_spec = detail::column_spec_of_t<ColumnType>;
373 return get<column_spec>();
386 template<
typename ColumnType>
387 auto operator[](
const ColumnType& ) {
388 using column_spec = detail::column_spec_of_t<ColumnType>;
389 constexpr auto idx = detail::column_index<ColumnType, column_tuple_t>::value;
390 using value_type = std::tuple_element_t<idx, values_tuple_t>;
391 return detail::column_proxy<column_spec, value_type>(std::get<idx>(values));
401 template<
typename ColumnType>
402 const auto& operator[](
const ColumnType& column)
const {
414 auto insert_into()
const {
416 return generate_insert_impl(table, std::make_index_sequence<std::tuple_size_v<values_tuple_t>>{});
423 values = values_tuple_t{};
431 static constexpr std::size_t column_count() {
432 return std::tuple_size_v<values_tuple_t>;
447 template<std::size_t... Is>
448 auto generate_insert_impl(Table& table, std::index_sequence<Is...>)
const {
449 auto columns = sqlpp::all_of(table);
452 auto assignments = std::tuple_cat(
453 detail::make_assignment_if_insertable<Is>(columns, values)...
457 return std::apply([&table](
auto&&... args) {
458 return sqlpp::insert_into(table).set(args...);
464using beam_optics_row = row<beam_optics>;
465using md_data_row = row<md_data>;
466using lumi_data_row = row<lumi_data>;
467using beam_row = row<beam>;
468using beam_errors_row = row<beam_errors>;
469using lumi_errors_row = row<lumi_errors>;
470using md_errors_row = row<md_errors>;
471using general_errors_row = row<general_errors>;