Skip to content

Instantly share code, notes, and snippets.

@OperationDarkside
Created January 13, 2026 21:33
Show Gist options
  • Select an option

  • Save OperationDarkside/bb692e33c848b63d8c0db1a41ed3e3d7 to your computer and use it in GitHub Desktop.

Select an option

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.
#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