Created
January 13, 2026 21:33
-
-
Save OperationDarkside/bb692e33c848b63d8c0db1a41ed3e3d7 to your computer and use it in GitHub Desktop.
Creates create table, select and insert sqlite string via std::meta reflections for all classes of a given namespace. Works with GCC C++26 Reflections branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <string> | |
| #include <string_view> | |
| #include <meta> | |
| #include <vector> | |
| #include <array> | |
| #include <algorithm> | |
| #include <iterator> | |
| namespace db { | |
| struct employee { | |
| int id = 0; | |
| int age = 0; | |
| int group_id = 0; | |
| double salary; | |
| std::string name = "Karl"; | |
| }; | |
| struct group { | |
| int id; | |
| std::string name = "Manager"; | |
| }; | |
| } | |
| struct column { | |
| std::string_view name; | |
| std::string_view type_name; | |
| }; | |
| template <std::meta::info inf> | |
| consteval auto get_nonstatic_data_members() { | |
| constexpr auto ctx = std::meta::access_context::current(); | |
| constexpr size_t N = std::meta::nonstatic_data_members_of(inf, ctx).size(); | |
| const auto members = std::meta::nonstatic_data_members_of(inf, ctx); | |
| std::array<std::meta::info, N> result{}; | |
| for (int i = 0; i < members.size(); i++) { | |
| result[i] = members[i]; | |
| } | |
| return result; | |
| } | |
| consteval auto get_type_name(std::meta::info inf) { | |
| const auto true_type = std::meta::dealias(std::meta::remove_cvref(inf)); | |
| if(true_type == ^^int) { | |
| return "INTEGER"; | |
| } else if (true_type == ^^double) { | |
| return "REAL"; | |
| } else if (std::meta::is_same_type(true_type, ^^std::string)) { | |
| return "TEXT"; | |
| } else { | |
| return "BLOB"; | |
| } | |
| } | |
| template <std::meta::info inf> | |
| consteval auto get_member_names() { | |
| constexpr auto members = get_nonstatic_data_members<inf>(); | |
| std::array<column, members.size()> layout; | |
| for (int i = 0; i < members.size(); ++i) { | |
| const std::string_view name = std::meta::identifier_of(members[i]); | |
| const std::string_view type_name = get_type_name(std::meta::type_of(members[i])); | |
| layout[i] = {name, type_name}; | |
| } | |
| return layout; | |
| } | |
| template<std::size_t N> | |
| consteval std::size_t sum_str_lens(std::array<column, N> member_names) { | |
| std::size_t size = 0; | |
| for(int i = 0; i < N; i++) { | |
| size += member_names[i].name.size(); | |
| if(member_names[i].name == "id") { | |
| size += 12; | |
| } | |
| size += member_names[i].type_name.size(); | |
| } | |
| return size; | |
| } | |
| template<std::size_t N> | |
| consteval std::size_t sum_member_name_str_lens(std::array<column, N> member_names) { | |
| std::size_t size = 0; | |
| for(int i = 0; i < N; i++) { | |
| size += member_names[i].name.size(); | |
| } | |
| return size; | |
| } | |
| template <std::meta::info inf> | |
| consteval auto get_create_sql_impl() { | |
| constexpr auto members = get_nonstatic_data_members<inf>(); | |
| constexpr auto N = members.size(); | |
| // 1. Calculate the exact size needed | |
| constexpr std::string_view sql_start = "CREATE TABLE IF NOT EXISTS "; | |
| constexpr std::string_view table_name = std::meta::identifier_of(inf); | |
| constexpr auto member_names = get_member_names<inf>(); | |
| constexpr std::size_t sql_start_size = sql_start.size() + table_name.size() + 6; // " ( " and "\n);" | |
| constexpr std::size_t member_names_len = sum_str_lens(member_names) + (N * 4); | |
| // 2. Build the result in a fixed_string | |
| constexpr std::size_t total_size = sql_start_size + member_names_len; | |
| std::array<char, total_size> result{}; | |
| auto out = result.begin(); | |
| auto append = [&](std::string_view sv) { | |
| out = std::copy(sv.begin(), sv.end(), out); | |
| }; | |
| append(sql_start); | |
| append(table_name); | |
| append(" (\n"); | |
| for (std::size_t i = 0; i < member_names.size(); ++i) { | |
| append("\t"); | |
| append(member_names[i].name); | |
| append(" "); | |
| append(member_names[i].type_name); | |
| if(member_names[i].name == "id") { | |
| append(" PRIMARY KEY"); | |
| } | |
| if (i < member_names.size() - 1) { | |
| append(",\n"); | |
| } | |
| } | |
| append("\n);"); | |
| return result; | |
| } | |
| template <std::meta::info inf> | |
| consteval auto get_insert_sql_impl() { | |
| constexpr auto members = get_nonstatic_data_members<inf>(); | |
| constexpr auto N = members.size(); | |
| // 1. Calculate the exact size needed | |
| constexpr std::string_view sql_start = "INSERT INTO "; | |
| constexpr std::string_view sql_values = " VALUES ("; | |
| constexpr std::string_view table_name = std::meta::identifier_of(inf); | |
| constexpr auto member_names = get_member_names<inf>(); | |
| constexpr std::size_t sql_start_size = sql_start.size() + table_name.size() + sql_values.size() + 6; // " ( " and "\n);" | |
| constexpr std::size_t member_names_len = sum_member_name_str_lens(member_names) + (N * 6); // "?,"" * N | |
| // 2. Build the result in a fixed_string | |
| constexpr std::size_t total_size = sql_start_size + member_names_len; | |
| std::array<char, total_size> result{}; | |
| auto out = result.begin(); | |
| auto append = [&](std::string_view sv) { | |
| out = std::copy(sv.begin(), sv.end(), out); | |
| }; | |
| append(sql_start); | |
| append(table_name); | |
| append(" (\n"); | |
| for (std::size_t i = 0; i < member_names.size(); ++i) { | |
| append("\t"); | |
| append(member_names[i].name); | |
| if (i < member_names.size() - 1) { | |
| append(",\n"); | |
| } | |
| } | |
| append("\n)"); | |
| append(sql_values); | |
| for (std::size_t i = 0; i < member_names.size(); ++i) { | |
| append("?"); | |
| if (i < member_names.size() - 1) { | |
| append(","); | |
| } | |
| } | |
| append(");"); | |
| return result; | |
| } | |
| template <std::meta::info inf> | |
| consteval auto get_select_sql_impl() { | |
| // 1. Calculate the exact size needed | |
| constexpr std::string_view sql_start = "SELECT * FROM "; | |
| constexpr std::string_view table_name = std::meta::identifier_of(inf); | |
| // 2. Build the result in a fixed_string | |
| constexpr std::size_t total_size = sql_start.size() + table_name.size() + 1; | |
| std::array<char, total_size> result{}; | |
| auto out = result.begin(); | |
| auto append = [&](std::string_view sv) { | |
| out = std::copy(sv.begin(), sv.end(), out); | |
| }; | |
| append(sql_start); | |
| append(table_name); | |
| append(";"); | |
| return result; | |
| } | |
| template <typename T> | |
| consteval std::string_view get_create_sql() { | |
| static constexpr auto bla = get_create_sql_impl<^^T>(); | |
| return std::string_view {bla.begin(), bla.end()}; | |
| } | |
| template <typename T> | |
| consteval std::string_view get_insert_sql() { | |
| static constexpr auto bla = get_insert_sql_impl<^^T>(); | |
| return std::string_view {bla.begin(), bla.end()}; | |
| } | |
| template <typename T> | |
| consteval std::string_view get_select_sql() { | |
| static constexpr auto bla = get_select_sql_impl<^^T>(); | |
| return std::string_view {bla.begin(), bla.end()}; | |
| } | |
| template<std::meta::info ns> | |
| consteval std::size_t get_members_amount() { | |
| constexpr auto ctx = std::meta::access_context::current(); | |
| return std::meta::members_of(ns, ctx).size(); | |
| } | |
| template<std::meta::info ns> | |
| consteval auto get_members() { | |
| constexpr auto ctx = std::meta::access_context::current(); | |
| constexpr std::size_t N = get_members_amount<ns>(); | |
| const auto members = std::meta::members_of(ns, ctx); | |
| std::array<std::meta::info, N> result{}; | |
| for (int i = 0; i < members.size(); i++) { | |
| result[i] = members[i]; | |
| } | |
| return result; | |
| } | |
| template <std::size_t N> | |
| consteval auto get_pure_member_names(std::array<std::meta::info, N> members) { | |
| std::array<column, N> layout; | |
| for (int i = 0; i < N; ++i) { | |
| const std::string_view name = std::meta::identifier_of(members[i]); | |
| const std::string_view type_name = std::meta::display_string_of(members[i]); | |
| layout[i] = {name, type_name}; | |
| } | |
| return layout; | |
| } | |
| template<std::size_t LEN1, std::size_t LEN2, std::size_t LEN3> | |
| consteval auto combine_sql_queries (std::array<char, LEN1> create, std::array<char, LEN2> select, std::array<char, LEN3> insert) { | |
| constexpr std::size_t TOTAL_LEN = LEN1 + LEN2 + LEN3 + 3; | |
| std::array<char, TOTAL_LEN> result{}; | |
| std::array<char, 1> new_line{'\n'}; | |
| auto out = result.begin(); | |
| auto append = [&]<std::size_t N>(std::array<char, N> sv) { | |
| out = std::copy(sv.begin(), sv.end(), out); | |
| }; | |
| append(create); | |
| append(new_line); | |
| append(select); | |
| append(new_line); | |
| append(insert); | |
| append(new_line); | |
| return result; | |
| } | |
| template<std::size_t N, std::array<std::meta::info, N> members> | |
| consteval auto get_all_member_queries() { | |
| std::array<std::string_view, N> queries_by_member{}; | |
| int i = 0; | |
| template for (constexpr auto m : members) { | |
| //constexpr auto m = members[i]; | |
| constexpr auto create = get_create_sql_impl<m>(); | |
| constexpr auto select = get_select_sql_impl<m>(); | |
| constexpr auto insert = get_insert_sql_impl<m>(); | |
| constexpr static auto full = combine_sql_queries(create, select, insert); | |
| queries_by_member[i++] = std::string_view{full.data(), full.size()}; | |
| } | |
| return queries_by_member; | |
| } | |
| template<std::size_t N> | |
| consteval std::size_t get_len_of_sv_array(std::array<std::string_view, N> queries_by_member) { | |
| std::size_t total_len = 0; | |
| for (int i = 0; i < N; ++i) { | |
| total_len += queries_by_member[i].size(); | |
| } | |
| return total_len; | |
| } | |
| template<std::meta::info ns> | |
| consteval auto get_ns_classes() { | |
| if(!std::meta::is_namespace(ns)) { | |
| throw "hello"; | |
| } | |
| constexpr auto members = get_members<ns>(); | |
| constexpr std::size_t N = members.size(); | |
| constexpr auto member_queries_list = get_all_member_queries<N, members>(); | |
| constexpr std::size_t total_queries_len = get_len_of_sv_array(member_queries_list) + N; | |
| //constexpr std::array member_names = get_pure_member_names(members); | |
| //constexpr std::size_t str_len = sum_str_lens(member_names) + member_names.size() * 6; | |
| std::array<char, total_queries_len> result{}; | |
| auto out = result.begin(); | |
| auto append = [&](std::string_view sv) { | |
| out = std::copy(sv.begin(), sv.end(), out); | |
| }; | |
| for(int i = 0; i < N; i++) { | |
| append(member_queries_list[i]); | |
| append("\n"); | |
| } | |
| return result; | |
| } | |
| template<std::meta::info ns> | |
| consteval std::string_view get_ns_member_names() { | |
| static constexpr auto bla = get_ns_classes<ns>(); | |
| return std::string_view {bla.begin(), bla.end()}; | |
| } | |
| int main() | |
| { | |
| constexpr auto all_sqls = get_ns_member_names<^^db>(); | |
| std::cout << all_sqls << "\n\n"; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment