#pragma once #include // std::tuple #include // std::string #include // std::unique_ptr #include // std::is_same, std::is_member_object_pointer #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" #include "tuple_helper/tuple_traits.h" #include "tuple_helper/tuple_filter.h" #include "type_traits.h" #include "member_traits/member_traits.h" #include "type_is_nullable.h" #include "constraints.h" namespace sqlite_orm { namespace internal { struct column_identifier { /** * Column name. */ std::string name; }; struct empty_setter {}; /* * Encapsulates object member pointers that are used as column fields, * and whose object is mapped to storage. * * G is a member object pointer or member function pointer * S is a member function pointer or `empty_setter` */ template struct column_field { using member_pointer_t = G; using setter_type = S; using object_type = member_object_type_t; using field_type = member_field_type_t; /** * Member pointer used to read a field value. * If it is a object member pointer it is also used to write a field value. */ const member_pointer_t member_pointer; /** * Setter member function to write a field value */ SQLITE_ORM_NOUNIQUEADDRESS const setter_type setter; /** * Simplified interface for `NOT NULL` constraint */ constexpr bool is_not_null() const { return !type_is_nullable::value; } }; /* * Encapsulates a tuple of column constraints. * * Op... is a constraints pack, e.g. primary_key_t, unique_t etc */ template struct column_constraints { using constraints_type = std::tuple; SQLITE_ORM_NOUNIQUEADDRESS constraints_type constraints; /** * Checks whether contraints are of trait `Trait` */ template class Trait> constexpr bool is() const { return tuple_has::value; } constexpr bool is_generated() const { #if SQLITE_VERSION_NUMBER >= 3031000 return is(); #else return false; #endif } /** * Simplified interface for `DEFAULT` constraint * @return string representation of default value if it exists otherwise nullptr */ std::unique_ptr default_value() const; }; /** * Column definition. * * It is a composition of orthogonal information stored in different base classes. */ template struct column_t : column_identifier, column_field, column_constraints { #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED column_t(std::string name, G memberPointer, S setter, std::tuple op) : column_identifier{std::move(name)}, column_field{memberPointer, setter}, column_constraints{std::move(op)} {} #endif }; template SQLITE_ORM_INLINE_VAR constexpr bool is_column_v = polyfill::is_specialization_of_v; template using is_column = polyfill::bool_constant>; template using col_index_sequence_with_field_type = filter_tuple_sequence_t::template fn, field_type_t, filter_tuple_sequence_t>; template class TraitFn> using col_index_sequence_with = filter_tuple_sequence_t::template fn, constraints_type_t, filter_tuple_sequence_t>; template class TraitFn> using col_index_sequence_excluding = filter_tuple_sequence_t::template fn, constraints_type_t, filter_tuple_sequence_t>; } /** * Column builder function. You should use it to create columns instead of constructor */ template = true> internal::column_t make_column(std::string name, M m, Op... constraints) { static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {std::move(name), m, {}, std::make_tuple(constraints...)}); } /** * Column builder function with setter and getter. You should use it to create columns instead of constructor */ template = true, internal::satisfies = true> internal::column_t make_column(std::string name, S setter, G getter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( return {std::move(name), getter, setter, std::make_tuple(constraints...)}); } /** * Column builder function with getter and setter (reverse order). You should use it to create columns instead of * constructor */ template = true, internal::satisfies = true> internal::column_t make_column(std::string name, G getter, S setter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( return {std::move(name), getter, setter, std::make_tuple(constraints...)}); } }