Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
entity.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#include "entity.h"
6#include <sstream>
7#include <algorithm>
8#include <iostream>
9
10// Logging helper macros - using std::cerr/cout for consistent behavior
11// Note: For structured logging, use integrated_database module which provides
12// logger_adapter. The database module itself should not depend on integrated_database
13// to avoid circular dependencies.
14#define ORM_LOG_ERROR(context, message) \
15 std::cerr << "[ORM:" << context << "] Error: " << message << std::endl
16#define ORM_LOG_WARNING(message) \
17 std::cerr << "[ORM] Warning: " << message << std::endl
18#define ORM_LOG_INFO(message) \
19 std::cout << "[ORM] Info: " << message << std::endl
20
21namespace database::orm
22{
23 // field_metadata implementation
24 field_metadata::field_metadata(const std::string& name,
25 const std::string& type_name,
26 field_constraint constraints,
27 const std::string& index_name,
28 const std::string& foreign_table,
29 const std::string& foreign_field)
30 : name_(name)
31 , type_name_(type_name)
32 , constraints_(constraints)
33 , index_name_(index_name)
34 , foreign_table_(foreign_table)
35 , foreign_field_(foreign_field)
36 {
37 }
38
40 {
41 std::ostringstream oss;
42 oss << name_ << " ";
43
44 // Map C++ types to SQL types
45 if (type_name_ == "int32_t" || type_name_ == "int") {
46 oss << "INTEGER";
47 } else if (type_name_ == "int64_t") {
48 oss << "BIGINT";
49 } else if (type_name_ == "double") {
50 oss << "DOUBLE PRECISION";
51 } else if (type_name_ == "std::string") {
52 oss << "VARCHAR(255)";
53 } else if (type_name_ == "bool") {
54 oss << "BOOLEAN";
55 } else if (type_name_.find("time_point") != std::string::npos) {
56 oss << "TIMESTAMP";
57 } else {
58 oss << "TEXT";
59 }
60
61 // Add constraints
62 if (is_primary_key()) {
63 oss << " PRIMARY KEY";
64 }
65 if (is_auto_increment()) {
66 oss << " AUTO_INCREMENT";
67 }
68 if (is_not_null() && !is_primary_key()) {
69 oss << " NOT NULL";
70 }
71 if (is_unique() && !is_primary_key()) {
72 oss << " UNIQUE";
73 }
74 if (has_default_now()) {
75 oss << " DEFAULT CURRENT_TIMESTAMP";
76 }
77
78 return oss.str();
79 }
80
81 // entity_metadata implementation
82 entity_metadata::entity_metadata(const std::string& table_name)
83 : table_name_(table_name)
84 {
85 }
86
88 {
89 fields_.push_back(field);
90 }
91
93 {
94 auto it = std::find_if(fields_.begin(), fields_.end(),
95 [](const field_metadata& field) {
96 return field.is_primary_key();
97 });
98 return (it != fields_.end()) ? &(*it) : nullptr;
99 }
100
101 std::vector<const field_metadata*> entity_metadata::get_indexes() const
102 {
103 std::vector<const field_metadata*> indexes;
104 for (const auto& field : fields_) {
105 if (field.has_index()) {
106 indexes.push_back(&field);
107 }
108 }
109 return indexes;
110 }
111
112 std::vector<const field_metadata*> entity_metadata::get_foreign_keys() const
113 {
114 std::vector<const field_metadata*> foreign_keys;
115 for (const auto& field : fields_) {
116 if (field.is_foreign_key()) {
117 foreign_keys.push_back(&field);
118 }
119 }
120 return foreign_keys;
121 }
122
124 {
125 std::ostringstream oss;
126 oss << "CREATE TABLE IF NOT EXISTS " << table_name_ << " (\n";
127
128 bool first = true;
129 for (const auto& field : fields_) {
130 if (!first) oss << ",\n";
131 oss << " " << field.to_sql_definition();
132 first = false;
133 }
134
135 // Add foreign key constraints
136 auto foreign_keys = get_foreign_keys();
137 for (const auto* fk : foreign_keys) {
138 oss << ",\n FOREIGN KEY (" << fk->name() << ") REFERENCES "
139 << fk->foreign_table() << "(" << fk->foreign_field() << ")";
140 }
141
142 oss << "\n)";
143 return oss.str();
144 }
145
147 {
148 std::ostringstream oss;
149 auto indexes = get_indexes();
150
151 for (const auto* index : indexes) {
152 if (!index->index_name().empty()) {
153 oss << "CREATE INDEX IF NOT EXISTS " << index->index_name()
154 << " ON " << table_name_ << "(" << index->name() << ");\n";
155 } else {
156 oss << "CREATE INDEX IF NOT EXISTS idx_" << table_name_
157 << "_" << index->name() << " ON " << table_name_
158 << "(" << index->name() << ");\n";
159 }
160 }
161
162 return oss.str();
163 }
164
165 // entity_manager implementation
166 bool entity_manager::create_tables(std::shared_ptr<core::database_backend> db)
167 {
168 if (!db) {
169 ORM_LOG_ERROR("create_tables", "Database connection is null");
170 return false;
171 }
172
173 try {
174 for (const auto& [name, metadata] : metadata_cache_) {
175 // Create table
176 std::string create_sql = metadata->create_table_sql();
177 auto result = db->execute_query(create_sql);
178 if (result.is_err()) {
179 ORM_LOG_ERROR("create_tables", "Failed to create table: " + name);
180 return false;
181 }
182
183 // Create indexes
184 std::string index_sql = metadata->create_indexes_sql();
185 if (!index_sql.empty()) {
186 auto index_result = db->execute_query(index_sql);
187 if (index_result.is_err()) {
188 ORM_LOG_ERROR("create_tables", "Failed to create indexes for table: " + name);
189 return false;
190 }
191 }
192 }
193 return true;
194 } catch (const std::exception& e) {
195 ORM_LOG_ERROR("create_tables", std::string("Exception during table creation: ") + e.what());
196 return false;
197 }
198 }
199
200 bool entity_manager::drop_tables(std::shared_ptr<core::database_backend> db)
201 {
202 if (!db) {
203 ORM_LOG_ERROR("drop_tables", "Database connection is null");
204 return false;
205 }
206
207 try {
208 for (const auto& [name, metadata] : metadata_cache_) {
209 std::string drop_sql = "DROP TABLE IF EXISTS " + metadata->table_name();
210 auto result = db->execute_query(drop_sql);
211 if (result.is_err()) {
212 ORM_LOG_ERROR("drop_tables", "Failed to drop table: " + name);
213 return false;
214 }
215 }
216 return true;
217 } catch (const std::exception& e) {
218 ORM_LOG_ERROR("drop_tables", std::string("Exception during table dropping: ") + e.what());
219 return false;
220 }
221 }
222
223 bool entity_manager::sync_schema(std::shared_ptr<core::database_backend> db)
224 {
225 if (!db) {
226 ORM_LOG_ERROR("sync_schema", "Database connection is null");
227 return false;
228 }
229
230 try {
231 // For now, just recreate all tables
232 // In a real implementation, this would do schema diffing
233 if (!drop_tables(db)) {
234 ORM_LOG_ERROR("sync_schema", "Failed to drop existing tables");
235 return false;
236 }
237
238 if (!create_tables(db)) {
239 ORM_LOG_ERROR("sync_schema", "Failed to create new tables");
240 return false;
241 }
242
243 return true;
244 } catch (const std::exception& e) {
245 ORM_LOG_ERROR("sync_schema", std::string("Exception during schema sync: ") + e.what());
246 return false;
247 }
248 }
249
250 // Note: Template implementations moved to header file to avoid
251 // template instantiation issues. Only non-template methods implemented here.
252
253} // namespace database::orm
bool drop_tables(std::shared_ptr< core::database_backend > db)
Definition entity.cpp:200
bool sync_schema(std::shared_ptr< core::database_backend > db)
Definition entity.cpp:223
std::unordered_map< std::string, std::unique_ptr< entity_metadata > > metadata_cache_
Definition entity.h:270
bool create_tables(std::shared_ptr< core::database_backend > db)
Definition entity.cpp:166
std::string create_table_sql() const
Definition entity.cpp:123
void add_field(const field_metadata &field)
Definition entity.cpp:87
std::vector< const field_metadata * > get_foreign_keys() const
Definition entity.cpp:112
std::vector< const field_metadata * > get_indexes() const
Definition entity.cpp:101
std::string create_indexes_sql() const
Definition entity.cpp:146
entity_metadata(const std::string &table_name)
Definition entity.cpp:82
const field_metadata * get_primary_key() const
Definition entity.cpp:92
std::vector< field_metadata > fields_
Definition entity.h:135
Metadata for entity fields including constraints and relationships.
Definition entity.h:78
std::string to_sql_definition() const
Definition entity.cpp:39
field_metadata(const std::string &name, const std::string &type_name, field_constraint constraints=field_constraint::none, const std::string &index_name="", const std::string &foreign_table="", const std::string &foreign_field="")
Definition entity.cpp:24
bool is_primary_key() const
Definition entity.h:94
bool is_auto_increment() const
Definition entity.h:97
bool has_default_now() const
Definition entity.h:100
#define ORM_LOG_ERROR(context, message)
Definition entity.cpp:14