27#include "joedb/Freedom_Keeper.h"
28#include "joedb/error/Exception.h"
29#include "joedb/error/assert.h"
30#include "joedb/get_version.h"
42 out <<
"#include \"joedb/Blob.h\"\n";
46 out <<
"#include \"joedb/ui/type_io.h\"\n";
47 out <<
"#include <sstream>\n";
51 out <<
"#include <map>\n";
53 out <<
"\nstatic_assert(std::string_view(joedb::get_version()) == \"";
65 using joedb::Record_Id;
66 using joedb::Table_Id;
67 using joedb::Field_Id;
71 for (
const auto &[tid, tname]: tables)
72 out <<
" class container_of_" << tname <<
";\n";
74 out <<
"\n namespace detail\n {";
75 for (
const auto &[tid, tname]: tables)
77 out <<
"\n struct data_of_" << tname;
81 out <<
" Field_Id current_field_id = Field_Id(0);\n";
83 std::vector<std::string> fields;
85 for (
const auto &[fid, fname]: db.
get_fields(tid))
87 fields.emplace_back(
"field_value_of_" + fname);
91 out <<
" std::vector<";
93 out <<
"> " << fields.back() <<
";\n";
97 if (index.table_id == tid)
99 out <<
" std::vector<";
101 out <<
"::iterator> ";
102 fields.emplace_back(
"iterator_over_" + index.name);
103 out << fields.back() <<
";\n";
107 joedb::Freedom_Keeper freedom_keeper;
109 size_t size() const {return freedom_keeper.size();}
111 void resize(size_t new_size)
115 fields.emplace_back("freedom_keeper");
116 for (
const std::string &field: fields)
117 out <<
" " << field <<
".resize(new_size);\n";
125 out <<
" class range_of_" << index.name <<
";\n";
128 out <<
" /// Store all the tables of the database\n";
129 out <<
" class Database\n {\n";
130 out <<
" friend class Readable;\n";
132 for (
const auto &[tid, tname]: tables)
133 out <<
" friend class container_of_" << tname <<
";\n";
137 out <<
" friend class range_of_" << index.name <<
";\n";
141 template<typename E = joedb::Exception>
142 static void throw_exception(const std::string &message)
146 << R"RRR(: " + message);
154 for (
const auto &[tid, tname]: tables)
156 out <<
" bool is_valid(id_of_" << tname <<
" id) const {return is_valid_record_id_for_" << tname <<
"(id.get_record_id());}\n";
159 out <<
"\n protected:\n";
161 for (
const auto &[tid, tname]: tables)
163 out <<
" detail::data_of_" << tname <<
" storage_of_" << tname <<
";\n";
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";
182 out <<
" index_of_" << index.name <<
";\n";
184 out <<
" void remove_index_of_" << index.name <<
"(Record_Id record_id)\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";
190 out <<
" index_of_" << index.name <<
".erase(iterator);\n";
191 out <<
" iterator = index_of_" << index.name <<
".end();\n";
195 out <<
" void add_index_of_" << index.name <<
"(Record_Id record_id)\n";
197 out <<
" auto result = index_of_" << index.name;
198 out <<
".insert\n (\n ";
200 out <<
"::value_type\n (\n ";
203 for (
size_t i = 0; i < index.field_ids.size(); i++)
207 out <<
"storage_of_" << tname <<
".field_value_of_";
209 out <<
"[to_underlying(record_id)]";
212 out <<
",\n id_of_" << tname <<
"(record_id)\n )\n );\n";
215 out <<
" if (!result.second)\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++)
222 out <<
" out << \", \";\n";
223 const auto type = db.
get_field_type(index.table_id, index.field_ids[i]);
225 out <<
"storage_of_" << tname <<
".field_value_of_";
227 out <<
"[to_underlying(record_id)]";
228 if (type.get_type_id() == joedb::Type::Type_Id::reference)
229 out <<
".get_record_id()";
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";
236 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = result.first;\n";
239 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = result;\n";
247 for (
const auto &[tid, tname]: tables)
249 out <<
" void internal_delete_" << tname <<
"(Record_Id record_id)\n";
251 out <<
" JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname <<
"(record_id));\n";
254 if (index.table_id == tid)
255 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
257 for (
const auto &[fid, fname]: db.
get_fields(tid))
261 out <<
" storage_of_" << tname <<
".field_value_of_";
262 out << fname <<
"[to_underlying(record_id)]";
268 else if (type.
get_type_id() == Type::Type_Id::reference)
272 out <<
"(joedb::Record_Id::null)";
274 else if (type.
get_type_id() == Type::Type_Id::blob)
276 out <<
" = joedb::Blob()";
286 out <<
" storage_of_" << tname <<
".freedom_keeper.free(record_id);\n";
291 for (
const auto &[tid, tname]: tables)
293 out <<
" void internal_insert_" << tname <<
"(Record_Id record_id)\n";
297 if (index.table_id == tid)
299 out <<
" storage_of_" << tname;
300 out <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = ";
301 out <<
"index_of_" << index.name <<
".end();\n";
304 out <<
" storage_of_" << tname <<
".freedom_keeper.use(record_id);\n";
308 out <<
" void internal_vector_insert_" << tname <<
"(Record_Id record_id, size_t size)\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";
314 if (index.table_id == tid)
316 out <<
" std::fill_n\n";
318 out <<
" &storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)],\n";
320 out <<
" index_of_" << index.name <<
".end()\n";
328 for (
const auto &[tid, tname]: tables)
330 for (
const auto &[fid, fname]: db.
get_fields(tid))
334 out <<
" void internal_update_" << tname <<
"__" << fname;
335 out <<
"\n (\n Record_Id record_id,\n ";
337 out <<
" field_value_of_" << fname <<
"\n )\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;
346 if (index.is_trigger(tid, fid))
348 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
349 out <<
" add_index_of_" << index.name <<
"(record_id);\n";
355 out <<
" void internal_update_vector_" << tname <<
"__" << fname <<
'\n';
357 out <<
" Record_Id record_id,\n";
358 out <<
" size_t size,\n";
364 out <<
" JOEDB_RELEASE_ASSERT(storage_of_" << tname <<
".freedom_keeper.is_used_vector(record_id, size));\n";
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";
374 if (index.is_trigger(tid, fid))
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";
392 for (
const auto &[tid, tname]: tables)
401 out <<
" container_of_" << tname <<
" get_" << tname <<
"_table() const;\n\n";
403 out <<
" id_of_" << tname <<
" next(id_of_" << tname <<
" id) const\n";
405 out <<
" return id_of_" << tname <<
"\n (\n Record_Id(storage_of_" << tname <<
".freedom_keeper.get_next(id.get_record_id()))\n );\n";
408 out <<
" id_of_" << tname <<
" previous(id_of_" << tname <<
" id) const\n";
410 out <<
" return id_of_" << tname <<
"\n (\n Record_Id(storage_of_" << tname <<
".freedom_keeper.get_previous(id.get_record_id()))\n );\n";
415 out <<
" template<class Comparator>\n";
416 out <<
" std::vector<id_of_" << tname <<
"> sorted_" << tname;
417 out <<
"(Comparator comparator) const;\n\n";
423 out <<
" static id_of_" << tname <<
" null_" << tname <<
"()\n";
425 out <<
" return id_of_" << tname <<
"();\n";
433 out <<
" static constexpr id_of_" << tname <<
" the_" << tname <<
"()\n";
435 out <<
" return id_of_" << tname <<
"{0};\n";
442 for (
const auto &[fid, fname]: db.
get_fields(tid))
453 out <<
" get_" << fname <<
"(id_of_" << tname <<
" record";
455 out <<
" = id_of_" << tname <<
"{0}";
458 out <<
" JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname <<
"(record.get_record_id()));\n";
461 out <<
")(storage_of_" << tname;
462 out <<
".field_value_of_" << fname <<
"[record.get_id()]);\n";
475 out <<
" &get_index_of_" << index.name <<
"()\n";
477 out <<
" return index_of_" << index.name <<
";\n";
491 out <<
" id_of_" << tname <<
" next_" << index.name <<
'(';
492 out <<
"id_of_" << tname <<
" id)\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";
500 out <<
" return id_of_" << tname <<
"();\n";
503 out <<
" id_of_" << tname <<
" previous_" << index.name <<
'(';
504 out <<
"id_of_" << tname <<
" id)\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";
511 out <<
" return id_of_" << tname <<
"();\n";
514 out <<
" id_of_" << tname <<
" find_" << index.name <<
'(';
515 for (
size_t i = 0; i < index.field_ids.size(); i++)
521 out <<
" field_value_of_";
526 out <<
" const auto i = index_of_" << index.name <<
".find(";
529 for (
size_t i = 0; i < index.field_ids.size(); i++)
533 out <<
"field_value_of_";
537 out <<
" if (i == index_of_" << index.name <<
".end())\n";
538 out <<
" return id_of_" << tname <<
"();\n";
540 out <<
" return i->second;\n";
545 out <<
" range_of_" << index.name <<
" find_" << index.name <<
'(';
546 for (
size_t i = 0; i < index.field_ids.size(); i++)
552 out <<
" field_value_of_";
564 for (
const auto &[tid, tname]: tables)
568 out <<
" /// returned by @ref Database::get_" << tname <<
"_table\n";
569 out <<
" class container_of_" << tname <<
"\n";
571 out <<
" friend class Database;\n";
573 out <<
" private:\n";
574 out <<
" const Database &db;\n";
575 out <<
" container_of_" << tname <<
"(const Database &db): db(db) {}\n";
578 out <<
" class iterator\n";
580 out <<
" friend class container_of_" << tname <<
";\n";
581 out <<
" private:\n";
584 out <<
" const joedb::Freedom_Keeper *fk;\n";
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";
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";
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";
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";
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";
620 out <<
" inline container_of_" << tname <<
" Database::get_" << tname <<
"_table() const\n";
622 out <<
" return container_of_" << tname <<
"(*this);\n";
628 out <<
" template<class Comparator>\n";
629 out <<
" std::vector<id_of_" << tname <<
"> Database::sorted_" << tname;
630 out <<
"(Comparator comparator) const\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";
648 out <<
" /// returned by @ref Database::find_" << index.name <<
'\n';
649 out <<
" class range_of_" << index.name <<
"\n";
651 out <<
" friend class Database;\n";
652 out <<
" private:\n";
653 out <<
" std::pair<";
655 out <<
"::const_iterator, ";
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++)
668 out <<
" range = db.index_of_" << index.name <<
".equal_range(";
671 for (
size_t i = 0; i < index.field_ids.size(); i++)
680 out <<
" class iterator\n";
682 out <<
" friend class range_of_" << index.name <<
";\n";
683 out <<
" private:\n";
686 out <<
"::const_iterator map_iterator;\n";
689 out <<
"::const_iterator map_iterator): map_iterator(map_iterator) {}\n"
691 <<
" bool operator !=(const iterator &i) const\n"
693 <<
" return map_iterator != i.map_iterator;\n"
695 <<
" iterator &operator++() {map_iterator++; return *this;}\n"
697 <<
" operator*() const {return map_iterator->second;}\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"
705 out <<
" inline range_of_" << index.name <<
" Database::find_" << index.name <<
'(';
706 for (
size_t i = 0; i < index.field_ids.size(); i++)
712 out <<
" field_value_of_";
717 out <<
" return range_of_" << index.name <<
"(*this";
718 for (
size_t i = 0; i < index.field_ids.size(); i++)
721 out <<
"field_value_of_";
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 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
const std::string & get_table_name(Table_Id 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_type_string(Type type)
void write_type(Type type, bool return_type, bool setter_type)
const Compiler_Options & options
void write_tuple_type(const Compiler_Options::Index &index, bool reference)
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()
One code generator for each of the file generated by joedbc.