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)
134 out <<
" friend class id_of_" << tname <<
";\n";
135 out <<
" friend class container_of_" << tname <<
";\n";
140 out <<
" friend class range_of_" << index.name <<
";\n";
144 template<typename E = joedb::Exception>
145 static void throw_exception(const std::string &message)
149 << R"RRR(: " + message);
157 for (
const auto &[tid, tname]: tables)
159 out <<
" bool is_valid(id_of_" << tname <<
" id) const {return is_valid_record_id_for_" << tname <<
"(id.get_record_id());}\n";
162 out <<
"\n protected:\n";
164 for (
const auto &[tid, tname]: tables)
166 out <<
" detail::data_of_" << tname <<
" storage_of_" << tname <<
";\n";
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";
185 out <<
" index_of_" << index.name <<
";\n";
187 out <<
" void remove_index_of_" << index.name <<
"(Record_Id record_id)\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";
193 out <<
" index_of_" << index.name <<
".erase(iterator);\n";
194 out <<
" iterator = index_of_" << index.name <<
".end();\n";
198 out <<
" void add_index_of_" << index.name <<
"(Record_Id record_id)\n";
200 out <<
" auto result = index_of_" << index.name;
201 out <<
".insert\n (\n ";
203 out <<
"::value_type\n (\n ";
206 for (
size_t i = 0; i < index.field_ids.size(); i++)
210 out <<
"storage_of_" << tname <<
".field_value_of_";
212 out <<
"[to_underlying(record_id)]";
215 out <<
",\n id_of_" << tname <<
"(record_id)\n )\n );\n";
218 out <<
" if (!result.second)\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++)
225 out <<
" out << \", \";\n";
226 const auto type = db.
get_field_type(index.table_id, index.field_ids[i]);
228 out <<
"storage_of_" << tname <<
".field_value_of_";
230 out <<
"[to_underlying(record_id)]";
231 if (type.get_type_id() == joedb::Type::Type_Id::reference)
232 out <<
".get_record_id()";
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";
239 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = result.first;\n";
242 out <<
" storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = result;\n";
250 for (
const auto &[tid, tname]: tables)
252 out <<
" void internal_delete_" << tname <<
"(Record_Id record_id)\n";
254 out <<
" JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname <<
"(record_id));\n";
257 if (index.table_id == tid)
258 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
260 for (
const auto &[fid, fname]: db.
get_fields(tid))
264 out <<
" storage_of_" << tname <<
".field_value_of_";
265 out << fname <<
"[to_underlying(record_id)]";
271 else if (type.
get_type_id() == Type::Type_Id::reference)
275 out <<
"(joedb::Record_Id::null)";
277 else if (type.
get_type_id() == Type::Type_Id::blob)
279 out <<
" = joedb::Blob()";
289 out <<
" storage_of_" << tname <<
".freedom_keeper.free(record_id);\n";
294 for (
const auto &[tid, tname]: tables)
296 out <<
" void internal_insert_" << tname <<
"(Record_Id record_id)\n";
300 if (index.table_id == tid)
302 out <<
" storage_of_" << tname;
303 out <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)] = ";
304 out <<
"index_of_" << index.name <<
".end();\n";
307 out <<
" storage_of_" << tname <<
".freedom_keeper.use(record_id);\n";
311 out <<
" void internal_vector_insert_" << tname <<
"(Record_Id record_id, size_t size)\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";
317 if (index.table_id == tid)
319 out <<
" std::fill_n\n";
321 out <<
" &storage_of_" << tname <<
".iterator_over_" << index.name <<
"[to_underlying(record_id)],\n";
323 out <<
" index_of_" << index.name <<
".end()\n";
331 for (
const auto &[tid, tname]: tables)
333 for (
const auto &[fid, fname]: db.
get_fields(tid))
337 out <<
" void internal_update_" << tname <<
"__" << fname;
338 out <<
"\n (\n Record_Id record_id,\n ";
340 out <<
" field_value_of_" << fname <<
"\n )\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;
349 if (index.is_trigger(tid, fid))
351 out <<
" remove_index_of_" << index.name <<
"(record_id);\n";
352 out <<
" add_index_of_" << index.name <<
"(record_id);\n";
358 out <<
" void internal_update_vector_" << tname <<
"__" << fname <<
'\n';
360 out <<
" Record_Id record_id,\n";
361 out <<
" size_t size,\n";
367 out <<
" JOEDB_RELEASE_ASSERT(storage_of_" << tname <<
".freedom_keeper.is_used_vector(record_id, size));\n";
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";
377 if (index.is_trigger(tid, fid))
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";
395 for (
const auto &[tid, tname]: tables)
403 out <<
" container_of_" << tname <<
" get_" << tname <<
"_table() const;\n\n";
405 out <<
" id_of_" << tname <<
" next(id_of_" << tname <<
" id) const\n";
407 out <<
" return id_of_" << tname <<
"\n (\n Record_Id(storage_of_" << tname <<
".freedom_keeper.get_next(id.get_record_id()))\n );\n";
410 out <<
" id_of_" << tname <<
" previous(id_of_" << tname <<
" id) const\n";
412 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";
422 out <<
" static id_of_" << tname <<
" null_" << tname <<
"()\n";
424 out <<
" return id_of_" << tname <<
"();\n";
432 out <<
" static constexpr id_of_" << tname <<
" the_" << tname <<
"()\n";
434 out <<
" return id_of_" << tname <<
"{0};\n";
441 for (
const auto &[fid, fname]: db.
get_fields(tid))
452 out <<
" get_" << fname <<
"(id_of_" << tname <<
" record";
454 out <<
" = id_of_" << tname <<
"{0}";
457 out <<
" JOEDB_RELEASE_ASSERT(is_valid_record_id_for_" << tname <<
"(record.get_record_id()));\n";
460 out <<
")(storage_of_" << tname;
461 out <<
".field_value_of_" << fname <<
"[record.get_id()]);\n";
474 out <<
" &get_index_of_" << index.name <<
"()\n";
476 out <<
" return index_of_" << index.name <<
";\n";
490 out <<
" id_of_" << tname <<
" next_" << index.name <<
'(';
491 out <<
"id_of_" << tname <<
" id)\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";
499 out <<
" return id_of_" << tname <<
"();\n";
502 out <<
" id_of_" << tname <<
" previous_" << index.name <<
'(';
503 out <<
"id_of_" << tname <<
" id)\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";
510 out <<
" return id_of_" << tname <<
"();\n";
513 out <<
" id_of_" << tname <<
" find_" << index.name <<
'(';
514 for (
size_t i = 0; i < index.field_ids.size(); i++)
520 out <<
" field_value_of_";
525 out <<
" const auto i = index_of_" << index.name <<
".find(";
528 for (
size_t i = 0; i < index.field_ids.size(); i++)
532 out <<
"field_value_of_";
536 out <<
" if (i == index_of_" << index.name <<
".end())\n";
537 out <<
" return id_of_" << tname <<
"();\n";
539 out <<
" return i->second;\n";
544 out <<
" range_of_" << index.name <<
" find_" << index.name <<
'(';
545 for (
size_t i = 0; i < index.field_ids.size(); i++)
551 out <<
" field_value_of_";
563 for (
const auto &[tid, tname]: tables)
565 out <<
" /// returned by @ref Database::get_" << tname <<
"_table\n";
566 out <<
" class container_of_" << tname <<
"\n";
568 out <<
" friend class Database;\n";
570 out <<
" private:\n";
571 out <<
" const Database &db;\n";
572 out <<
" container_of_" << tname <<
"(const Database &db): db(db) {}\n";
575 out <<
" class iterator\n";
577 out <<
" friend class container_of_" << tname <<
";\n";
578 out <<
" private:\n";
581 out <<
" const joedb::Freedom_Keeper *fk;\n";
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";
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";
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";
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";
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";
617 out <<
" inline container_of_" << tname <<
" Database::get_" << tname <<
"_table() const\n";
619 out <<
" return container_of_" << tname <<
"(*this);\n";
623 out <<
" template<class Comparator>\n";
624 out <<
" std::vector<id_of_" << tname <<
"> Database::sorted_" << tname;
625 out <<
"(Comparator comparator) const\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";
642 out <<
" /// returned by @ref Database::find_" << index.name <<
'\n';
643 out <<
" class range_of_" << index.name <<
"\n";
645 out <<
" friend class Database;\n";
646 out <<
" private:\n";
647 out <<
" std::pair<";
649 out <<
"::const_iterator, ";
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++)
662 out <<
" range = db.index_of_" << index.name <<
".equal_range(";
665 for (
size_t i = 0; i < index.field_ids.size(); i++)
674 out <<
" class iterator\n";
676 out <<
" friend class range_of_" << index.name <<
";\n";
677 out <<
" private:\n";
680 out <<
"::const_iterator map_iterator;\n";
683 out <<
"::const_iterator map_iterator): map_iterator(map_iterator) {}\n"
685 <<
" bool operator !=(const iterator &i) const\n"
687 <<
" return map_iterator != i.map_iterator;\n"
689 <<
" iterator &operator++() {map_iterator++; return *this;}\n"
691 <<
" operator*() const {return map_iterator->second;}\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"
699 out <<
" inline range_of_" << index.name <<
" Database::find_" << index.name <<
'(';
700 for (
size_t i = 0; i < index.field_ids.size(); i++)
706 out <<
" field_value_of_";
711 out <<
" return range_of_" << index.name <<
"(*this";
712 for (
size_t i = 0; i < index.field_ids.size(); i++)
715 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(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()
One code generator for each of the file generated by joedbc.