Skip to content

Commit 4822ea4

Browse files
author
Pierre-Luc Gagné
committed
Rename SQL wrapper types and headers
1 parent 9087e3d commit 4822ea4

20 files changed

Lines changed: 242 additions & 232 deletions

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4545
- Boost.PFR powered compile-time reflection — no macros required for reflection.
4646
- `COLUMN_FIELD` macro for ergonomic per-table, per-column unique type definitions.
4747
- Strong-type wrappers: `host_name`, `database_name`, `port_number`, `user_name`,
48-
`user_password`, `varchar_field<N>`, `text_field`.
48+
`user_password`, `varchar_type<N>`, `text_type`.
4949
- `std::optional<T>` support mapping to nullable SQL columns.
5050
- `std::expected`-based error handling throughout — no exceptions in the query path.
5151
- SQL extension helpers: `ROUND`, `FORMAT`, `COALESCE`, `IFNULL`, `DATE_FORMAT`,

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DSMySQL provides a **header-only** library for building type-safe SQL queries an
1212
- **Schema validation** — verify a live database schema against your C++ definitions
1313
- **C++23** — uses `std::expected`, concepts, ranges, and structured bindings
1414
- **Zero-overhead abstractions** — all query building happens at compile time
15-
- **Strong types**`host_name`, `database_name`, `port_number`, `varchar_field<N>`, etc.
15+
- **Strong types**`host_name`, `database_name`, `port_number`, `varchar_type<N>`, etc.
1616
- **Optional support**`std::optional<T>` maps to nullable SQL columns automatically
1717
- **Temporal types**`datetime_type`, `timestamp_type`, and `time_type` map to MySQL
1818
`DATETIME`, `TIMESTAMP`, and `TIME`; `sql_now` sentinel resolves to `NOW()`
@@ -31,8 +31,8 @@ using namespace ds_mysql;
3131
// one-liner that generates a nested tag struct, a type alias, and a member.
3232
struct product {
3333
COLUMN_FIELD(id, uint32_t)
34-
COLUMN_FIELD(sku, varchar_field<64>)
35-
COLUMN_FIELD(name, varchar_field<255>)
34+
COLUMN_FIELD(sku, varchar_type<64>)
35+
COLUMN_FIELD(name, varchar_type<255>)
3636
COLUMN_FIELD(price, double)
3737
};
3838

