|
9 | 9 | #include <utility> |
10 | 10 |
|
11 | 11 | #include "ds_mysql/fixed_string.hpp" |
| 12 | +#include "ds_mysql/name_reflection.hpp" |
12 | 13 | #include "ds_mysql/sql_temporal.hpp" |
13 | 14 | #include "ds_mysql/varchar_field.hpp" |
14 | 15 |
|
@@ -521,6 +522,68 @@ using unwrap_column_field_t = typename unwrap_column_field<T>::type; |
521 | 522 |
|
522 | 523 | } // namespace ds_mysql |
523 | 524 |
|
| 525 | +// =================================================================== |
| 526 | +// tagged_column_field — tag-struct convenience alias |
| 527 | +// =================================================================== |
| 528 | + |
| 529 | +namespace ds_mysql { |
| 530 | + |
| 531 | +namespace detail { |
| 532 | + |
| 533 | +/** |
| 534 | + * Construct a fixed_string<N> from a string_view at compile time. |
| 535 | + * N must equal sv.size() + 1 (to include the null terminator). |
| 536 | + */ |
| 537 | +template <std::size_t N> |
| 538 | +consteval fixed_string<N> fixed_string_from_sv(std::string_view sv) noexcept { |
| 539 | + fixed_string<N> result{}; |
| 540 | + for (std::size_t i = 0; i + 1 < N; ++i) |
| 541 | + result.data[i] = sv[i]; |
| 542 | + return result; |
| 543 | +} |
| 544 | + |
| 545 | +/** |
| 546 | + * Derive the column name from a tag type at compile time. |
| 547 | + * Strips a trailing "_tag" suffix if present, then returns a fixed_string. |
| 548 | + * |
| 549 | + * Examples: |
| 550 | + * column_name_from_tag<id_tag>() → fixed_string{"id"} |
| 551 | + * column_name_from_tag<price_tag>() → fixed_string{"price"} |
| 552 | + * column_name_from_tag<foo>() → fixed_string{"foo"} (no suffix) |
| 553 | + */ |
| 554 | +template <typename Tag> |
| 555 | +consteval auto column_name_from_tag() noexcept { |
| 556 | + constexpr std::string_view full = extract_type_name<Tag>(); |
| 557 | + constexpr std::string_view suffix = "_tag"; |
| 558 | + constexpr std::string_view name = full.ends_with(suffix) |
| 559 | + ? full.substr(0, full.size() - suffix.size()) |
| 560 | + : full; |
| 561 | + return fixed_string_from_sv<name.size() + 1>(name); |
| 562 | +} |
| 563 | + |
| 564 | +} // namespace detail |
| 565 | + |
| 566 | +/** |
| 567 | + * tagged_column_field<Tag, T> — tag-struct alternative to column_field<"name", T>. |
| 568 | + * |
| 569 | + * Derive the SQL column name from a tag struct at compile time (stripping a |
| 570 | + * trailing "_tag" suffix). The result is an ordinary column_field, so it |
| 571 | + * satisfies all the same concepts and works everywhere column_field does. |
| 572 | + * |
| 573 | + * Usage: |
| 574 | + * struct price_tag {}; |
| 575 | + * using price = tagged_column_field<price_tag, double>; |
| 576 | + * price price_; |
| 577 | + * |
| 578 | + * This is exactly equivalent to: |
| 579 | + * using price = column_field<"price", double>; |
| 580 | + * price price_; |
| 581 | + */ |
| 582 | +template <typename Tag, typename T> |
| 583 | +using tagged_column_field = column_field<detail::column_name_from_tag<Tag>(), T>; |
| 584 | + |
| 585 | +} // namespace ds_mysql |
| 586 | + |
524 | 587 | /** |
525 | 588 | * COLUMN_FIELD(tag, type) — convenience macro to declare a column field member. |
526 | 589 | * |
|
0 commit comments