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