Joedb 10.2.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Writable_Database_h.cpp
Go to the documentation of this file.
3#include "joedb/ui/type_io.h"
4
5namespace joedb::generator
6{
7 ////////////////////////////////////////////////////////////////////////////
9 ////////////////////////////////////////////////////////////////////////////
10 (
11 const Compiler_Options &options
12 ):
13 Generator(".", "Writable_Database.h", options)
14 {
15 }
16
17 ////////////////////////////////////////////////////////////////////////////
19 ////////////////////////////////////////////////////////////////////////////
20 {
21 const Database &db = options.get_db();
22 auto tables = db.get_tables();
23
25
27 out << "\n#include \"joedb/Span.h\"\n";
28
29 out << R"RRR(
30#include "Database_Writable.h"
31
32)RRR";
33
35
36 //
37 // Writable_Database
38 //
39 out << R"RRR(
40 namespace detail
41 {
42 class Client_Data;
43 }
44
45 class Client;
46 class Multiplexer;
47 class Memory_Database;
48
49 /// A @ref Database that contains a @ref joedb::Writable_Journal and keeps them in sync
50 class Writable_Database: public Database_Writable
51 {
52 friend class detail::Client_Data;
53 friend class Client;
54 friend class Multiplexer;
55 friend class Memory_Database;
56
57 private:
58 joedb::Writable_Journal journal;
59 bool ready_to_write;
60
61 void play_journal();
62 void auto_upgrade();
63 void check_single_row();
64 void initialize();
65)RRR";
66
67
68 if (!options.get_custom_names().empty())
69 {
70 out << R"RRR(
71 void custom(const std::string &name) override
72 {
73 Database_Writable::custom(name);
74
75 if (upgrading_schema)
76 {
77)RRR";
78 for (const auto &name: options.get_custom_names())
79 {
80 out << " if (name == \"" << name << "\")\n";
81 out << " " << name << "(*this);\n";
82 }
83 out << " }\n";
84 out << " }\n";
85
86 out << '\n';
87 out << " public:\n";
88 for (const auto &name: options.get_custom_names())
89 out << " static void " << name << "(Writable_Database &db);\n";
90 out << "\n private:";
91 }
92
93 if (db_has_values())
94 {
95 out << R"RRR(
96 void add_field
97 (
98 Table_Id table_id,
99 const std::string &name,
100 joedb::Type type
101 ) override;
102)RRR";
103 }
104
106 {
107 out <<"\n void create_table(const std::string &name) override;\n";
108 }
109
110 out << R"RRR(
111 Writable_Database
112 (
113 joedb::Abstract_File &file,
114 joedb::Recovery recovery,
115 bool perform_initialization
116 );
117
118 public:
119 Writable_Database(joedb::Abstract_File &file);
120
121 Writable_Database
122 (
123 joedb::Abstract_File &file,
124 joedb::Recovery recovery
125 );
126
127 const joedb::Readonly_Journal &get_journal() const {return journal;}
128
129 std::string read_blob(joedb::Blob blob) const
130 {
131 return journal.get_file().read_blob(blob);
132 }
133
134 joedb::Blob write_blob(const std::string &data) override
135 {
136 return journal.write_blob(data);
137 }
138
139 int64_t ahead_of_checkpoint() const
140 {
141 return journal.ahead_of_checkpoint();
142 }
143
144 void soft_checkpoint() override
145 {
146 journal.soft_checkpoint();
147 }
148
149 void hard_checkpoint() override
150 {
151 journal.hard_checkpoint();
152 }
153
154 void write_comment(const std::string &comment);
155 void write_timestamp();
156 void write_timestamp(int64_t timestamp);
157 void write_valid_data();
158 void flush() override {journal.flush();}
159)RRR";
160
161 for (const auto &[tid, tname]: tables)
162 {
163 out << '\n';
164 const bool single_row = options.get_table_options(tid).single_row;
165
166 //
167 // Erase all elements of the table
168 //
169 if (!single_row)
170 {
171 out << " void clear_" << tname << "_table();\n";
172 out << '\n';
173 }
174
175 if (single_row)
176 out << " private:\n";
177
178 //
179 // Uninitialized new
180 //
181 out << " id_of_" << tname << " new_" << tname << "()\n";
182 out << " {\n";
183
184 out << " id_of_" << tname << " result(Record_Id(storage_of_" << tname << ".freedom_keeper.get_free_record()));\n";
185 out << " storage_of_" << tname << ".resize(storage_of_" << tname << ".freedom_keeper.size());\n";
186 out << " internal_insert_" << tname << "(result.get_record_id());\n\n";
187 out << " journal.insert_into(Table_Id(" << tid << "), result.get_record_id());\n";
188 out << " return result;\n";
189 out << " }\n";
190 out << '\n';
191
192 //
193 // new uninitialized vector
194 //
195 if (!single_row)
196 {
197 out << " id_of_" << tname << " new_vector_of_" << tname << "(size_t size)\n";
198 out << " {\n";
199 out << " id_of_" << tname << " result(Record_Id(storage_of_" << tname;
200 out << ".size()));\n";
201 out << " storage_of_" << tname << ".resize(storage_of_";
202 out << tname << ".size() + size);\n";
203 out << " internal_vector_insert_" << tname << "(result.get_record_id(), size);\n";
204 out << " journal.insert_vector(Table_Id(" << tid;
205 out << "), result.get_record_id(), size);\n";
206 out << " return result;\n";
207 out << " }\n";
208 out << '\n';
209 }
210
211 //
212 // new with all fields
213 //
214 if (!db.get_fields(tid).empty())
215 {
216 out << " id_of_" << tname << " new_" << tname << '\n';
217 out << " (\n ";
218 {
219 bool first = true;
220
221 for (const auto &[fid, fname]: db.get_fields(tid))
222 {
223 if (first)
224 first = false;
225 else
226 out << ",\n ";
227
228 const Type &type = db.get_field_type(tid, fid);
229 write_type(type, false, true);
230 out << " field_value_of_" << fname;
231 }
232
233 out << '\n';
234 }
235 out << " )\n";
236 out << " {\n";
237 out << " auto result = new_" << tname << "();\n";
238
239 for (const auto &[fid, fname]: db.get_fields(tid))
240 out << " set_" << fname << "(result, field_value_of_" << fname << ");\n";
241
242 out << " return result;\n";
243 out << " }\n\n";
244 }
245
246 if (single_row)
247 out << " public:\n";
248
249 //
250 // Delete
251 //
252 if (!single_row)
253 {
254 out << " void delete_" << tname << "(id_of_" << tname << " record)\n";
255 out << " {\n";
256 out << " internal_delete_" << tname << "(record.get_record_id());\n";
257 out << " journal.delete_from(Table_Id(" << tid << "), record.get_record_id());\n";
258 out << " }\n\n";
259
260 out << " void delete_vector_of_" << tname << "(id_of_" << tname << " v, size_t size)\n";
261 out << " {\n";
262 out << " for (size_t i = size; i > 0;)\n";
263 out << " internal_delete_" << tname << "(v[--i].get_record_id());\n";
264 out << " journal.delete_vector(Table_Id(" << tid << "), v.get_record_id(), size);\n";
265 out << " }\n\n";
266 }
267
268 //
269 // Loop over fields
270 //
271 for (const auto &[fid, fname]: db.get_fields(tid))
272 {
273 const Type &type = db.get_field_type(tid, fid);
274
275 //
276 // Setter
277 //
278 out << " void set_" << fname;
279 out << "(id_of_" << tname << " record, ";
280 write_type(type, false, true);
281 out << " field_value_of_" << fname << ")\n";
282 out << " {\n";
283 out << " internal_update_" << tname << "__" << fname;
284
285 out << "(record.get_record_id(), ";
286 out << "field_value_of_" << fname << ");\n";
287 out << " journal.update_";
288 out << get_type_string(type);
289 out << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), ";
290 out << "field_value_of_" << fname;
291 if (type.get_type_id() == Type::Type_Id::reference)
292 out << ".get_record_id()";
293 out << ");\n";
294 out << " }\n\n";
295
296 if (single_row && options.is_unique_field_name(fname))
297 {
298 out << " void set_" << fname;
299 out << "(";
300 write_type(type, false, true);
301 out << " field_value_of_" << fname << ")\n";
302 out << " {\n";
303 out << " set_" << fname << "(the_" << tname;
304 out << "(), field_value_of_" << fname << ");\n";
305 out << " }\n\n";
306 }
307
308 //
309 // Vector update
310 //
311 if (!single_row)
312 {
313 out << " template<typename F> void update_vector_of_" << fname;
314 out << "(id_of_" << tname << " record, size_t size, F f)\n";
315 out << " {\n";
316 out << " joedb::Span<";
317 write_type(type, false, false);
318 out << "> span(&storage_of_" << tname;
319 out << ".field_value_of_" << fname << ".data()[record.get_id()], size);\n";
320 out << " f(span);\n";
321 out << " internal_update_vector_" << tname << "__" << fname << "(record.get_record_id(), size, span.begin());\n";
322 out << " journal.update_vector_" << get_type_string(type) << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), size, ";
323
324 if (type.get_type_id() == Type::Type_Id::reference)
325 out << "reinterpret_cast<Record_Id *>";
326
327 out << "(span.begin()));\n";
328 out << " }\n\n";
329 }
330 }
331 }
332
333 out << "\n };";
334
337 }
338}
const std::vector< std::string > & get_custom_names() const
const std::vector< std::string > & get_name_space() const
bool is_unique_field_name(const std::string &field_name) const
const Table_Options & get_table_options(Table_Id table_id) const
const Database & get_db() const
const std::map< Table_Id, std::string > & get_tables() const override
const Type & get_field_type(Table_Id table_id, Field_Id field_id) const override
const std::map< Field_Id, std::string > & get_fields(Table_Id table_id) const override
Type_Id get_type_id() const
Definition Type.h:41
static const char * get_type_string(Type type)
void write_type(Type type, bool return_type, bool setter_type)
Definition Generator.cpp:41
const Compiler_Options & options
Definition Generator.h:13
Writable_Database_h(const Compiler_Options &options)
void namespace_open(std::ostream &out, const std::vector< std::string > &n)
void namespace_close(std::ostream &out, const std::vector< std::string > &n)
void namespace_include_guard_open(std::ostream &out, const char *name, const std::vector< std::string > &n)
void namespace_include_guard_close(std::ostream &out)
One code generator for each of the file generated by joedbc.
Definition Client_h.cpp:5