Skip to content

Commit c3b75d2

Browse files
author
Pierre-Luc Gagné
committed
Add templated temporal FSP types and migrate default usages
1 parent 9cb7ec2 commit c3b75d2

12 files changed

Lines changed: 290 additions & 176 deletions

examples/basic_query.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct product {
4848
COLUMN_FIELD(price, double)
4949
COLUMN_FIELD(stock, uint32_t)
5050
COLUMN_FIELD(description, std::optional<ds_mysql::varchar_field<512>>)
51-
COLUMN_FIELD(created_at, ds_mysql::datetime_type)
51+
COLUMN_FIELD(created_at, ds_mysql::datetime_type<>)
5252
};
5353

5454
// ===================================================================

examples/schema_generation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct user {
2525
COLUMN_FIELD(username, ds_mysql::varchar_field<64>)
2626
COLUMN_FIELD(email, ds_mysql::varchar_field<255>)
2727
COLUMN_FIELD(is_active, bool)
28-
COLUMN_FIELD(created_at, ds_mysql::datetime_type)
28+
COLUMN_FIELD(created_at, ds_mysql::datetime_type<>)
2929
};
3030

3131
// ===================================================================
@@ -43,7 +43,7 @@ struct order_row {
4343
COLUMN_FIELD(status, ds_mysql::varchar_field<32>)
4444

4545
struct order_created_at_tag {};
46-
using created_at = ds_mysql::tagged_column_field<order_created_at_tag, ds_mysql::datetime_type>;
46+
using created_at = ds_mysql::tagged_column_field<order_created_at_tag, ds_mysql::datetime_type<>>;
4747
created_at created_at_;
4848
};
4949

examples/tables_with_constraints.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ struct symbol {
2828
COLUMN_FIELD(name, std::optional<ds_mysql::varchar_field<255>>)
2929
COLUMN_FIELD(sector, std::optional<ds_mysql::varchar_field<255>>)
3030
COLUMN_FIELD(currency, std::optional<ds_mysql::varchar_field<32>>)
31-
COLUMN_FIELD(created_date, ds_mysql::datetime_type)
32-
COLUMN_FIELD(last_updated_date, ds_mysql::datetime_type)
31+
COLUMN_FIELD(created_date, ds_mysql::datetime_type<>)
32+
COLUMN_FIELD(last_updated_date, ds_mysql::datetime_type<>)
3333
};
3434

3535
// ===================================================================

lib/include/ds_mysql/column_field.hpp

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -415,194 +415,194 @@ struct base<std::optional<varchar_field<N>>> : column_field_tag {
415415
}
416416
};
417417

