Joedb 10.3.2
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 ////////////////////////////////////////////////////////////////////////////
18 void Writable_Database_h::write(std::ostream &out)
19 ////////////////////////////////////////////////////////////////////////////
20 {
21 const Database &db = options.get_db();
22 auto tables = db.get_tables();
23
24 namespace_include_guard_open(out, "Writable_Database", options.get_name_space());
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(std::string_view 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\n";
190
191 out << " void insert_" << tname << "(id_of_" << tname << " id)\n";
192 out << " {\n";
193 out << " if (id.get_record_id() >= Record_Id(storage_of_" << tname << ".size()))\n";
194 out << " storage_of_" << tname << ".resize(id.get_id() + 1);\n";
195 out << " internal_insert_" << tname << "(id.get_record_id());\n";
196 out << " journal.insert_into(Table_Id(" << tid << "), id.get_record_id());\n";
197 out << " }\n\n";
198
199 //
200 // new uninitialized vector
201 //
202 if (!single_row)
203 {
204 out << " id_of_" << tname << " new_vector_of_" << tname << "(size_t size)\n";
205 out << " {\n";
206 out << " id_of_" << tname << " result(Record_Id(storage_of_" << tname;
207 out << ".size()));\n";
208 out << " storage_of_" << tname << ".resize(storage_of_";
209 out << tname << ".size() + size);\n";
210 out << " internal_vector_insert_" << tname << "(result.get_record_id(), size);\n";
211 out << " journal.insert_vector(Table_Id(" << tid;
212 out << "), result.get_record_id(), size);\n";
213 out << " return result;\n";
214 out << " }\n";
215 out << '\n';
216 }
217
218 //
219 // new with all fields
220 //
221 if (!db.get_fields(tid).empty())
222 {
223 out << " id_of_" << tname << " new_" << tname << '\n';
224 out << " (\n ";
225 {
226 bool first = true;
227
228 for (const auto &[fid, fname]: db.get_fields(tid))
229 {
230 if (first)
231 first = false;
232 else
233 out << ",\n ";
234
235 const Type &type = db.get_field_type(tid, fid);
236 write_type(out, type, false, true);
237 out << " field_value_of_" << fname;
238 }
239
240 out << '\n';
241 }
242 out << " )\n";
243 out << " {\n";
244 out << " auto result = new_" << tname << "();\n";
245
246 for (const auto &[fid, fname]: db.get_fields(tid))
247 out << " set_" << fname << "(result, field_value_of_" << fname << ");\n";
248
249 out << " return result;\n";
250 out << " }\n\n";
251 }
252
253 if (single_row)
254 out << " public:\n";
255
256 //
257 // Delete
258 //
259 if (!single_row)
260 {
261 out << " void delete_" << tname << "(id_of_" << tname << " record)\n";
262 out << " {\n";
263 out << " internal_delete_" << tname << "(record.get_record_id());\n";
264 out << " journal.delete_from(Table_Id(" << tid << "), record.get_record_id());\n";
265 out << " }\n\n";
266
267 out << " void delete_vector_of_" << tname << "(id_of_" << tname << " v, size_t size)\n";
268 out << " {\n";
269 out << " for (size_t i = size; i > 0;)\n";
270 out << " internal_delete_" << tname << "(v[--i].get_record_id());\n";
271 out << " journal.delete_vector(Table_Id(" << tid << "), v.get_record_id(), size);\n";
272 out << " }\n\n";
273 }
274
275 //
276 // Loop over fields
277 //
278 for (const auto &[fid, fname]: db.get_fields(tid))
279 {
280 const Type &type = db.get_field_type(tid, fid);
281
282 //
283 // Setter
284 //
285 out << " void set_" << fname;
286 out << "(id_of_" << tname << " record, ";
287 write_type(out, type, false, true);
288 out << " field_value_of_" << fname << ")\n";
289 out << " {\n";
290 out << " internal_update_" << tname << "__" << fname;
291
292 out << "(record.get_record_id(), ";
293 out << "field_value_of_" << fname << ");\n";
294 out << " journal.update_";
295 out << get_type_string(type);
296 out << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), ";
297 out << "field_value_of_" << fname;
298 if (type.get_type_id() == Type::Type_Id::reference)
299 out << ".get_record_id()";
300 out << ");\n";
301 out << " }\n\n";
302
303 if (single_row && options.is_unique_field_name(fname))
304 {
305 out << " void set_" << fname;
306 out << "(";
307 write_type(out, type, false, true);
308 out << " field_value_of_" << fname << ")\n";
309 out << " {\n";
310 out << " set_" << fname << "(the_" << tname;
311 out << "(), field_value_of_" << fname << ");\n";
312 out << " }\n\n";
313 }
314
315 //
316 // Vector update
317 //
318 if (!single_row)
319 {
320 out << " template<typename F> void update_vector_of_" << fname;
321 out << "(id_of_" << tname << " record, size_t size, F f)\n";
322 out << " {\n";
323 out << " joedb::Span<";
324 write_type(out, type, false, false);
325 out << "> span(&storage_of_" << tname;
326 out << ".field_value_of_" << fname << ".data()[record.get_id()], size);\n";
327 out << " f(span);\n";
328 out << " internal_update_vector_" << tname << "__" << fname << "(record.get_record_id(), size, span.begin());\n";
329 out << " journal.update_vector_" << get_type_string(type) << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), size, ";
330
331 if (type.get_type_id() == Type::Type_Id::reference)
332 out << "reinterpret_cast<Record_Id *>";
333
334 out << "(span.begin()));\n";
335 out << " }\n\n";
336 }
337 }
338 }
339
340 out << "\n };";
341
344 }
345}
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)
const Compiler_Options & options
Definition Generator.h:16
void write_type(std::ostream &out, Type type, bool return_type, bool setter_type)
Definition Generator.cpp:42
Writable_Database_h(const Compiler_Options &options)
void write(std::ostream &out) override
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