1#ifndef NEFORCE_DATABASE_SQL_MAPPER_HPP__
2#define NEFORCE_DATABASE_SQL_MAPPER_HPP__
30NEFORCE_BEGIN_NAMESPACE__
45 if (tid == type_id_for<short>()) {
48 if (tid == type_id_for<unsigned short>()) {
51 if (tid == type_id_for<int>()) {
54 if (tid == type_id_for<unsigned int>()) {
57#ifdef NEFORCE_PLATFORM_WINDOWS
58 if (tid == type_id_for<long>()) {
61 if (tid == type_id_for<unsigned long>()) {
65 if (tid == type_id_for<long>()) {
68 if (tid == type_id_for<unsigned long>()) {
72 if (tid == type_id_for<long long>()) {
75 if (tid == type_id_for<unsigned long long>()) {
78 if (tid == type_id_for<double>()) {
79 return "DOUBLE PRECISION";
81 if (tid == type_id_for<float>()) {
84 if (tid == type_id_for<bool>()) {
87 if (tid == type_id_for<string>()) {
102 if (tid == type_id_for<int>()) {
104 }
else if (tid == type_id_for<int64_t>()) {
106 }
else if (tid == type_id_for<short>()) {
108 }
else if (tid == type_id_for<double>()) {
110 }
else if (tid == type_id_for<float>()) {
112 }
else if (tid == type_id_for<bool>()) {
114 }
else if (tid == type_id_for<string>()) {
127 if (!val.has_value()) {
130 const auto tid = val.type_id();
133 if (tid == type_id_for<int>()) {
134 return integer32(val.get<
int>()).to_string();
135 }
else if (tid == type_id_for<int64_t>()) {
137 }
else if (tid == type_id_for<short>()) {
138 return integer32(val.get<
short>()).to_string();
139 }
else if (tid == type_id_for<double>()) {
140 return float64(val.get<
double>()).to_string();
141 }
else if (tid == type_id_for<float>()) {
142 return float64(val.get<
float>()).to_string();
143 }
else if (tid == type_id_for<bool>()) {
144 return val.get<
bool>() ?
"1" :
"0";
145 }
else if (tid == type_id_for<string>()) {
147 const auto& s = val.get<
string>();
149 escaped.reserve(s.size() + 2);
151 for (
const auto ch: s) {
177 if (meta ==
nullptr) {
185 static string resolve_table_name() {
186 const auto* meta = get_meta();
187 const auto tn = meta->table_name();
198 const auto* meta = get_meta();
200 for (
const auto& entry: meta->all_properties()) {
201 const auto* prop = entry.second;
202 if (prop->is_transient()) {
205 if (!include_pk && prop->is_auto_increment()) {
217 const auto* meta = get_meta();
218 for (
const auto& entry: meta->all_properties()) {
219 if (entry.second->is_primary_key()) {
239 const auto* meta = get_meta();
240 const string tbl = table_override.empty() ? resolve_table_name() :
string(table_override);
245 for (
const auto& entry: meta->all_properties()) {
246 const auto* prop = entry.second;
247 if (prop->is_transient()) {
253 if (prop->is_primary_key() && prop->is_auto_increment()) {
255 }
else if (prop->is_primary_key()) {
257 }
else if (prop->is_unique()) {
259 }
else if (prop->is_required()) {
262 b.
column(prop->name(), sql_type);
275 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
287 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
290 const auto* meta = get_meta();
292 for (
const auto& entry: meta->all_properties()) {
293 if (entry.second->is_transient()) {
296 b.
select(entry.second->name());
309 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
311 const auto props = collect_persistent_props(
false);
314 for (
const auto* p: props) {
332 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
333 const auto* pk = find_pk_prop();
335 NEFORCE_THROW_EXCEPTION(
value_exception(
"sql_mapper: no primary key defined for DELETE"));
353 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
354 const auto* pk = find_pk_prop();
356 NEFORCE_THROW_EXCEPTION(
value_exception(
"sql_mapper: no primary key defined for UPDATE"));
359 const auto props = collect_persistent_props(
true);
365 for (
const auto* p: props) {
366 if (p->is_primary_key() || p->is_auto_increment()) {
383 const auto props = collect_persistent_props(include_pk);
385 values.reserve(props.size());
386 for (
const auto* prop: props) {
399 const auto* pk = find_pk_prop();
403 return pk->get(&entity);
413 const auto* meta = get_meta();
414 auto obj_any = meta->create();
415 if (!obj_any.has_value()) {
416 NEFORCE_THROW_EXCEPTION(
value_exception(
"sql_mapper: failed to create entity instance"));
418 void* raw = obj_any.raw();
420 unordered_map<string, size_t> effective_map;
421 if (col_map.empty()) {
423 for (
size_t i = 0; i < names.size(); ++i) {
424 effective_map[names[i]] = i;
427 effective_map = col_map;
430 for (
const auto& entry: meta->all_properties()) {
431 const auto* prop = entry.second;
432 if (prop->is_transient() || prop->is_readonly()) {
436 auto it = effective_map.find(prop->name());
437 if (it == effective_map.end()) {
445 return *
static_cast<T*
>(raw);
455 if (result ==
nullptr || result->empty()) {
460 const auto& names = result->column_names();
461 for (
size_t i = 0; i < names.size(); ++i) {
462 col_map[names[i]] = i;
465 while (result->next()) {
478 const string tbl = table_override.
empty() ? resolve_table_name() :
string(table_override);
479 const auto* pk = find_pk_prop();
481 NEFORCE_THROW_EXCEPTION(
value_exception(
"sql_mapper: no primary key defined for SELECT BY PK"));
484 const auto* meta = get_meta();
487 for (
const auto& entry: meta->all_properties()) {
488 if (entry.second->is_transient()) {
491 b.
select(entry.second->name());
501NEFORCE_END_NAMESPACE__
constexpr bool empty() const noexcept
检查是否为空
static registry & instance()
获取单例实例
sql_builder & where_eq(string field, string value)
添加相等条件
sql_builder & from(string table) noexcept
设置主表
sql_builder & column_not_null(string name, string type)
添加带NOT NULL约束的列定义
sql_builder & set_param(string field)
添加 SET 赋值
sql_builder & column_auto_increment(string name, string type)
添加自增主键列定义(事实标准:AUTO_INCREMENT)
sql_builder & column(string name, string type)
添加基础列定义
sql_builder & set_dialect(const sql_dialect dialect) noexcept
设置数据库方言
sql_builder & column_unique(string name, string type)
添加带UNIQUE约束的列定义
string placeholder(const size_t index) const
生成方言感知的参数占位符
string build() const
构建最终的SQL语句
sql_builder & select(vector< string > fields)
列表设置SELECT字段
sql_builder & column_primary_key(string name, string type)
添加PRIMARY KEY列定义
string next_placeholder()
获取下一个参数占位符
sql_builder & update(string table)
设置UPDATE表名
sql_builder & delete_from(string table)
设置DELETE FROM表名
sql_builder & drop_table_if_exists(string table)
删除表(IF EXISTS)
sql_builder & insert_into(string table, vector< string > fields)
设置INSERT INTO表名和字段
sql_builder & create_table_if_not_exists(string table)
创建表(IF NOT EXISTS)
static string select_sql(string_view table_override="")
生成 SELECT 查询 SQL
static string create_table_sql(string_view table_override="")
生成 CREATE TABLE SQL
static T from_row(const idb_tb_result &row, const unordered_map< string, size_t > &col_map={})
从结果行构建实体对象
static reflect::meta_any get_pk_value(const T &entity)
获取主键值
static string delete_sql(string_view table_override="", const sql_dialect dialect=sql_dialect::GENERIC)
生成 DELETE SQL(按主键删除)
static string insert_sql(string_view table_override="", const sql_dialect dialect=sql_dialect::GENERIC)
生成 INSERT SQL(占位符由方言自动决定)
static vector< T > from_result(unique_ptr< idb_tb_result > result)
从查询结果集构建实体对象列表
static vector< string > get_values(const T &entity, bool include_pk=true)
从实体提取所有持久化字段的值(以 SQL 字面量表示)
static string drop_table_sql(string_view table_override="")
生成 DROP TABLE SQL
static string table_name()
获取映射的表名
static string update_sql(string_view table_override="", const sql_dialect dialect=sql_dialect::GENERIC)
生成 UPDATE SQL(按主键更新所有非主键字段)
static string select_by_pk_sql(string_view table_override="", const sql_dialect dialect=sql_dialect::GENERIC)
生成按主键查询的 SELECT SQL
constexpr void reserve(const size_type n)
预留容量
constexpr void push_back(const T &value)
在末尾拷贝插入元素
constexpr type_id type_id_for() noexcept
计算类型 T 的运行时期类型标识
constexpr string_view type_name_v
type_name 的便捷访问变量模板
string cpp_type_to_sql_type(const reflect::type_id tid)
将 C++ 类型 ID 映射为 SQL 类型名称
reflect::meta_any read_column_by_type(const idb_tb_result &row, const size_t col, const reflect::type_id tid)
从结果行中按类型ID读取值到 meta_any
string meta_any_to_sql_literal(const reflect::meta_any &val)
将 meta_any 值转换为 SQL 字面量字符串
basic_string< char > string
字符字符串
basic_string_view< char > string_view
字符字符串视图
constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
virtual bool get_bool(size_type n) const =0
布尔值
virtual int64_t get_int64(size_type n) const =0
64位整数
virtual int32_t get_int32(size_type n) const =0
32位整数
virtual string_view get(size_type n) const =0
字符串
virtual float64_t get_float64(size_type n) const =0
64位浮点数
virtual const vector< string_view > & column_names() const =0
获取所有列名
virtual float32_t get_float32(size_type n) const =0
32位浮点数