418-
template <>
419-
struct base<datetime_type> : column_field_tag {
420-
using value_type = datetime_type;
418+
template <uint32_t Fsp>
419+
struct base<detail::basic_datetime_type<Fsp>> : column_field_tag {
420+
using value_type = detail::basic_datetime_type<Fsp>;
421421

422-
datetime_type value{};
422+
detail::basic_datetime_type<Fsp> value{};
423423

424424
constexpr base() = default;
425425
base(sql_now_t) noexcept : value(sql_now_t{}) {
426426
}
427427
base(std::chrono::system_clock::time_point tp) noexcept : value(tp) {
428428
}
429-
base(datetime_type v) noexcept : value(v) {
429+
base(detail::basic_datetime_type<Fsp> v) noexcept : value(v) {
430430
}
431431

432432
base& operator=(sql_now_t) noexcept {
433-
value = datetime_type{sql_now_t{}};
433+
value = detail::basic_datetime_type<Fsp>{sql_now_t{}};
434434
return *this;
435435
}
436436
base& operator=(std::chrono::system_clock::time_point tp) noexcept {
437-
value = datetime_type{tp};
437+
value = detail::basic_datetime_type<Fsp>{tp};
438438
return *this;
439439
}
440-
base& operator=(datetime_type v) noexcept {
440+
base& operator=(detail::basic_datetime_type<Fsp> v) noexcept {
441441
value = v;
442442
return *this;
443443
}
444444

445-
[[nodiscard]] constexpr datetime_type const& get() const noexcept {
445+
[[nodiscard]] constexpr detail::basic_datetime_type<Fsp> const& get() const noexcept {
446446
return value;
447447
}
448-
[[nodiscard]] constexpr datetime_type& get() noexcept {
448+
[[nodiscard]] constexpr detail::basic_datetime_type<Fsp>& get() noexcept {
449449
return value;
450450
}
451451

452-
constexpr operator datetime_type const&() const noexcept {
452+
constexpr operator detail::basic_datetime_type<Fsp> const&() const noexcept {
453453
return value;
454454
}
455-
constexpr operator datetime_type&() noexcept {
455+
constexpr operator detail::basic_datetime_type<Fsp>&() noexcept {
456456
return value;
457457
}
458458
};
459459

460-
template <>
461-
struct base<std::optional<datetime_type>> : column_field_tag {
462-
using value_type = std::optional<datetime_type>;
460+
template <uint32_t Fsp>
461+
struct base<std::optional<detail::basic_datetime_type<Fsp>>> : column_field_tag {
462+
using value_type = std::optional<detail::basic_datetime_type<Fsp>>;
463463

464-
std::optional<datetime_type> value{};
464+
std::optional<detail::basic_datetime_type<Fsp>> value{};
465465

466466
constexpr base() = default;
467467
constexpr base(std::nullopt_t) noexcept : value(std::nullopt) {
468468
}
469-
base(sql_now_t) noexcept : value(datetime_type{sql_now_t{}}) {
469+
base(sql_now_t) noexcept : value(detail::basic_datetime_type<Fsp>{sql_now_t{}}) {
470470
}
471-
base(std::chrono::system_clock::time_point tp) noexcept : value(datetime_type{tp}) {
471+
base(std::chrono::system_clock::time_point tp) noexcept : value(detail::basic_datetime_type<Fsp>{tp}) {
472472
}
473-
base(datetime_type v) noexcept : value(std::move(v)) {
473+
base(detail::basic_datetime_type<Fsp> v) noexcept : value(std::move(v)) {
474474
}
475-
base(std::optional<datetime_type> v) noexcept : value(std::move(v)) {
475+
base(std::optional<detail::basic_datetime_type<Fsp>> v) noexcept : value(std::move(v)) {
476476
}
477477

478478
constexpr base& operator=(std::nullopt_t) noexcept {
479479
value = std::nullopt;
480480
return *this;
481481
}
482482
constexpr base& operator=(sql_now_t) noexcept {
483-
value = datetime_type{sql_now_t{}};
483+
value = detail::basic_datetime_type<Fsp>{sql_now_t{}};
484484
return *this;
485485
}
486486
constexpr base& operator=(std::chrono::system_clock::time_point tp) noexcept {
487-
value = datetime_type{tp};
487+
value = detail::basic_datetime_type<Fsp>{tp};
488488
return *this;
489489
}
490-
constexpr base& operator=(datetime_type v) noexcept {
490+
constexpr base& operator=(detail::basic_datetime_type<Fsp> v) noexcept {
491491
value = std::move(v);
492492
return *this;
493493
}
494-
constexpr base& operator=(std::optional<datetime_type> v) noexcept {
494+
constexpr base& operator=(std::optional<detail::basic_datetime_type<Fsp>> v) noexcept {
495495
value = std::move(v);
496496
return *this;
497497
}
498498

499-
[[nodiscard]] constexpr std::optional<datetime_type> const& get() const noexcept {
499+
[[nodiscard]] constexpr std::optional<detail::basic_datetime_type<Fsp>> const& get() const noexcept {
500500
return value;
501501
}
502-
[[nodiscard]] constexpr std::optional<datetime_type>& get() noexcept {
502+
[[nodiscard]] constexpr std::optional<detail::basic_datetime_type<Fsp>>& get() noexcept {
503503
return value;
504504
}
505505

506-
constexpr operator std::optional<datetime_type> const&() const noexcept {
506+
constexpr operator std::optional<detail::basic_datetime_type<Fsp>> const&() const noexcept {
507507
return value;
508508
}
509-
constexpr operator std::optional<datetime_type>&() noexcept {
509+
constexpr operator std::optional<detail::basic_datetime_type<Fsp>>&() noexcept {
510510
return value;
511511
}
512512
};
513513

514-
template <>
515-
struct base<timestamp_type> : column_field_tag {
516-
using value_type = timestamp_type;
514+
template <uint32_t Fsp>
515+
struct base<detail::basic_timestamp_type<Fsp>> : column_field_tag {
516+
using value_type = detail::basic_timestamp_type<Fsp>;
517517

518-
timestamp_type value{};
518+
detail::basic_timestamp_type<Fsp> value{};
519519

520520
constexpr base() = default;
521521
base(sql_now_t) noexcept : value(sql_now_t{}) {
522522
}
523523
base(std::chrono::system_clock::time_point tp) noexcept : value(tp) {
524524
}
525-
base(timestamp_type v) noexcept : value(v) {
525+
base(detail::basic_timestamp_type<Fsp> v) noexcept : value(v) {
526526
}
527527

528528
base& operator=(sql_now_t) noexcept {
529-
value = timestamp_type{sql_now_t{}};
529+
value = detail::basic_timestamp_type<Fsp>{sql_now_t{}};
530530
return *this;
531531
}
532532
base& operator=(std::chrono::system_clock::time_point tp) noexcept {
533-
value = timestamp_type{tp};
533+
value = detail::basic_timestamp_type<Fsp>{tp};
534534
return *this;
535535
}
536-
base& operator=(timestamp_type v) noexcept {
536+
base& operator=(detail::basic_timestamp_type<Fsp> v) noexcept {
537537
value = v;
538538
return *this;
539539
}
540540

541-
[[nodiscard]] constexpr timestamp_type const& get() const noexcept {
541+
[[nodiscard]] constexpr detail::basic_timestamp_type<Fsp> const& get() const noexcept {
542542
return value;
543543
}
544-
[[nodiscard]] constexpr timestamp_type& get() noexcept {
544+
[[nodiscard]] constexpr detail::basic_timestamp_type<Fsp>& get() noexcept {
545545
return value;
546546
}
547547

548-
constexpr operator timestamp_type const&() const noexcept {
548+
constexpr operator detail::basic_timestamp_type<Fsp> const&() const noexcept {
549549
return value;
550550
}
551-
constexpr operator timestamp_type&() noexcept {
551+
constexpr operator detail::basic_timestamp_type<Fsp>&() noexcept {
552552
return value;
553553
}
554554
};
555555

556-
template <>
557-
struct base<std::optional<timestamp_type>> : column_field_tag {
558-
using value_type = std::optional<timestamp_type>;
556+
template <uint32_t Fsp>
557+
struct base<std::optional<detail::basic_timestamp_type<Fsp>>> : column_field_tag {
558+
using value_type = std::optional<detail::basic_timestamp_type<Fsp>>;
559559

560-
std::optional<timestamp_type> value{};
560+
std::optional<detail::basic_timestamp_type<Fsp>> value{};
561561

562562
constexpr base() = default;
563563
constexpr base(std::nullopt_t) noexcept : value(std::nullopt) {
564564
}
565-
base(sql_now_t) noexcept : value(timestamp_type{sql_now_t{}}) {
565+
base(sql_now_t) noexcept : value(detail::basic_timestamp_type<Fsp>{sql_now_t{}}) {
566566
}
567-
base(std::chrono::system_clock::time_point tp) noexcept : value(timestamp_type{tp}) {
567+
base(std::chrono::system_clock::time_point tp) noexcept : value(detail::basic_timestamp_type<Fsp>{tp}) {
568568
}
569-
base(timestamp_type v) noexcept : value(std::move(v)) {
569+
base(detail::basic_timestamp_type<Fsp> v) noexcept : value(std::move(v)) {
570570
}
571-
base(std::optional<timestamp_type> v) noexcept : value(std::move(v)) {
571+
base(std::optional<detail::basic_timestamp_type<Fsp>> v) noexcept : value(std::move(v)) {
572572
}
573573

574574
constexpr base& operator=(std::nullopt_t) noexcept {
575575
value = std::nullopt;
576576
return *this;
577577
}
578578
constexpr base& operator=(sql_now_t) noexcept {
579-
value = timestamp_type{sql_now_t{}};
579+
value = detail::basic_timestamp_type<Fsp>{sql_now_t{}};
580580
return *this;
581581
}
582582
constexpr base& operator=(std::chrono::system_clock::time_point tp) noexcept {
583-
value = timestamp_type{tp};
583+
value = detail::basic_timestamp_type<Fsp>{tp};
584584
return *this;
585585
}
586-
constexpr base& operator=(timestamp_type v) noexcept {
586+
constexpr base& operator=(detail::basic_timestamp_type<Fsp> v) noexcept {
587587
value = std::move(v);
588588
return *this;
589589
}
590-
constexpr base& operator=(std::optional<timestamp_type> v) noexcept {
590+
constexpr base& operator=(std::optional<detail::basic_timestamp_type<Fsp>> v) noexcept {
591591
value = std::move(v);
592592
return *this;
593593
}
594594

595-
[[nodiscard]] constexpr std::optional<timestamp_type> const& get() const noexcept {
595+
[[nodiscard]] constexpr std::optional<detail::basic_timestamp_type<Fsp>> const& get() const noexcept {
596596
return value;
597597
}
598-
[[nodiscard]] constexpr std::optional<timestamp_type>& get() noexcept {
598+
[[nodiscard]] constexpr std::optional<detail::basic_timestamp_type<Fsp>>& get() noexcept {
599599
return value;
600600
}
601601

602-
constexpr operator std::optional<timestamp_type> const&() const noexcept {
602+
constexpr operator std::optional<detail::basic_timestamp_type<Fsp>> const&() const noexcept {
603603
return value;
604604
}
605-
constexpr operator std::optional<timestamp_type>&() noexcept {
605+
constexpr operator std::optional<detail::basic_timestamp_type<Fsp>>&() noexcept {
606606
return value;
607607
}
608608
};

lib/include/ds_mysql/schema_generator.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,32 @@ struct sql_type_name {
8787
}
8888
} else if constexpr (std::same_as<base_type, std::chrono::system_clock::time_point>) {
8989
return "DATETIME";
90-
} else if constexpr (std::same_as<base_type, datetime_type>) {
91-
return "DATETIME";
92-
} else if constexpr (std::same_as<base_type, timestamp_type>) {
93-
return "TIMESTAMP";
94-
} else if constexpr (std::same_as<base_type, time_type>) {
95-
return "TIME";
90+
} else if constexpr (is_datetime_type_v<base_type>) {
91+
if constexpr (base_type::column_fsp == 0) {
92+
return "DATETIME";
93+
} else {
94+
return "DATETIME(" + std::to_string(base_type::column_fsp) + ")";
95+
}
96+
} else if constexpr (is_timestamp_type_v<base_type>) {
97+
if constexpr (base_type::column_fsp == 0) {
98+
return "TIMESTAMP";
99+
} else {
100+
return "TIMESTAMP(" + std::to_string(base_type::column_fsp) + ")";
101+
}
102+
} else if constexpr (is_time_type_v<base_type>) {
103+
if constexpr (base_type::column_fsp == 0) {
104+
return "TIME";
105+
} else {
106+
return "TIME(" + std::to_string(base_type::column_fsp) + ")";
107+
}
96108
} else {
97109
static_assert(false,
98110
"Unsupported type for SQL mapping. Supported: uint32_t, int32_t, uint64_t, "
99111
"int64_t, float, double, float_type<P,S>, double_type<P,S>, decimal_type<P,S>, "
100112
"bool, varchar_field<N>, text_field (TEXT), "
101113
"mediumtext_field (MEDIUMTEXT, MySQL), longtext_field (LONGTEXT, MySQL), "
102-
"std::chrono::system_clock::time_point, datetime_type, timestamp_type, time_type, "
103-
"and their std::optional variants");
114+
"std::chrono::system_clock::time_point, datetime_type<Fsp>, timestamp_type<Fsp>, "
115+
"time_type<Fsp>, and their std::optional variants");
104116
}
105117
} // end else (not ColumnFieldType)
106118
}

lib/include/ds_mysql/sql.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ std::string to_sql_value(T const& v) {
248248
return "NULL";
249249
}
250250
return to_sql_value(v.value());
251-
} else if constexpr (std::same_as<T, datetime_type>) {
251+
} else if constexpr (is_datetime_type_v<T>) {
252252
if (v.is_now()) {
253253
auto const precision = normalize_fractional_second_precision(v.fractional_second_precision());
254254
if (precision == 0U) {
@@ -257,7 +257,7 @@ std::string to_sql_value(T const& v) {
257257
return "NOW(" + std::to_string(precision) + ")";
258258
}
259259
return format_datetime(v.time_point(), v.fractional_second_precision());
260-
} else if constexpr (std::same_as<T, timestamp_type>) {
260+
} else if constexpr (is_timestamp_type_v<T>) {
261261
if (v.is_now()) {
262262
auto const precision = normalize_fractional_second_precision(v.fractional_second_precision());
263263
if (precision == 0U) {
@@ -268,7 +268,7 @@ std::string to_sql_value(T const& v) {
268268
return format_datetime(v.time_point(), v.fractional_second_precision());
269269
} else if constexpr (std::same_as<T, std::chrono::system_clock::time_point>) {
270270
return format_datetime(v);
271-
} else if constexpr (std::same_as<T, time_type>) {
271+
} else if constexpr (is_time_type_v<T>) {
272272
return format_time(v.duration(), v.fractional_second_precision());
273273
} else if constexpr (std::same_as<T, bool>) {
274274
return v ? "1" : "0";
@@ -299,9 +299,9 @@ std::string to_sql_value(T const& v) {
299299
// Constrains template parameters that must produce a valid SQL literal.
300300
// ===================================================================
301301
template <typename T>
302-
concept SqlValue = ColumnFieldType<T> || is_optional_v<T> || std::same_as<T, datetime_type> ||
303-
std::same_as<T, timestamp_type> || std::same_as<T, std::chrono::system_clock::time_point> ||
304-
std::same_as<T, time_type> || std::same_as<T, bool> || std::integral<T> || std::floating_point<T> ||
302+
concept SqlValue = ColumnFieldType<T> || is_optional_v<T> || is_datetime_type_v<T> || is_timestamp_type_v<T> ||
303+
std::same_as<T, std::chrono::system_clock::time_point> || is_time_type_v<T> ||
304+
std::same_as<T, bool> || std::integral<T> || std::floating_point<T> ||
305305
is_formatted_numeric_type_v<T> || is_varchar_field_v<T> || std::same_as<T, std::string>;
306306

307307
// ===================================================================
@@ -4955,7 +4955,7 @@ T from_mysql_value_nonnull(std::string_view sv) {
49554955
std::tm tm{};
49564956
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
49574957
return std::chrono::system_clock::from_time_t(std::mktime(&tm));
4958-
} else if constexpr (std::same_as<T, time_type>) {
4958+
} else if constexpr (is_time_type_v<T>) {
49594959
bool const negative = !sv.empty() && sv[0] == '-';
49604960
std::string_view const s = negative ? sv.substr(1) : sv;
49614961
auto const c1 = s.find(':');
@@ -4975,7 +4975,7 @@ T from_mysql_value_nonnull(std::string_view sv) {
49754975
int64_t total_us = (hours * 3600LL + mins * 60LL + secs) * 1000000LL + frac_us;
49764976
if (negative)
49774977
total_us = -total_us;
4978-
return time_type{std::chrono::microseconds{total_us}};
4978+
return T{std::chrono::microseconds{total_us}};
49794979
} else {
49804980
static_assert(false,
49814981
"Unsupported type for MySQL deserialization. "

0 commit comments

Comments
 (0)