30#include "joedb/Freedom_Keeper.h"
31#include "joedb/journal/Writable_Journal.h"
32#include "joedb/journal/Memory_File.h"
33#include "joedb/error/Exception.h"
34#include "joedb/error/Out_Of_Date.h"
35#include "joedb/error/assert.h"
36#include "joedb/get_version.h"
49 out <<
"#include <map>\n\n";
53 out <<
"#include \"joedb/ui/type_io.h\"\n";
54 out <<
"#include <sstream>\n\n";
57 out <<
"static_assert(std::string_view(joedb::get_version()) == \"";
69 using joedb::Record_Id;
70 using joedb::Table_Id;
71 using joedb::Field_Id;
75 extern const char * schema_string;
76 inline constexpr size_t schema_string_size = )RRR";
80 for (
const auto &[tid, tname]: tables)
81 out <<
" class container_of_" << tname <<
";\n";
83 out <<
"\n namespace detail\n {";
84 for (
const auto &[tid, tname]: tables)
86 out <<
"\n struct data_of_" << tname;
90 out <<
" Field_Id current_field_id = Field_Id(0);\n";
92 std::vector<std::string> fields;
94 for (
const auto &[fid, fname]: db.
get_fields(tid))
96 fields.emplace_back(
"field_value_of_" + fname);
100 out <<
" std::vector<";
102 out <<
"> " << fields.back() <<
";\n";
106 if (index.table_id == tid)
108 out <<
" std::vector<";
110 out <<
"::iterator> ";
111 fields.emplace_back(
"iterator_over_" + index.name);
112 out << fields.back() <<
";\n";
116 joedb::Compact_Freedom_Keeper freedom_keeper;
118 size_t size() const {return freedom_keeper.size();}
120 void resize(size_t new_size)
124 fields.emplace_back("freedom_keeper");
125 for (
const std::string &field: fields)
126 out <<
" " << field <<
".resize(new_size);\n";
134 out <<
" class range_of_" << index.name <<
";\n";
137 out <<
" /// Store all the tables of the database\n";
138 out <<
" class Database: public joedb::Writable\n {\n";
139 out <<
" friend class Readable;\n";
141 for (
const auto &[tid, tname]: tables)
143 out <<
" friend class id_of_" << tname <<
";\n";
144 out <<
" friend class container_of_" << tname <<
";\n";
149 out <<
" friend class range_of_" << index.name <<
";\n";
153 template<typename E = joedb::Exception>
154 static void throw_exception(const std::string &message)
158 << R"RRR(: " + message);
161 size_t max_record_id;
162 Table_Id current_table_id = Table_Id{0};
164 void set_max_record_id(size_t record_id)
166 max_record_id = record_id;
174 for (
const auto &[tid, tname]: tables)
176 out <<
" bool is_valid(id_of_" << tname <<
" id) const {return is_valid_record_id_for_" << tname <<
"(id.get_record_id());}\n";
179 out <<
"\n protected:\n";
181 for (
const auto &[tid, tname]: tables)
183 out <<
" detail::data_of_" << tname <<
" storage_of_" << tname <<
";\n";
185 out <<
" bool is_valid_record_id_for_" << tname;
186 out <<
"(Record_Id record_id) const {return storage_of_" << tname;
187 out <<
".freedom_keeper.is_used(size_t(record_id) + 1);}\n";
202 out <<
" index_of_" << index.name <<
";\n";
204 out <<
" void remove_index_of_" << index.name <<
"(Record_Id record_id)\n";
206 out <<
" auto &iterator = storage_of_" << tname;
207 out <<
".iterator_over_" << index.name <<
"[size_t(record_id) - 1];\n";
208 out <<
" if (iterator != index_of_" << index.name <<
".end())\n";
210 out <<
" index_of_" << index.name <<
".erase(iterator);\n";
211 out <<
" iterator = index_of_" << index.name <<
".end();\n";
215 out <<
" void add_index_of_" << index.name <<
"(Record_Id record_id)\n";
217 out <<
" auto result = index_of_" << index.name;
218 out <<
".insert\n (\n ";
220 out <<
"::value_type\n (\n ";
223 for (
size_t i = 0; i < index.field_ids.size(); i++)
227 out <<
"storage_of_" << tname <<
".field_value_of_";
229 out <<
"[size_t(record_id) - 1]";
232 out <<
",\n id_of_" << tname <<
"(record_id)\n )\n );\n";
235 out <<
" if (!result.second)\n";
237 out <<
" std::ostringstream out;\n";
238 out <<
" out << \"" << index.name <<
" unique index failure: (\";\n";
239 for (
size_t i = 0; i < index.field_ids.size(); i++)
242 out <<
" out << \", \";\n";
243 const auto type = db.
get_field_type(index.table_id, index.field_ids[i]);
245 out <<
"storage_of_" << tname <<
".field_value_of_";
247 out <<
"[size_t(record_id) - 1]";
248 if (type.get_type_id() == joedb::Type::Type_Id::reference)
249 out <<
".get_record_id()";
252 out <<
" out << \") at id = \" << record_id << ' ';\n";
253 out <<
" out << \"was already at id = \" << result.first->second.get_id();\n";
254 out <<
" throw_exception(out.str());\n";
256 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[size_t(record_id) - 1] = result.first;\n";
259 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[size_t(record_id) - 1] = result;\n";
267 for (
const auto &[tid, tname]: tables)
269 out <<
" void internal_delete_" << tname <<
"(Record_Id record_id)\n";
271 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(record_id));\n";
274 if (index.table_id == tid)
275 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
277 for (
const auto &[fid, fname]: db.
get_fields(tid))
281 out <<
" storage_of_" << tname <<
".field_value_of_";
282 out << fname <<
"[size_t(record_id) - 1]";
288 else if (type.
get_type_id() == Type::Type_Id::reference)
292 out <<
"(Record_Id(0))";
294 else if (type.
get_type_id() == Type::Type_Id::blob)
296 out <<
" = joedb::Blob();";
306 out <<
" storage_of_" << tname <<
".freedom_keeper.free(size_t(record_id) + 1);\n";
311 for (
const auto &[tid, tname]: tables)
313 out <<
" void internal_insert_" << tname <<
"(Record_Id record_id)\n";
317 if (index.table_id == tid)
319 out <<
" storage_of_" << tname;
320 out <<
".iterator_over_" << index.name <<
"[size_t(record_id) - 1] = ";
321 out <<
"index_of_" << index.name <<
".end();\n";
324 out <<
" storage_of_" << tname <<
".freedom_keeper.use(size_t(record_id) + 1);\n";
328 out <<
" void internal_vector_insert_" << tname <<
"(Record_Id record_id, size_t size)\n";
330 out <<
" storage_of_" << tname <<
".freedom_keeper.use_vector(size_t(record_id) + 1, size);\n";
333 if (index.table_id == tid)
335 out <<
" std::fill_n\n";
337 out <<
" &storage_of_" << tname <<
".iterator_over_" << index.name <<
"[size_t(record_id) - 1],\n";
339 out <<
" index_of_" << index.name <<
".end()\n";
347 for (
const auto &[tid, tname]: tables)
349 for (
const auto &[fid, fname]: db.
get_fields(tid))
353 out <<
" void internal_update_" << tname <<
"__" << fname;
354 out <<
"\n (\n Record_Id record_id,\n ";
356 out <<
" field_value_of_" << fname <<
"\n )\n";
358 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(record_id));\n";
359 out <<
" storage_of_" << tname <<
".field_value_of_" << fname;
360 out <<
"[size_t(record_id) - 1] = field_value_of_" << fname;
365 if (index.is_trigger(tid, fid))
367 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
368 out <<
" add_index_of_" << index.name <<
"(record_id);\n";
374 out <<
" void internal_update_vector_" << tname <<
"__" << fname <<
'\n';
376 out <<
" Record_Id record_id,\n";
377 out <<
" size_t size,\n";
383 out <<
" for (size_t i = 0; i < size; i++)\n";
384 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(record_id + i));\n";
387 out <<
" *target = &storage_of_" << tname;
388 out <<
".field_value_of_" << fname <<
"[size_t(record_id) - 1];\n";
389 out <<
" if (target != value)\n";
390 out <<
" std::copy_n(value, size, target);\n";
394 if (index.is_trigger(tid, fid))
396 out <<
" for (size_t i = 0; i < size; i++)\n";
397 out <<
" remove_index_of_" << index.name <<
"(record_id + i);\n";
398 out <<
" for (size_t i = 0; i < size; i++)\n";
399 out <<
" add_index_of_" << index.name <<
"(record_id + i);\n";
411 out <<
" void delete_from(Table_Id table_id, Record_Id record_id) final\n";
415 for (
const auto &[tid, tname]: tables)
423 out <<
"if (table_id == Table_Id(" << tid <<
"))\n";
424 out <<
" internal_delete_" << tname <<
"(record_id);\n";
433 out <<
" void insert_into(Table_Id table_id, Record_Id record_id) final\n";
435 out <<
" if (size_t(record_id) <= 0 || (max_record_id && size_t(record_id) > max_record_id))\n";
436 out <<
" throw_exception(\"insert_into: too big\");\n";
439 for (
const auto &[tid, tname]: tables)
447 out <<
"if (table_id == Table_Id(" << tid <<
"))\n";
449 out <<
" if (is_valid_record_id_for_" << tname <<
"(record_id))\n";
450 out <<
" throw_exception(\"Duplicate insert into table " << tname <<
"\");\n";
451 out <<
" if (storage_of_" << tname <<
".size() < size_t(record_id))\n";
452 out <<
" storage_of_" << tname <<
".resize(size_t(record_id));\n";
453 out <<
" internal_insert_" << tname <<
"(record_id);\n";
473 size_t(record_id) <= 0 ||
474 (max_record_id && (size_t(record_id) > max_record_id || size > max_record_id))
477 throw_exception("insert_vector: null record_id, or too big");
483 for (
const auto &[tid, tname]: tables)
491 out <<
"if (table_id == Table_Id(" << tid <<
"))\n";
493 out <<
" if (storage_of_" << tname <<
".size() < size_t(record_id) + size - 1)\n";
494 out <<
" storage_of_" << tname <<
".resize(size_t(record_id) + size - 1);\n";
495 out <<
" internal_vector_insert_" << tname <<
"(record_id, size);\n";
504 std::set<Type::Type_Id> db_types;
506 for (
const auto &[tid, tname]: tables)
507 for (
const auto &[fid, fname]: db.
get_fields(tid))
514 for (
int type_index = 1; type_index < int(
Type::type_ids); type_index++)
517 if (db_types.find(type_id) == db_types.end())
523 out <<
" Table_Id table_id,\n";
524 out <<
" Record_Id record_id,\n";
525 out <<
" Field_Id field_id,\n";
531 for (
const auto &[tid, tname]: tables)
533 bool has_typed_field =
false;
535 for (
const auto &[fid, fname]: db.
get_fields(tid))
540 has_typed_field =
true;
547 out <<
" if (table_id == Table_Id(" << tid <<
"))\n";
550 for (
const auto &[fid, fname]: db.
get_fields(tid))
555 out <<
" if (field_id == Field_Id(" << fid <<
"))\n";
557 out <<
" internal_update_" << tname;
558 out <<
"__" << fname <<
"(record_id, ";
559 if (type.
get_type_id() != Type::Type_Id::reference)
585 for (
int type_index = 1; type_index < int(
Type::type_ids); type_index++)
594 out <<
" Table_Id table_id,\n";
595 out <<
" Record_Id record_id,\n";
596 out <<
" Field_Id field_id,\n";
597 out <<
" size_t size,\n";
603 for (
const auto &[tid, tname]: tables)
605 bool has_typed_field =
false;
607 for (
const auto &[fid, fname]: db.
get_fields(tid))
612 has_typed_field =
true;
619 out <<
" if (table_id == Table_Id(" << tid <<
"))\n";
622 for (
const auto &[fid, fname]: db.
get_fields(tid))
627 out <<
" if (field_id == Field_Id(" << fid <<
"))\n";
629 out <<
" internal_update_vector_" << tname;
630 out <<
"__" << fname <<
"(record_id, size, ";
632 if (type_id != joedb::Type::Type_Id::reference)
636 out <<
"reinterpret_cast<const ";
660 for (
int type_index = 1; type_index < int(
Type::type_ids); type_index++)
670 out <<
" Table_Id table_id,\n";
671 out <<
" Record_Id record_id,\n";
672 out <<
" Field_Id field_id,\n";
673 out <<
" size_t &capacity\n";
678 for (
const auto &[tid, tname]: tables)
680 bool has_typed_field =
false;
682 for (
const auto &[fid, fname]: db.
get_fields(tid))
687 has_typed_field =
true;
694 out <<
" if (table_id == Table_Id(" << tid <<
"))\n";
696 out <<
" capacity = size_t(storage_of_" << tname <<
".freedom_keeper.size());\n";
698 for (
const auto &[fid, fname]: db.
get_fields(tid))
703 out <<
" if (field_id == Field_Id(" << fid <<
"))\n"
707 if (type_id == Type::Type_Id::reference)
708 out <<
"reinterpret_cast<Record_Id *>";
710 out <<
"(storage_of_" << tname;
711 out <<
".field_value_of_" << fname <<
".data() + size_t(record_id) - 1);\n"
716 out <<
" return nullptr;\n";
721 out <<
" return nullptr;\n";
730 void comment(const std::string &comment) override {}
731 void timestamp(int64_t timestamp) override {}
732 void valid_data() final {}
739 bool upgrading_schema = false;
740 joedb::Memory_File schema_file;
741 joedb::Writable_Journal schema_journal;
743 bool requires_schema_upgrade() const
745 return schema_file.get_data().size() < detail::schema_string_size;
750 constexpr size_t pos = size_t(joedb::Writable_Journal::header_size);
751 const size_t schema_file_size = schema_file.get_data().size();
755 schema_file_size < pos ||
756 schema_file_size > detail::schema_string_size ||
759 schema_file.get_data().data() + pos,
760 detail::schema_string + pos,
761 schema_file_size - pos
765 throw_exception("Trying to open a file with incompatible schema");
769 void create_table(const std::string &name) override
772 schema_journal.create_table(name);
773 schema_journal.default_checkpoint();
776 void drop_table(Table_Id table_id) final
778 schema_journal.drop_table(table_id);
779 schema_journal.default_checkpoint();
785 const std::string &name
788 schema_journal.rename_table(table_id, name);
789 schema_journal.default_checkpoint();
795 const std::string &name,
799 schema_journal.add_field(table_id, name, type);
800 schema_journal.default_checkpoint();
803 void drop_field(Table_Id table_id, Field_Id field_id) final
805 schema_journal.drop_field(table_id, field_id);
806 schema_journal.default_checkpoint();
813 const std::string &name
816 schema_journal.rename_field(table_id, field_id, name);
817 schema_journal.default_checkpoint();
820 void custom(const std::string &name) override
822 schema_journal.custom(name);
823 schema_journal.default_checkpoint();
834 schema_journal(schema_file)
837 int64_t get_schema_checkpoint() const
839 return schema_journal.get_checkpoint_position();
842 void initialize_with_readonly_journal(joedb::Readonly_Journal &journal)
844 max_record_id = size_t(journal.get_checkpoint_position());
845 journal.replay_log(*this);
850 if (requires_schema_upgrade())
851 throw_exception<joedb::Out_Of_Date>("Schema is out of date. Can't upgrade a read-only database.");
855 for (
const auto &[tid, tname]: tables)
863 out <<
" container_of_" << tname <<
" get_" << tname <<
"_table() const;\n\n";
865 out <<
" id_of_" << tname <<
" next(id_of_" << tname <<
" id) const\n";
867 out <<
" return id_of_" << tname <<
"\n (\n Record_Id(storage_of_" << tname <<
".freedom_keeper.get_next(id.get_id() + 1) - 1)\n );\n";
870 out <<
" id_of_" << tname <<
" previous(id_of_" << tname <<
" id) const\n";
872 out <<
" return id_of_" << tname <<
"\n (\n Record_Id(storage_of_" << tname <<
".freedom_keeper.get_previous(id.get_id() + 1) - 1)\n );\n";
875 out <<
" template<class Comparator>\n";
876 out <<
" std::vector<id_of_" << tname <<
"> sorted_" << tname;
877 out <<
"(Comparator comparator) const;\n\n";
882 out <<
" static id_of_" << tname <<
" null_" << tname <<
"()\n";
884 out <<
" return id_of_" << tname <<
"();\n";
892 out <<
" static constexpr id_of_" << tname <<
" the_" << tname <<
"()\n";
894 out <<
" return id_of_" << tname <<
"{1};\n";
901 for (
const auto &[fid, fname]: db.
get_fields(tid))
912 out <<
" get_" << fname <<
"(id_of_" << tname <<
" record";
914 out <<
"= id_of_" << tname <<
"{1}";
917 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(record.get_record_id()));\n";
920 out <<
")(storage_of_" << tname;
921 out <<
".field_value_of_" << fname <<
"[record.get_id() - 1]);\n";
934 out <<
" &get_index_of_" << index.name <<
"()\n";
936 out <<
" return index_of_" << index.name <<
";\n";
949 out <<
" id_of_" << tname <<
" next_" << index.name <<
'(';
950 out <<
"id_of_" << tname <<
" id)\n";
952 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(id.get_record_id()));\n";
953 out <<
" auto iterator = storage_of_" << tname <<
".iterator_over_" << index.name <<
"[id.get_id() - 1];\n";
954 out <<
" ++iterator;\n";
955 out <<
" if (iterator != index_of_" << index.name <<
".end())\n";
956 out <<
" return iterator->second;\n";
958 out <<
" return id_of_" << tname <<
"();\n";
961 out <<
" id_of_" << tname <<
" previous_" << index.name <<
'(';
962 out <<
"id_of_" << tname <<
" id)\n";
964 out <<
" JOEDB_ASSERT(is_valid_record_id_for_" << tname <<
"(id.get_record_id()));\n";
965 out <<
" auto iterator = storage_of_" << tname <<
".iterator_over_" << index.name <<
"[id.get_id() - 1];\n";
966 out <<
" if (iterator != index_of_" << index.name <<
".begin())\n";
967 out <<
" return (--iterator)->second;\n";
969 out <<
" return id_of_" << tname <<
"();\n";
972 out <<
" id_of_" << tname <<
" find_" << index.name <<
'(';
973 for (
size_t i = 0; i < index.field_ids.size(); i++)
979 out <<
" field_value_of_";
984 out <<
" const auto i = index_of_" << index.name <<
".find(";
987 for (
size_t i = 0; i < index.field_ids.size(); i++)
991 out <<
"field_value_of_";
995 out <<
" if (i == index_of_" << index.name <<
".end())\n";
996 out <<
" return id_of_" << tname <<
"();\n";
998 out <<
" return i->second;\n";
1003 out <<
" range_of_" << index.name <<
" find_" << index.name <<
'(';
1004 for (
size_t i = 0; i < index.field_ids.size(); i++)
1010 out <<
" field_value_of_";
1013 out <<
") const;\n";
1021 for (
const auto &[tid, tname]: tables)
1023 out <<
" /// returned by @ref Database::get_" << tname <<
"_table\n";
1024 out <<
" class container_of_" << tname <<
"\n";
1026 out <<
" friend class Database;\n";
1028 out <<
" private:\n";
1029 out <<
" const Database &db;\n";
1030 out <<
" container_of_" << tname <<
"(const Database &db): db(db) {}\n";
1032 out <<
" public:\n";
1033 out <<
" class iterator\n";
1035 out <<
" friend class container_of_" << tname <<
";\n";
1036 out <<
" private:\n";
1039 out <<
" const joedb::Compact_Freedom_Keeper *fk;\n";
1040 out <<
" size_t index;\n";
1041 out <<
" iterator(const detail::data_of_" << tname <<
" &data): fk(&data.freedom_keeper), index(0) {}\n";
1042 out <<
" public:\n";
1043 out <<
" typedef std::forward_iterator_tag iterator_category;\n";
1044 out <<
" typedef id_of_" << tname <<
" value_type;\n";
1045 out <<
" typedef std::ptrdiff_t difference_type;\n";
1046 out <<
" typedef value_type* pointer;\n";
1047 out <<
" typedef value_type& reference;\n";
1049 out <<
" bool operator==(const iterator &i) const {return index == i.index;}\n";
1050 out <<
" bool operator!=(const iterator &i) const {return index != i.index;}\n";
1051 out <<
" iterator &operator++() {index = fk->get_next(index); return *this;}\n";
1052 out <<
" iterator operator++(int) {auto copy = *this; index = fk->get_next(index); return copy;}\n";
1053 out <<
" iterator &operator--() {index = fk->get_previous(index); return *this;}\n";
1054 out <<
" iterator operator--(int) {auto copy = *this; index = fk->get_previous(index); return copy;}\n";
1055 out <<
" id_of_" << tname <<
" operator*() const {return id_of_";
1056 out << tname <<
"(Record_Id(index - 1));}\n";
1059 out <<
" iterator begin() const {return ++iterator(db.storage_of_" << tname <<
");}\n";
1060 out <<
" iterator end() const {return iterator(db.storage_of_" << tname <<
");}\n";
1061 out <<
" bool is_empty() const {return db.storage_of_" << tname
1062 <<
".freedom_keeper.is_empty();}\n";
1063 out <<
" size_t get_size() const {return db.storage_of_" << tname <<
".freedom_keeper.get_used_count();}\n";
1064 out <<
" static id_of_" << tname <<
" get_at(size_t i) {return id_of_"
1065 << tname <<
"(Record_Id(i));}\n";
1066 out <<
" bool is_valid_at(size_t i) {return db.storage_of_" << tname <<
".freedom_keeper.is_used(i + 1);}\n";
1068 out <<
" id_of_" << tname <<
" first() const {return *begin();}\n";
1069 out <<
" id_of_" << tname <<
" last() const {return *--end();}\n";
1070 out <<
" id_of_" << tname <<
" get_end() const {return *end();}\n";
1075 out <<
" inline container_of_" << tname <<
" Database::get_" << tname <<
"_table() const\n";
1077 out <<
" return container_of_" << tname <<
"(*this);\n";
1081 out <<
" template<class Comparator>\n";
1082 out <<
" std::vector<id_of_" << tname <<
"> Database::sorted_" << tname;
1083 out <<
"(Comparator comparator) const\n";
1085 out <<
" std::vector<id_of_" << tname <<
"> result;\n";
1086 out <<
" for (auto x: get_" << tname <<
"_table())\n";
1087 out <<
" result.emplace_back(x);\n";
1088 out <<
" std::sort(result.begin(), result.end(), comparator);\n";
1089 out <<
" return result;\n";
1100 out <<
" /// returned by @ref Database::find_" << index.name <<
'\n';
1101 out <<
" class range_of_" << index.name <<
"\n";
1103 out <<
" friend class Database;\n";
1104 out <<
" private:\n";
1105 out <<
" std::pair<";
1107 out <<
"::const_iterator, ";
1109 out <<
"::const_iterator> range;\n";
1110 out <<
" range_of_" << index.name <<
"(const Database &db";
1111 for (
size_t i = 0; i < index.field_ids.size(); i++)
1120 out <<
" range = db.index_of_" << index.name <<
".equal_range(";
1123 for (
size_t i = 0; i < index.field_ids.size(); i++)
1131 out <<
" public:\n";
1132 out <<
" class iterator\n";
1134 out <<
" friend class range_of_" << index.name <<
";\n";
1135 out <<
" private:\n";
1138 out <<
"::const_iterator map_iterator;\n";
1139 out <<
" iterator(";
1141 out <<
"::const_iterator map_iterator): map_iterator(map_iterator) {}\n"
1143 <<
" bool operator !=(const iterator &i) const\n"
1145 <<
" return map_iterator != i.map_iterator;\n"
1147 <<
" iterator &operator++() {map_iterator++; return *this;}\n"
1149 <<
" operator*() const {return map_iterator->second;}\n"
1151 <<
" iterator begin() const {return range.first;}\n"
1152 <<
" iterator end() const {return range.second;}\n"
1153 <<
" bool empty() const {return range.first == range.second;}\n"
1154 <<
" size_t size() const {return size_t(std::distance(range.first, range.second));}\n"
1157 out <<
" inline range_of_" << index.name <<
" Database::find_" << index.name <<
'(';
1158 for (
size_t i = 0; i < index.field_ids.size(); i++)
1164 out <<
" field_value_of_";
1169 out <<
" return range_of_" << index.name <<
"(*this";
1170 for (
size_t i = 0; i < index.field_ids.size(); i++)
1173 out <<
"field_value_of_";
1182 out <<
"\n#endif\n";
const std::vector< std::string > & get_name_space() const
bool has_unique_index() 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 Compact_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
int64_t get_size() const override
const std::string & get_field_name(Table_Id table_id, Field_Id field_id) const
const std::string & get_table_name(Table_Id table_id) const
Table_Id get_table_id() const
Type_Id get_type_id() const
Database_h(const Compiler_Options &options)
void write_index_type(const Compiler_Options::Index &index)
static const char * get_storage_type_string(Type type)
static const char * get_type_string(Type type)
void write_tuple_type(const Compiler_Options::Index &index)
void write_type(Type type, bool return_type, bool setter_type)
static const char * get_cpp_type_string(Type type)
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(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)
One code generator for each of the file generated by joedbc.
constexpr const char * get_version()