15 static std::string
to_sql() {
return " UNIQUE"; }
20 static std::string
to_sql() {
return " PRIMARY KEY"; }
27 return " AUTOINCREMENT";
41template <
auto Start = 1,
auto Increment = 1,
42 auto MinValue = std::numeric_limits<
decltype(Start)>::min(),
43 auto MaxValue = std::numeric_limits<
decltype(Start)>::max(),
bool Cycle =
false>
47 static constexpr auto start = Start;
48 static constexpr auto increment = Increment;
49 static constexpr auto min_value = MinValue;
50 static constexpr auto max_value = MaxValue;
51 static constexpr bool cycle = Cycle;
54 std::string result =
" GENERATED ALWAYS AS IDENTITY";
57 if constexpr (start != 1 || increment != 1 ||
58 min_value != std::numeric_limits<
decltype(start)>::min() ||
59 max_value != std::numeric_limits<
decltype(start)>::max() || cycle) {
63 if constexpr (start != 1) {
64 result +=
"START WITH " + std::to_string(start);
68 if constexpr (increment != 1) {
69 if constexpr (start != 1) {
72 result +=
"INCREMENT BY " + std::to_string(increment);
76 if constexpr (min_value != std::numeric_limits<
decltype(start)>::min()) {
77 if constexpr (start != 1 || increment != 1) {
80 result +=
"MINVALUE " + std::to_string(min_value);
84 if constexpr (max_value != std::numeric_limits<
decltype(start)>::max()) {
85 if constexpr (start != 1 || increment != 1 ||
86 min_value != std::numeric_limits<
decltype(start)>::min()) {
89 result +=
"MAXVALUE " + std::to_string(max_value);
93 if constexpr (cycle) {
94 if constexpr (start != 1 || increment != 1 ||
95 min_value != std::numeric_limits<
decltype(start)>::min() ||
96 max_value != std::numeric_limits<
decltype(start)>::max()) {
110template <fixed_
string Expr>
112 static constexpr auto expr = Expr;
114 static std::string
to_sql() {
return " CHECK(" + std::string(std::string_view(expr)) +
")"; }
118template <fixed_
string Table, fixed_
string Column>
120 static constexpr auto table = Table;
124 return " REFERENCES " + std::string(std::string_view(table)) +
"(" +
125 std::string(std::string_view(
column)) +
")";
130template <fixed_
string Action>
132 static constexpr auto action = Action;
134 static std::string
to_sql() {
return " ON DELETE " + std::string(std::string_view(action)); }
138template <fixed_
string Action>
140 static constexpr auto action = Action;
142 static std::string
to_sql() {
return " ON UPDATE " + std::string(std::string_view(action)); }
153 if constexpr (std::is_same_v<value_type, bool>) {
155 return " DEFAULT " + std::string(value ?
"true" :
"false");
156 }
else if constexpr (std::is_integral_v<value_type> || std::is_floating_point_v<value_type>) {
158 return " DEFAULT " + std::to_string(value);
161 return " DEFAULT " + std::to_string(value);
167template <fixed_
string Value,
bool IsLiteral = false>
169 static constexpr auto value = Value;
172 if constexpr (IsLiteral) {
174 return " DEFAULT " + std::string(std::string_view(value));
177 return " DEFAULT '" + std::string(std::string_view(value)) +
"'";
184 static std::string
to_sql() {
return " DEFAULT NULL"; }
188template <
typename... Modifiers>
191 [[maybe_unused]]
auto _ = (result += ... += Modifiers::to_sql());
196template <
typename TypeParam>
205template <
typename TypeParam>
208template <fixed_
string Value,
bool IsLiteral>
216template <
typename TableT,
fixed_string Name,
typename T,
typename... Modifiers>
226 static constexpr auto name = Name;
237 std::string result = std::string(std::string_view(
name)) +
" " +
238 std::string(std::string_view(
sql_type));
242 result +=
" NOT NULL";
272 template <
typename PatternType>
273 requires std::convertible_to<PatternType, std::string>
274 auto like(PatternType&& pattern)
const;
286 template <
typename ValueT,
typename First,
typename... Rest>
287 static std::optional<ValueT> find_default_value() {
288 if constexpr (is_default_value_type<First, ValueT>()) {
289 return extract_default_value<First, ValueT>();
290 }
else if constexpr (
sizeof...(Rest) > 0) {
291 return find_default_value<ValueT, Rest...>();
297 template <
typename ValueT>
298 static std::optional<ValueT> find_default_value() {
303 template <
typename Mod,
typename ValueT>
304 static constexpr bool is_default_value_type() {
305 if constexpr (std::is_same_v<Mod, null_default>) {
307 }
else if constexpr (is_default_value_specialization<Mod>::value) {
308 using DefaultValueType =
typename is_default_value_specialization<Mod>::value_type;
309 return std::is_same_v<DefaultValueType, ValueT> ||
310 std::is_convertible_v<DefaultValueType, ValueT>;
311 }
else if constexpr (is_string_default_specialization<Mod>::value) {
312 if constexpr (std::is_same_v<ValueT, std::string> ||
313 std::is_convertible_v<std::string, ValueT> ||
314 std::is_constructible_v<ValueT, std::string_view> ||
315 std::is_constructible_v<ValueT, const char*>) {
326 template <
typename Mod,
typename ValueT>
327 static std::optional<ValueT> extract_default_value() {
328 if constexpr (std::is_same_v<Mod, null_default>) {
332 }
else if constexpr (is_default_value_specialization<Mod>::value) {
333 return static_cast<ValueT
>(Mod::value);
334 }
else if constexpr (is_string_default_specialization<Mod>::value) {
335 if constexpr (std::is_constructible_v<ValueT, std::string_view>) {
336 return ValueT(std::string_view(Mod::value));
337 }
else if constexpr (std::is_constructible_v<ValueT, std::string>) {
338 return ValueT(std::string(std::string_view(Mod::value)));
339 }
else if constexpr (std::is_constructible_v<ValueT, const char*>) {
340 return ValueT(Mod::value.data());
348template <
typename TableT, fixed_string Name,
typename T,
typename... Modifiers>
349class column<TableT, Name,
std::optional<T>, Modifiers...> {
357 static constexpr auto name = Name;
362 std::string result = std::string(std::string_view(
name)) +
" " +
363 std::string(std::string_view(
sql_type));
374 if (value.has_value()) {
381 if (sql_str ==
"NULL") {
390 return find_default_value<std::optional<T>, Modifiers...>();
396 template <
typename PatternType>
397 requires std::convertible_to<PatternType, std::string>
398 auto like(PatternType&& pattern)
const;
410 template <
typename ValueT,
typename First,
typename... Rest>
411 static std::optional<ValueT> find_default_value() {
412 if constexpr (is_default_value_type<First, ValueT>()) {
413 return extract_default_value<First, ValueT>();
414 }
else if constexpr (
sizeof...(Rest) > 0) {
415 return find_default_value<ValueT, Rest...>();
421 template <
typename ValueT>
422 static std::optional<ValueT> find_default_value() {
427 template <
typename Mod,
typename ValueT>
428 static constexpr bool is_default_value_type() {
429 if constexpr (std::is_same_v<Mod, null_default>) {
431 }
else if constexpr (is_default_value_specialization<Mod>::value) {
432 using DefaultValueType =
typename is_default_value_specialization<Mod>::value_type;
433 using OptionalBaseType =
typename ValueT::value_type;
434 return std::is_same_v<DefaultValueType, OptionalBaseType> ||
435 std::is_convertible_v<DefaultValueType, OptionalBaseType>;
436 }
else if constexpr (is_string_default_specialization<Mod>::value) {
437 using OptionalBaseType =
typename ValueT::value_type;
438 return std::is_convertible_v<std::string_view, OptionalBaseType>;
445 template <
typename Mod,
typename ValueT>
446 static std::optional<ValueT> extract_default_value() {
447 if constexpr (std::is_same_v<Mod, null_default>) {
451 }
else if constexpr (is_default_value_specialization<Mod>::value) {
452 return static_cast<ValueT
>(Mod::value);
453 }
else if constexpr (is_string_default_specialization<Mod>::value) {
454 if constexpr (std::is_constructible_v<ValueT, std::string_view>) {
455 return ValueT(std::string_view(Mod::value));
456 }
else if constexpr (std::is_constructible_v<ValueT, std::string>) {
457 return ValueT(std::string(std::string_view(Mod::value)));
458 }
else if constexpr (std::is_constructible_v<ValueT, const char*>) {
459 return ValueT(Mod::value.data());
std::optional< T > value_type
std::string sql_definition() const
TableT table_type
The table type this column belongs to.
static std::optional< T > from_sql_string(const std::string &sql_str)
std::optional< std::optional< T > > get_default_value() const
Get the default value if set.
static std::string to_sql_string(const std::optional< T > &value)
Represents a column in a database table.
static constexpr auto name
The column name.
std::optional< T > get_default_value() const
Get the default value if set.
auto is_null() const
Create an IS NULL condition for this column.
std::string sql_definition() const
Get the SQL definition of this column.
auto is_not_null() const
Create an IS NOT NULL condition for this column.
TableT table_type
The table type this column belongs to.
static std::string to_sql_string(const T &value)
Convert a C++ value to SQL string.
static T from_sql_string(const std::string &sql_str)
Parse a SQL string to C++ value.
T value_type
The C++ type of the column.
static constexpr bool nullable
Flag indicating if the column can be NULL.
static constexpr auto sql_type
The SQL type of the column.
Concept for valid identity types.
static std::string apply_modifiers()
Helper to apply all column modifiers to a SQL definition.
AUTOINCREMENT constraint.
static std::string to_sql()
static std::string to_sql()
Contains schema definition components.
static constexpr bool nullable
Whether this type can be NULL.
static T from_sql_string(const std::string &value)
Parse a SQL string representation to a C++ value.
static std::string to_sql_string(const T &value)
Convert a C++ value to a SQL string representation.
DEFAULT value for non-string values.
decltype(Value) value_type
static std::string to_sql()
Compile-time string type that can be used as template non-type parameter in C++20.
IDENTITY constraint with configurable options.
static std::string to_sql()
decltype(Value) value_type
NULL default for optional types.
static std::string to_sql()
ON DELETE action for foreign keys.
static std::string to_sql()
ON UPDATE action for foreign keys.
static std::string to_sql()
static std::string to_sql()
REFERENCES constraint for foreign keys.
static std::string to_sql()
DEFAULT value for string literals.
static std::string to_sql()
static std::string to_sql()