Joedb 10.0.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Database_h.cpp
Go to the documentation of this file.
3#include "joedb/get_version.h"
4
5namespace joedb::generator
6{
7 ////////////////////////////////////////////////////////////////////////////
9 ////////////////////////////////////////////////////////////////////////////
10 (
11 const Compiler_Options &options
12 ):
13 Generator(".", "Database.h", options)
14 {
15 }
16
17 ////////////////////////////////////////////////////////////////////////////
19 ////////////////////////////////////////////////////////////////////////////
20 {
21 const Database_Schema &db = options.get_db();
22 auto tables = db.get_tables();
23
25
26 out << R"RRR(
27#include "joedb/Freedom_Keeper.h"
28#include "joedb/error/Exception.h"
29#include "joedb/error/assert.h"
30#include "joedb/get_version.h"
31#include "ids.h"
32
33#include <string>
34#include <cstring>
35#include <vector>
36#include <algorithm>
37#include <string_view>
38
39)RRR";
40
41 if (options.has_blob())
42 out << "#include \"joedb/Blob.h\"\n";
43
45 {
46 out << "#include \"joedb/ui/type_io.h\"\n";
47 out << "#include <sstream>\n";
48 }
49
50 if (options.has_index())
51 out << "#include <map>\n";
52
53 out << "\nstatic_assert(std::string_view(joedb::get_version()) == \"";
54 out << joedb::get_version() << "\");\n\n";
55
57
58 out << "\n /// @namespace " << namespace_string(options.get_name_space());
59 out << R"RRR(
60 ///
61 /// Automatically generated by joedbc
62)RRR";
63
64 out << R"RRR(
65 using joedb::Record_Id;
66 using joedb::Table_Id;
67 using joedb::Field_Id;
68
69)RRR";
70
71 for (const auto &[tid, tname]: tables)
72 out << " class container_of_" << tname << ";\n";
73
74 out << "\n namespace detail\n {";
75 for (const auto &[tid, tname]: tables)
76 {
77 out << "\n struct data_of_" << tname;
78
79 out <<"\n {\n";
80 if (db.get_freedom(tid).get_used_count() > Record_Id{0})
81 out <<" Field_Id current_field_id = Field_Id(0);\n";
82
83 std::vector<std::string> fields;
84
85 for (const auto &[fid, fname]: db.get_fields(tid))
86 {
87 fields.emplace_back("field_value_of_" + fname);
88
89 const joedb::Type &type = db.get_field_type(tid, fid);
90
91 out << " std::vector<";
92 write_type(type, false, false);
93 out << "> " << fields.back() << ";\n";
94 }
95
96 for (const auto &index: options.get_indices())
97 if (index.table_id == tid)
98 {
99 out << " std::vector<";
100 write_index_type(index);
101 out << "::iterator> ";
102 fields.emplace_back("iterator_over_" + index.name);
103 out << fields.back() << ";\n";
104 }
105
106 out << R"RRR(
107 joedb::Freedom_Keeper freedom_keeper;
108
109 size_t size() const {return freedom_keeper.size();}
110
111 void resize(size_t new_size)
112 {
113)RRR";
114
115 fields.emplace_back("freedom_keeper");
116 for (const std::string &field: fields)
117 out << " " << field << ".resize(new_size);\n";
118
119 out << " }\n };\n";
120 }
121 out << " }\n\n";
122
123 for (const auto &index: options.get_indices())
124 if (!index.unique)
125 out << " class range_of_" << index.name << ";\n";
126 out << '\n';
127
128 out << " /// Store all the tables of the database\n";
129 out << " class Database\n {\n";
130 out << " friend class Readable;\n";
131
132 for (const auto &[tid, tname]: tables)
133 {
134 out << " friend class id_of_" << tname << ";\n";
135 out << " friend class container_of_" << tname << ";\n";
136 }
137
138 for (const auto &index: options.get_indices())
139 if (!index.unique)
140 out << " friend class range_of_" << index.name << ";\n";
141
142 out << R"RRR(
143 public:
144 template<typename E = joedb::Exception>
145 static void throw_exception(const std::string &message)
146 {
147 throw E(")RRR" <<
149 << R"RRR(: " + message);
150 }
151
152)RRR";
153
154 //
155 // Validity checks
156 //
157 for (const auto &[tid, tname]: tables)
158 {
159 out << " bool is_valid(id_of_" << tname << " id) const {return is_valid_record_id_for_" << tname << "(id.get_record_id());}\n";
160 }
161
162 out << "\n protected:\n";
163
164 for (const auto &[tid, tname]: tables)
165 {
166 out << " detail::data_of_" << tname << " storage_of_" << tname << ";\n";
167
168 out << " bool is_valid_record_id_for_" << tname;
169 out << "(Record_Id record_id) const {return storage_of_" << tname;
170 out << ".freedom_keeper.is_used(record_id);}\n";
171 }
172
173 //
174 // Indices
175 //
176 if (!options.get_indices().empty())
177 out << '\n';
178
179 for (const auto &index: options.get_indices())
180 {
181 const std::string &tname = db.get_table_name(index.table_id);
182
183 out << " ";
184 write_index_type(index);
185 out << " index_of_" << index.name << ";\n";
186
187 out << " void remove_index_of_" << index.name << "(Record_Id record_id)\n";
188 out << " {\n";
189 out << " auto &iterator = storage_of_" << tname;
190 out << ".iterator_over_" << index.name << "[to_underlying(record_id)];\n";
191 out << " if (iterator != index_of_" << index.name << ".end())\n";
192 out << " {\n";
193 out << " index_of_" << index.name << ".erase(iterator);\n";
194 out << " iterator = index_of_" << index.name << ".end();\n";
195 out << " }\n";
196 out << " }\n";
197
198 out << " void add_index_of_" << index.name << "(Record_Id record_id)\n";
199 out << " {\n";
200 out << " auto result = index_of_" << index.name;
201 out << ".insert\n (\n ";
202 write_index_type(index);
203 out << "::value_type\n (\n ";
204 write_tuple_type(index, true);
205 out << '(';
206 for (size_t i = 0; i < index.field_ids.size(); i++)
207 {
208 if (i > 0)
209 out << ", ";
210 out << "storage_of_" << tname << ".field_value_of_";
211 out << db.get_field_name(index.table_id, index.field_ids[i]);
212 out << "[to_underlying(record_id)]";
213 }
214 out << ')';
215 out << ",\n id_of_" << tname << "(record_id)\n )\n );\n";
216 if (index.unique)
217 {
218 out << " if (!result.second)\n";
219 out << " {\n";
220 out << " std::ostringstream out;\n";
221 out << " out << \"" << index.name << " unique index failure: (\";\n";
222 for (size_t i = 0; i < index.field_ids.size(); i++)
223 {
224 if (i > 0)
225 out << " out << \", \";\n";
226 const auto type = db.get_field_type(index.table_id, index.field_ids[i]);
227 out << " joedb::write_" << get_type_string(type) << "(out, ";
228 out << "storage_of_" << tname << ".field_value_of_";
229 out << db.get_field_name(index.table_id, index.field_ids[i]);
230 out << "[to_underlying(record_id)]";
231 if (type.get_type_id() == joedb::Type::Type_Id::reference)
232 out << ".get_record_id()";
233 out << ");\n";
234 }
235 out << " out << \") at id = \" << record_id << ' ';\n";
236 out << " out << \"was already at id = \" << result.first->second.get_id();\n";
237 out << " throw_exception(out.str());\n";
238 out << " }\n";
239 out << " storage_of_" << tname << ".iterator_over_" << index.name << "[to_underlying(record_id)] = result.first;\n";
240 }
241 else
242 out << " storage_of_" << tname << ".iterator_over_" << index.name << "[to_underlying(record_id)] = result;\n";
243 out << " }\n";
244 }
245
246 //
247 // Internal data-modification functions
248 //
249 out << '\n';
250 for (const auto &[tid, tname]: tables)
251 {
252 out << " void internal_delete_" << tname << "(Record_Id record_id)\n";
253 out << " {\n";
254 out << " JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname << "(record_id));\n";
255
256 for (const auto &index: options.get_indices())
257 if (index.table_id == tid)
258 out << " remove_index_of_" << index.name << "(record_id);\n";
259
260 for (const auto &[fid, fname]: db.get_fields(tid))
261 {
262 const Type &type = db.get_field_type(tid, fid);
263
264 out << " storage_of_" << tname << ".field_value_of_";
265 out << fname << "[to_underlying(record_id)]";
266
267 if (type.get_type_id() == Type::Type_Id::string)
268 {
269 out << ".clear()";
270 }
271 else if (type.get_type_id() == Type::Type_Id::reference)
272 {
273 out << " = ";
274 write_type(type, false, false);
275 out << "(joedb::Record_Id::null)";
276 }
277 else if (type.get_type_id() == Type::Type_Id::blob)
278 {
279 out << " = joedb::Blob()";
280 }
281 else
282 {
283 out << " = 0";
284 }
285
286 out << ";\n";
287 }
288
289 out << " storage_of_" << tname << ".freedom_keeper.free(record_id);\n";
290 out << " }\n";
291 }
292
293 out << '\n';
294 for (const auto &[tid, tname]: tables)
295 {
296 out << " void internal_insert_" << tname << "(Record_Id record_id)\n";
297 out << " {\n";
298
299 for (const auto &index: options.get_indices())
300 if (index.table_id == tid)
301 {
302 out << " storage_of_" << tname;
303 out << ".iterator_over_" << index.name << "[to_underlying(record_id)] = ";
304 out << "index_of_" << index.name << ".end();\n";
305 }
306
307 out << " storage_of_" << tname << ".freedom_keeper.use(record_id);\n";
308
309 out << " }\n\n";
310
311 out << " void internal_vector_insert_" << tname << "(Record_Id record_id, size_t size)\n";
312 out << " {\n";
313 out << " JOEDB_RELEASE_ASSERT(storage_of_" << tname << ".freedom_keeper.is_free_vector(record_id, size));\n";
314 out << " storage_of_" << tname << ".freedom_keeper.use_vector(record_id, size);\n";
315
316 for (const auto &index: options.get_indices())
317 if (index.table_id == tid)
318 {
319 out << " std::fill_n\n";
320 out << " (\n";
321 out << " &storage_of_" << tname << ".iterator_over_" << index.name << "[to_underlying(record_id)],\n";
322 out << " size,\n";
323 out << " index_of_" << index.name << ".end()\n";
324 out << " );\n";
325 }
326
327 out << " }\n";
328 }
329
330 out << '\n';
331 for (const auto &[tid, tname]: tables)
332 {
333 for (const auto &[fid, fname]: db.get_fields(tid))
334 {
335 const Type &type = db.get_field_type(tid, fid);
336
337 out << " void internal_update_" << tname << "__" << fname;
338 out << "\n (\n Record_Id record_id,\n ";
339 write_type(type, true, false);
340 out << " field_value_of_" << fname << "\n )\n";
341 out << " {\n";
342 out << " JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname << "(record_id));\n";
343 out << " storage_of_" << tname << ".field_value_of_" << fname;
344 out << "[to_underlying(record_id)] = field_value_of_" << fname;
345 out << ";\n";
346
347 for (const auto &index: options.get_indices())
348 {
349 if (index.is_trigger(tid, fid))
350 {
351 out << " remove_index_of_" << index.name << "(record_id);\n";
352 out << " add_index_of_" << index.name << "(record_id);\n";
353 }
354 }
355
356 out << " }\n\n";
357
358 out << " void internal_update_vector_" << tname << "__" << fname << '\n';
359 out << " (\n";
360 out << " Record_Id record_id,\n";
361 out << " size_t size,\n";
362 out << " const ";
363 write_type(type, false, false);
364 out << " *value\n";
365 out << " )\n";
366 out << " {\n";
367 out << " JOEDB_RELEASE_ASSERT(storage_of_" << tname << ".freedom_keeper.is_used_vector(record_id, size));\n";
368 out << " ";
369 write_type(type, false, false);
370 out << " *target = &storage_of_" << tname;
371 out << ".field_value_of_" << fname << ".data()[to_underlying(record_id)];\n";
372 out << " if (target != value)\n";
373 out << " std::copy_n(value, size, target);\n";
374
375 for (const auto &index: options.get_indices())
376 {
377 if (index.is_trigger(tid, fid))
378 {
379 out << " for (size_t i = 0; i < size; i++)\n";
380 out << " remove_index_of_" << index.name << "(record_id + i);\n";
381 out << " for (size_t i = 0; i < size; i++)\n";
382 out << " add_index_of_" << index.name << "(record_id + i);\n";
383 }
384 }
385
386 out << " }\n\n";
387 }
388 }
389
390 //
391 // Public stuff
392 //
393 out << " public:";
394
395 for (const auto &[tid, tname]: tables)
396 {
397 out << '\n';
398 const bool single_row = options.get_table_options(tid).single_row;
399
400 //
401 // Declaration of container access
402 //
403 out << " container_of_" << tname << " get_" << tname << "_table() const;\n\n";
404
405 out << " id_of_" << tname << " next(id_of_" << tname << " id) const\n";
406 out << " {\n";
407 out << " return id_of_" << tname << "\n (\n Record_Id(storage_of_" << tname << ".freedom_keeper.get_next(id.get_record_id()))\n );\n";
408 out << " }\n\n";
409
410 out << " id_of_" << tname << " previous(id_of_" << tname << " id) const\n";
411 out << " {\n";
412 out << " return id_of_" << tname << "\n (\n Record_Id(storage_of_" << tname << ".freedom_keeper.get_previous(id.get_record_id()))\n );\n";
413 out << " }\n\n";
414
415 out << " template<class Comparator>\n";
416 out << " std::vector<id_of_" << tname << "> sorted_" << tname;
417 out << "(Comparator comparator) const;\n\n";
418
419 //
420 // Easy access to null
421 //
422 out << " static id_of_" << tname << " null_" << tname << "()\n";
423 out << " {\n";
424 out << " return id_of_" << tname << "();\n";
425 out << " }\n";
426
427 //
428 // the_<table>
429 //
430 if (single_row)
431 {
432 out << " static constexpr id_of_" << tname << " the_" << tname << "()\n";
433 out << " {\n";
434 out << " return id_of_" << tname << "{0};\n";
435 out << " }\n";
436 }
437
438 //
439 // Loop over fields
440 //
441 for (const auto &[fid, fname]: db.get_fields(tid))
442 {
443 const Type &type = db.get_field_type(tid, fid);
444
445 out << '\n';
446
447 //
448 // Getter
449 //
450 out << " ";
451 write_type(type, true, false);
452 out << " get_" << fname << "(id_of_" << tname << " record";
453 if (single_row)
454 out << " = id_of_" << tname << "{0}";
455 out << ") const\n";
456 out << " {\n";
457 out << " JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname << "(record.get_record_id()));\n";
458 out << " return (";
459 write_type(type, true, false);
460 out << ")(storage_of_" << tname;
461 out << ".field_value_of_" << fname << "[record.get_id()]);\n";
462 out << " }\n";
463 }
464 }
465
466 //
467 // get_index_of_X
468 //
469 for (const auto &index: options.get_indices())
470 {
471 out << '\n';
472 out << " const ";
473 write_index_type(index);
474 out << " &get_index_of_" << index.name << "()\n";
475 out << " {\n";
476 out << " return index_of_" << index.name << ";\n";
477 out << " }\n";
478 }
479
480 //
481 // find_index
482 //
483 for (const auto &index: options.get_indices())
484 {
485 if (index.unique)
486 {
487 const std::string &tname = db.get_table_name(index.table_id);
488 out << '\n';
489
490 out << " id_of_" << tname << " next_" << index.name << '(';
491 out << "id_of_" << tname << " id)\n";
492 out << " {\n";
493 out << " JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname << "(id.get_record_id()));\n";
494 out << " auto iterator = storage_of_" << tname << ".iterator_over_" << index.name << "[id.get_id()];\n";
495 out << " ++iterator;\n";
496 out << " if (iterator != index_of_" << index.name << ".end())\n";
497 out << " return iterator->second;\n";
498 out << " else\n";
499 out << " return id_of_" << tname << "();\n";
500 out << " }\n";
501
502 out << " id_of_" << tname << " previous_" << index.name << '(';
503 out << "id_of_" << tname << " id)\n";
504 out << " {\n";
505 out << " JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname << "(id.get_record_id()));\n";
506 out << " auto iterator = storage_of_" << tname << ".iterator_over_" << index.name << "[id.get_id()];\n";
507 out << " if (iterator != index_of_" << index.name << ".begin())\n";
508 out << " return (--iterator)->second;\n";
509 out << " else\n";
510 out << " return id_of_" << tname << "();\n";
511 out << " }\n";
512
513 out << " id_of_" << tname << " find_" << index.name << '(';
514 for (size_t i = 0; i < index.field_ids.size(); i++)
515 {
516 if (i > 0)
517 out << ", ";
518 const Type &type = db.get_field_type(index.table_id, index.field_ids[i]);
519 write_type(type, true, false);
520 out << " field_value_of_";
521 out << db.get_field_name(index.table_id, index.field_ids[i]);
522 }
523 out << ") const\n";
524 out << " {\n";
525 out << " const auto i = index_of_" << index.name << ".find(";
526 write_tuple_type(index, true);
527 out << '(';
528 for (size_t i = 0; i < index.field_ids.size(); i++)
529 {
530 if (i > 0)
531 out << ", ";
532 out << "field_value_of_";
533 out << db.get_field_name(index.table_id, index.field_ids[i]);
534 }
535 out << "));\n";
536 out << " if (i == index_of_" << index.name << ".end())\n";
537 out << " return id_of_" << tname << "();\n";
538 out << " else\n";
539 out << " return i->second;\n";
540 out << " }\n";
541 }
542 else
543 {
544 out << " range_of_" << index.name << " find_" << index.name << '(';
545 for (size_t i = 0; i < index.field_ids.size(); i++)
546 {
547 if (i > 0)
548 out << ", ";
549 const Type &type = db.get_field_type(index.table_id, index.field_ids[i]);
550 write_type(type, true, false);
551 out << " field_value_of_";
552 out << db.get_field_name(index.table_id, index.field_ids[i]);
553 }
554 out << ") const;\n";
555 }
556 }
557
558 out << " };\n";
559
560 //
561 // Plain iteration over tables
562 //
563 for (const auto &[tid, tname]: tables)
564 {
565 out << " /// returned by @ref Database::get_" << tname << "_table\n";
566 out << " class container_of_" << tname << "\n";
567 out << " {\n";
568 out << " friend class Database;\n";
569 out << '\n';
570 out << " private:\n";
571 out << " const Database &db;\n";
572 out << " container_of_" << tname << "(const Database &db): db(db) {}\n";
573 out << '\n';
574 out << " public:\n";
575 out << " class iterator\n";
576 out << " {\n";
577 out << " friend class container_of_" << tname << ";\n";
578 out << " private:\n";
579
580
581 out << " const joedb::Freedom_Keeper *fk;\n"; // must use pointer for copy constructor
582 out << " Record_Id index;\n";
583 out << " iterator(const detail::data_of_" << tname << " &data): fk(&data.freedom_keeper), index(joedb::Freedom_Keeper_Constants::used_list) {}\n";
584 out << " public:\n";
585 out << " typedef std::forward_iterator_tag iterator_category;\n";
586 out << " typedef id_of_" << tname << " value_type;\n";
587 out << " typedef std::ptrdiff_t difference_type;\n";
588 out << " typedef value_type* pointer;\n";
589 out << " typedef value_type& reference;\n";
590 out << '\n';
591 out << " bool operator==(const iterator &i) const {return index == i.index;}\n";
592 out << " bool operator!=(const iterator &i) const {return index != i.index;}\n";
593 out << " iterator &operator++() {index = fk->get_next(index); return *this;}\n";
594 out << " iterator operator++(int) {auto copy = *this; index = fk->get_next(index); return copy;}\n";
595 out << " iterator &operator--() {index = fk->get_previous(index); return *this;}\n";
596 out << " iterator operator--(int) {auto copy = *this; index = fk->get_previous(index); return copy;}\n";
597 out << " id_of_" << tname << " operator*() const {return id_of_";
598 out << tname << "(Record_Id(index));}\n";
599 out << " };\n";
600 out << '\n';
601 out << " iterator begin() const {return ++iterator(db.storage_of_" << tname << ");}\n";
602 out << " iterator end() const {return iterator(db.storage_of_" << tname << ");}\n";
603 out << " bool is_empty() const {return db.storage_of_" << tname
604 << ".freedom_keeper.get_used_count() == Record_Id{0};}\n";
605 out << " joedb::index_t get_size() const {return to_underlying(db.storage_of_" << tname << ".freedom_keeper.get_used_count());}\n";
606 out << " static id_of_" << tname << " get_at(size_t i) {return id_of_"
607 << tname << "(Record_Id(i));}\n";
608 out << " bool is_valid_at(size_t i) {return db.storage_of_" << tname << ".freedom_keeper.is_used(Record_Id(i));}\n";
609
610 out << " id_of_" << tname << " first() const {return *begin();}\n";
611 out << " id_of_" << tname << " last() const {return *--end();}\n";
612 out << " id_of_" << tname << " get_end() const {return *end();}\n";
613
614 out << " };\n";
615 out << '\n';
616
617 out << " inline container_of_" << tname << " Database::get_" << tname << "_table() const\n";
618 out << " {\n";
619 out << " return container_of_" << tname << "(*this);\n";
620 out << " }\n";
621 out << '\n';
622
623 out << " template<class Comparator>\n";
624 out << " std::vector<id_of_" << tname << "> Database::sorted_" << tname;
625 out << "(Comparator comparator) const\n";
626 out << " {\n";
627 out << " std::vector<id_of_" << tname << "> result;\n";
628 out << " for (auto x: get_" << tname << "_table())\n";
629 out << " result.emplace_back(x);\n";
630 out << " std::sort(result.begin(), result.end(), comparator);\n";
631 out << " return result;\n";
632 out << " }\n";
633 }
634
635 //
636 // Index ranges for indexes that are not unique
637 //
638 for (const auto &index: options.get_indices())
639 {
640 if (!index.unique)
641 {
642 out << " /// returned by @ref Database::find_" << index.name << '\n';
643 out << " class range_of_" << index.name << "\n";
644 out << " {\n";
645 out << " friend class Database;\n";
646 out << " private:\n";
647 out << " std::pair<";
648 write_index_type(index);
649 out << "::const_iterator, ";
650 write_index_type(index);
651 out << "::const_iterator> range;\n";
652 out << " range_of_" << index.name << "(const Database &db";
653 for (size_t i = 0; i < index.field_ids.size(); i++)
654 {
655 out << ", ";
656 const Type &type = db.get_field_type(index.table_id, index.field_ids[i]);
657 write_type(type, true, false);
658 out << ' ' << db.get_field_name(index.table_id, index.field_ids[i]);
659 }
660 out << ")\n";
661 out << " {\n";
662 out << " range = db.index_of_" << index.name << ".equal_range(";
663 write_tuple_type(index, true);
664 out << '(';
665 for (size_t i = 0; i < index.field_ids.size(); i++)
666 {
667 if (i > 0)
668 out << ", ";
669 out << db.get_field_name(index.table_id, index.field_ids[i]);
670 }
671 out << "));\n";
672 out << " }\n";
673 out << " public:\n";
674 out << " class iterator\n";
675 out << " {\n";
676 out << " friend class range_of_" << index.name << ";\n";
677 out << " private:\n";
678 out << " ";
679 write_index_type(index);
680 out << "::const_iterator map_iterator;\n";
681 out << " iterator(";
682 write_index_type(index);
683 out << "::const_iterator map_iterator): map_iterator(map_iterator) {}\n"
684 << " public:\n"
685 << " bool operator !=(const iterator &i) const\n"
686 << " {\n"
687 << " return map_iterator != i.map_iterator;\n"
688 << " }\n"
689 << " iterator &operator++() {map_iterator++; return *this;}\n"
690 << " id_of_" << db.get_table_name(index.table_id)
691 << " operator*() const {return map_iterator->second;}\n"
692 << " };\n"
693 << " iterator begin() const {return range.first;}\n"
694 << " iterator end() const {return range.second;}\n"
695 << " bool empty() const {return range.first == range.second;}\n"
696 << " size_t size() const {return size_t(std::distance(range.first, range.second));}\n"
697 << " };\n\n";
698
699 out << " inline range_of_" << index.name << " Database::find_" << index.name << '(';
700 for (size_t i = 0; i < index.field_ids.size(); i++)
701 {
702 if (i > 0)
703 out << ", ";
704 const Type &type = db.get_field_type(index.table_id, index.field_ids[i]);
705 write_type(type, true, false);
706 out << " field_value_of_";
707 out << db.get_field_name(index.table_id, index.field_ids[i]);
708 }
709 out << ") const\n";
710 out << " {\n";
711 out << " return range_of_" << index.name << "(*this";
712 for (size_t i = 0; i < index.field_ids.size(); i++)
713 {
714 out << ", ";
715 out << "field_value_of_";
716 out << db.get_field_name(index.table_id, index.field_ids[i]);
717 }
718 out << ");\n";
719 out << " }\n";
720 }
721 }
722
724 out << "\n#endif\n";
725 }
726}
const std::vector< std::string > & get_name_space() const
const std::vector< Index > & get_indices() const
const Table_Options & get_table_options(Table_Id table_id) const
const Database & get_db() const
const Freedom_Keeper & get_freedom(Table_Id table_id) const override
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
Record_Id get_used_count() const
const std::string & get_field_name(Table_Id table_id, Field_Id field_id) const
Definition Readable.cpp:54
const std::string & get_table_name(Table_Id table_id) const
Definition Readable.cpp:38
Type_Id get_type_id() const
Definition Type.h:41
Database_h(const Compiler_Options &options)
void write_index_type(const Compiler_Options::Index &index)
static const char * get_type_string(Type type)
void write_type(Type type, bool return_type, bool setter_type)
Definition Generator.cpp:42
const Compiler_Options & options
Definition Generator.h:14
void write_tuple_type(const Compiler_Options::Index &index, bool reference)
Definition Generator.cpp:71
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(std::ostream &out, const char *name, const std::vector< std::string > &n)
std::string namespace_string(const std::vector< std::string > &n, const char *delimiter)
constexpr const char * get_version()
Definition get_version.h:7
One code generator for each of the file generated by joedbc.
Definition Client_h.cpp:5