@@ -77,7 +77,7 @@ auto db = mysql_database::connect(mysql_config{
7777
// CREATE TABLE IF NOT EXISTS product (...)
7878
db.execute(create_table<product>().if_not_exists());
7979

80-
// Type-safe SELECT: returns std::expected<std::vector<std::tuple<uint32_t, varchar_field<255>>>, std::string>
80+
// Type-safe SELECT: returns std::expected<std::vector<std::tuple<uint32_t, varchar_type<255>>>, std::string>
8181
auto rows = db.query(select<product::id, product::name>()
8282
.from<product>()
8383
.where(product::price{9.99})

docs/QUICKREF.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ DSMySQL/
5757
| `ds_mysql/column_field.hpp` | Typed column descriptors |
5858
| `ds_mysql/schema_generator.hpp` | Schema generation |
5959
| `ds_mysql/config.hpp` | Connection configuration |
60-
| `ds_mysql/varchar_field.hpp` | Fixed-length string type |
60+
| `ds_mysql/sql_varchar.hpp` | Fixed-length string type |
6161

6262
## Environment Variables (Integration Tests)
6363

examples/basic_query.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ constexpr unsigned int port = 3306;
4343

4444
struct product {
4545
COLUMN_FIELD(id, uint32_t)
46-
COLUMN_FIELD(sku, ds_mysql::varchar_field<64>)
47-
COLUMN_FIELD(name, ds_mysql::varchar_field<255>)
46+
COLUMN_FIELD(sku, ds_mysql::varchar_type<64>)
47+
COLUMN_FIELD(name, ds_mysql::varchar_type<255>)
4848
COLUMN_FIELD(price, double)
4949
COLUMN_FIELD(stock, uint32_t)
50-
COLUMN_FIELD(description, std::optional<ds_mysql::varchar_field<512>>)
50+
COLUMN_FIELD(description, std::optional<ds_mysql::varchar_type<512>>)
5151
COLUMN_FIELD(created_at, ds_mysql::datetime_type<>)
5252
};
5353

examples/schema_generation.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
struct user {
2424
COLUMN_FIELD(id, uint32_t)
25-
COLUMN_FIELD(username, ds_mysql::varchar_field<64>)
26-
COLUMN_FIELD(email, ds_mysql::varchar_field<255>)
25+
COLUMN_FIELD(username, ds_mysql::varchar_type<64>)
26+
COLUMN_FIELD(email, ds_mysql::varchar_type<255>)
2727
COLUMN_FIELD(is_active, bool)
2828
COLUMN_FIELD(created_at, ds_mysql::datetime_type<>)
2929
};
@@ -40,7 +40,7 @@ struct order_row {
4040
COLUMN_FIELD(user_id, uint32_t)
4141
COLUMN_FIELD(amount, double)
4242
COLUMN_FIELD(fee, std::optional<double>)
43-
COLUMN_FIELD(status, ds_mysql::varchar_field<32>)
43+
COLUMN_FIELD(status, ds_mysql::varchar_type<32>)
4444

4545
struct order_created_at_tag {};
4646
using created_at = ds_mysql::tagged_column_field<order_created_at_tag, ds_mysql::datetime_type<>>;

examples/tables_with_constraints.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
struct symbol {
2424
COLUMN_FIELD(id, int32_t)
2525
COLUMN_FIELD(exchange_id, std::optional<int32_t>)
26-
COLUMN_FIELD(ticker, ds_mysql::varchar_field<32>)
27-
COLUMN_FIELD(instrument, ds_mysql::varchar_field<64>)
28-
COLUMN_FIELD(name, std::optional<ds_mysql::varchar_field<255>>)
29-
COLUMN_FIELD(sector, std::optional<ds_mysql::varchar_field<255>>)
30-
COLUMN_FIELD(currency, std::optional<ds_mysql::varchar_field<32>>)
26+
COLUMN_FIELD(ticker, ds_mysql::varchar_type<32>)
27+
COLUMN_FIELD(instrument, ds_mysql::varchar_type<64>)
28+
COLUMN_FIELD(name, std::optional<ds_mysql::varchar_type<255>>)
29+
COLUMN_FIELD(sector, std::optional<ds_mysql::varchar_type<255>>)
30+
COLUMN_FIELD(currency, std::optional<ds_mysql::varchar_type<32>>)
3131
COLUMN_FIELD(created_date, ds_mysql::datetime_type<>)
3232
COLUMN_FIELD(last_updated_date, ds_mysql::datetime_type<>)
3333
};

lib/include/ds_mysql/column_field.hpp

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
#include "ds_mysql/fixed_string.hpp"
1212
#include "ds_mysql/name_reflection.hpp"
13-
#include "ds_mysql/numeric_field.hpp"
13+
#include "ds_mysql/sql_numeric.hpp"
1414
#include "ds_mysql/sql_temporal.hpp"
15-
#include "ds_mysql/varchar_field.hpp"
15+
#include "ds_mysql/sql_varchar.hpp"
1616

1717
namespace ds_mysql {
1818

@@ -316,42 +316,42 @@ struct base<std::string> : column_field_tag {
316316
};
317317

318318
template <std::size_t N>
319-
struct base<varchar_field<N>> : column_field_tag {
320-
using value_type = varchar_field<N>;
319+
struct base<varchar_type<N>> : column_field_tag {
320+
using value_type = varchar_type<N>;
321321

322-
varchar_field<N> value{};
322+
varchar_type<N> value{};
323323

324324
constexpr base() = default;
325-
constexpr base(varchar_field<N> v) noexcept(std::is_nothrow_move_constructible_v<varchar_field<N>>)
325+
constexpr base(varchar_type<N> v) noexcept(std::is_nothrow_move_constructible_v<varchar_type<N>>)
326326
: value(std::move(v)) {
327327
}
328328

329329
template <std::size_t M>
330-
constexpr base(char const (&v)[M]) noexcept(std::is_nothrow_move_constructible_v<varchar_field<N>>) : value(v) {
330+
constexpr base(char const (&v)[M]) noexcept(std::is_nothrow_move_constructible_v<varchar_type<N>>) : value(v) {
331331
}
332332

333-
constexpr base& operator=(varchar_field<N> v) noexcept(std::is_nothrow_move_assignable_v<varchar_field<N>>) {
333+
constexpr base& operator=(varchar_type<N> v) noexcept(std::is_nothrow_move_assignable_v<varchar_type<N>>) {
334334
value = std::move(v);
335335
return *this;
336336
}
337337

338338
template <std::size_t M>
339-
constexpr base& operator=(char const (&v)[M]) noexcept(std::is_nothrow_move_assignable_v<varchar_field<N>>) {
339+
constexpr base& operator=(char const (&v)[M]) noexcept(std::is_nothrow_move_assignable_v<varchar_type<N>>) {
340340
value = v;
341341
return *this;
342342
}
343343

344-
[[nodiscard]] constexpr varchar_field<N> const& get() const noexcept {
344+
[[nodiscard]] constexpr varchar_type<N> const& get() const noexcept {
345345
return value;
346346
}
347-
[[nodiscard]] constexpr varchar_field<N>& get() noexcept {
347+
[[nodiscard]] constexpr varchar_type<N>& get() noexcept {
348348
return value;
349349
}
350350

351-
constexpr operator varchar_field<N> const&() const noexcept {
351+
constexpr operator varchar_type<N> const&() const noexcept {
352352
return value;
353353
}
354-
constexpr operator varchar_field<N>&() noexcept {
354+
constexpr operator varchar_type<N>&() noexcept {
355355
return value;
356356
}
357357
constexpr operator std::string_view() const noexcept {
@@ -360,57 +360,57 @@ struct base<varchar_field<N>> : column_field_tag {
360360
};
361361

362362
template <std::size_t N>
363-
struct base<std::optional<varchar_field<N>>> : column_field_tag {
364-
using value_type = std::optional<varchar_field<N>>;
363+
struct base<std::optional<varchar_type<N>>> : column_field_tag {
364+
using value_type = std::optional<varchar_type<N>>;
365365

366-
std::optional<varchar_field<N>> value{};
366+
std::optional<varchar_type<N>> value{};
367367

368368
constexpr base() = default;
369369
constexpr base(std::nullopt_t) noexcept : value(std::nullopt) {
370370
}
371-
constexpr base(varchar_field<N> v) noexcept(std::is_nothrow_move_constructible_v<varchar_field<N>>)
371+
constexpr base(varchar_type<N> v) noexcept(std::is_nothrow_move_constructible_v<varchar_type<N>>)
372372
: value(std::move(v)) {
373373
}
374-
constexpr base(std::optional<varchar_field<N>> v) noexcept(
375-
std::is_nothrow_move_constructible_v<std::optional<varchar_field<N>>>)
374+
constexpr base(std::optional<varchar_type<N>> v) noexcept(
375+
std::is_nothrow_move_constructible_v<std::optional<varchar_type<N>>>)
376376
: value(std::move(v)) {
377377
}
378378

379379
template <std::size_t M>
380-
constexpr base(char const (&v)[M]) noexcept(std::is_nothrow_move_constructible_v<varchar_field<N>>) : value(v) {
380+
constexpr base(char const (&v)[M]) noexcept(std::is_nothrow_move_constructible_v<varchar_type<N>>) : value(v) {
381381
}
382382

383383
constexpr base& operator=(std::nullopt_t) noexcept {
384384
value = std::nullopt;
385385
return *this;
386386
}
387-
constexpr base& operator=(varchar_field<N> v) noexcept(std::is_nothrow_move_assignable_v<varchar_field<N>>) {
387+
constexpr base& operator=(varchar_type<N> v) noexcept(std::is_nothrow_move_assignable_v<varchar_type<N>>) {
388388
value = std::move(v);
389389
return *this;
390390
}
391-
constexpr base& operator=(std::optional<varchar_field<N>> v) noexcept(
392-
std::is_nothrow_move_assignable_v<std::optional<varchar_field<N>>>) {
391+
constexpr base& operator=(std::optional<varchar_type<N>> v) noexcept(
392+
std::is_nothrow_move_assignable_v<std::optional<varchar_type<N>>>) {
393393
value = std::move(v);
394394
return *this;
395395
}
396396

397397
template <std::size_t M>
398-
constexpr base& operator=(char const (&v)[M]) noexcept(std::is_nothrow_move_assignable_v<varchar_field<N>>) {
399-
value = varchar_field<N>{v};
398+
constexpr base& operator=(char const (&v)[M]) noexcept(std::is_nothrow_move_assignable_v<varchar_type<N>>) {
399+
value = varchar_type<N>{v};
400400
return *this;
401401
}
402402

403-
[[nodiscard]] constexpr std::optional<varchar_field<N>> const& get() const noexcept {
403+
[[nodiscard]] constexpr std::optional<varchar_type<N>> const& get() const noexcept {
404404
return value;
405405
}
406-
[[nodiscard]] constexpr std::optional<varchar_field<N>>& get() noexcept {
406+
[[nodiscard]] constexpr std::optional<varchar_type<N>>& get() noexcept {
407407
return value;
408408
}
409409

410-
constexpr operator std::optional<varchar_field<N>> const&() const noexcept {
410+
constexpr operator std::optional<varchar_type<N>> const&() const noexcept {
411411
return value;
412412
}
413-
constexpr operator std::optional<varchar_field<N>>&() noexcept {
413+
constexpr operator std::optional<varchar_type<N>>&() noexcept {
414414
return value;
415415
}
416416
};
@@ -622,8 +622,8 @@ struct base<std::optional<timestamp_type<Fsp>>> : column_field_tag {
622622
* internal base type.
623623
*
624624
* using id = column_field<"id", uint32_t>;
625-
* using ticker = column_field<"ticker", varchar_field<32>>;
626-
* using sector = column_field<"sector", std::optional<varchar_field<64>>>;
625+
* using ticker = column_field<"ticker", varchar_type<32>>;
626+
* using sector = column_field<"sector", std::optional<varchar_type<64>>>;
627627
*
628628
* id id_;
629629
* ticker ticker_;

lib/include/ds_mysql/ds_mysql.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// metadata.hpp — runtime metadata helpers (column info, schema introspection)
1010
//
1111
// All other library headers (column_field, schema_generator, sql_identifiers,
12-
// sql_temporal, varchar_field, text_field, config, credentials, …) are
12+
// sql_temporal, sql_varchar, sql_text, config, credentials, …) are
1313
// pulled in transitively by the four headers above.
1414

1515
#include "ds_mysql/database.hpp"

lib/include/ds_mysql/schema_generator.hpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313
#include "ds_mysql/column_field.hpp"
1414
#include "ds_mysql/name_reflection.hpp"
1515
#include "ds_mysql/sql_identifiers.hpp"
16+
#include "ds_mysql/sql_numeric.hpp"
1617
#include "ds_mysql/sql_temporal.hpp"
17-
#include "ds_mysql/text_field.hpp"
18-
#include "ds_mysql/varchar_field.hpp"
18+
#include "ds_mysql/sql_text.hpp"
19+
#include "ds_mysql/sql_varchar.hpp"
1920

2021
namespace ds_mysql {
2122

@@ -74,17 +75,8 @@ struct sql_type_name {
7475
return "DOUBLE";
7576
} else if constexpr (std::same_as<base_type, bool>) {
7677
return "BOOLEAN";
77-
} else if constexpr (is_varchar_field_v<base_type>) {
78-
return "VARCHAR(" + std::to_string(is_varchar_field<base_type>::capacity) + ")";
79-
} else if constexpr (is_text_field_v<base_type>) {
80-
constexpr auto kind = is_text_field<base_type>::kind;
81-
if constexpr (kind == text_kind::mediumtext) {
82-
return "MEDIUMTEXT";
83-
} else if constexpr (kind == text_kind::longtext) {
84-
return "LONGTEXT";
85-
} else {
86-
return "TEXT";
87-
}
78+
} else if constexpr (is_varchar_type_v<base_type> || is_text_type_v<base_type>) {
79+
return base_type::sql_type();
8880
} else if constexpr (std::same_as<base_type, std::chrono::system_clock::time_point>) {
8981
return "DATETIME";
9082
} else if constexpr (is_datetime_type_v<base_type>) {
@@ -109,8 +101,8 @@ struct sql_type_name {
109101
static_assert(false,
110102
"Unsupported type for SQL mapping. Supported: uint32_t, int32_t, uint64_t, "
111103
"int64_t, float, double, float_type<P,S>, double_type<P,S>, decimal_type<P,S>, "
112-
"bool, varchar_field<N>, text_field (TEXT), "
113-
"mediumtext_field (MEDIUMTEXT, MySQL), longtext_field (LONGTEXT, MySQL), "
104+
"bool, varchar_type<N>, text_type (TEXT), "
105+
"mediumtext_type (MEDIUMTEXT, MySQL), longtext_type (LONGTEXT, MySQL), "
114106
"std::chrono::system_clock::time_point, datetime_type<Fsp>, timestamp_type<Fsp>, "
115107
"time_type<Fsp>, and their std::optional variants");
116108
}

lib/include/ds_mysql/sql.hpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "ds_mysql/name_reflection.hpp"
2626
#include "ds_mysql/schema_generator.hpp"
2727
#include "ds_mysql/sql_temporal.hpp"
28-
#include "ds_mysql/varchar_field.hpp"
28+
#include "ds_mysql/sql_varchar.hpp"
2929

3030
namespace ds_mysql {
3131

@@ -236,7 +236,7 @@ inline std::string format_time(std::chrono::microseconds dur, uint32_t fractiona
236236
* to_sql_value — convert a typed C++ value to its SQL literal representation.
237237
*
238238
* Handles: column_field<T> wrappers, std::optional<T>, datetime_type, bool,
239-
* integral types, floating-point types, varchar_field<N>, std::string, and
239+
* integral types, floating-point types, varchar_type<N>, text_type, std::string, and
240240
* std::chrono::system_clock::time_point.
241241
*/
242242
template <typename T>
@@ -278,7 +278,7 @@ std::string to_sql_value(T const& v) {
278278
return std::to_string(v);
279279
} else if constexpr (std::floating_point<T>) {
280280
return std::to_string(v);
281-
} else if constexpr (is_varchar_field_v<T>) {
281+
} else if constexpr (is_varchar_type_v<T> || is_text_type_v<T>) {
282282
return "'" + escape_sql_string(v.view()) + "'";
283283
} else if constexpr (std::same_as<T, std::string>) {
284284
return "'" + escape_sql_string(v) + "'";
@@ -287,7 +287,7 @@ std::string to_sql_value(T const& v) {
287287
"to_sql_value: unsupported type. "
288288
"Supported: column_field<T>, optional<T>, datetime_type, timestamp_type, bool, "
289289
"integral types, floating-point types, float_type<P,S>, double_type<P,S>, "
290-
"decimal_type<P,S>, varchar_field<N>, std::string, "
290+
"decimal_type<P,S>, varchar_type<N>, text_type, std::string, "
291291
"std::chrono::system_clock::time_point, time_type");
292292
}
293293
}
@@ -299,10 +299,11 @@ 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> || 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> ||
305-
is_formatted_numeric_type_v<T> || is_varchar_field_v<T> || std::same_as<T, std::string>;
302+
concept SqlValue =
303+
ColumnFieldType<T> || is_optional_v<T> || is_datetime_type_v<T> || is_timestamp_type_v<T> ||
304+
std::same_as<T, std::chrono::system_clock::time_point> || is_time_type_v<T> || std::same_as<T, bool> ||
305+
std::integral<T> || std::floating_point<T> || is_formatted_numeric_type_v<T> || is_varchar_type_v<T> ||
306+
is_text_type_v<T> || std::same_as<T, std::string>;
306307

307308
// ===================================================================
308309
// where_condition — a typed SQL WHERE fragment
@@ -655,7 +656,7 @@ struct col_expr {
655656
using value_type = typename Col::value_type;
656657

657658
// Operators accept value_type directly; callers must construct explicitly
658-
// (e.g. col_ref<trade::code> == varchar_field<32>{"AAPL"}).
659+
// (e.g. col_ref<trade::code> == varchar_type<32>{"AAPL"}).
659660
[[nodiscard]] where_condition operator==(value_type const& val) const {
660661
return equal<Col>(Col{val});
661662
}
@@ -4948,8 +4949,10 @@ T from_mysql_value_nonnull(std::string_view sv) {
49484949
return sv != "0" && sv != "false" && !sv.empty();
49494950
} else if constexpr (std::same_as<T, std::string>) {
49504951
return std::string{sv};
4951-
} else if constexpr (is_varchar_field_v<T>) {
4952+
} else if constexpr (is_varchar_type_v<T>) {
49524953
return T::create(sv).value_or(T{});
4954+
} else if constexpr (is_text_type_v<T>) {
4955+
return T{sv};
49534956
} else if constexpr (std::same_as<T, std::chrono::system_clock::time_point>) {
49544957
std::istringstream ss{std::string{sv}};
49554958
std::tm tm{};
@@ -4980,7 +4983,7 @@ T from_mysql_value_nonnull(std::string_view sv) {
49804983
static_assert(false,
49814984
"Unsupported type for MySQL deserialization. "
49824985
"Supported: uint32_t, int32_t, uint64_t, int64_t, float, double, float_type<P,S>, "
4983-
"double_type<P,S>, decimal_type<P,S>, bool, std::string, varchar_field<N>, "
4986+
"double_type<P,S>, decimal_type<P,S>, bool, std::string, varchar_type<N>, text_type, "
49844987
"std::chrono::system_clock::time_point (for DATETIME/TIMESTAMP), time_type, "
49854988
"and their std::optional variants.");
49864989
}

0 commit comments

Comments
 (0)