основные данные — C ++ Object Database

Я работаю над диссертацией моего бакалавра. Его цель — написать объектную базу данных (похожую на CoreData) на C ++. Одним из требований является поддержка отражающих отношений (1-1,1-M, M-M) и динамической загрузки объекта.

Мой текущий дизайн состоит из простого языка DDL с генерацией кода.
Пользователь пишет свои классы, которые он хочет сохранить, а затем записывает отношения между этими классами. Что-то вроде этого:

Person {
string name;
int salary;
}
relation Person.boss(1) references Person inverse Person.subs(M);

Исходя из этого, я генерирую заголовок C ++ с определением класса, источник C ++ с определениями метода. Класс имеет все примитивные поля как открытые, отношения являются частными и доступны только для методов get / set или get / add / remove / clear.
В этих методах я сохраняю последовательность рефлексивных отношений.
Например: в методе setBoss Я бы сделал следующее:

void setBoss(ptr<Person> val) {
if (boss) {
boss->subs.remove(this);
}
boss = val;
boss->subs.add(this);
boss.modified = true
}

Этот код генерируется и работает. Но мой супервайзер требует, чтобы я делал это без какой-либо формы генерации кода и пытался следовать CoreData как можно ближе. Я думаю, что его идея состоит в том, чтобы моделировать динамический объект в C ++, где каждый объект, который может быть сохранен в базе данных, содержит map<string,value>и поля считываются с этой карты. Я думаю, что этот дизайн явно не подходит для C ++, так как для хранения всего подобного необходимо, чтобы каждое поле было пользовательским классом, имеющим ссылку на владельца и динамическое приведение при каждом доступе к полю, и я даже не говорю о хранении других классов, которые используют пользовательский общий указатель (это шаблон, поэтому динамическое приведение не будет работать).

Кроме того, существует проблема с метаданными, как определить схему в этой системе? Я, вероятно, мог бы использовать посетителя, который посещает все поля и с помощью некоторого макрокоманды извлекает их имя и тип, но рефлексивные отношения? Я не знаю.

В моем подходе я могу каким-то образом добавлять версии полей и генерировать для них код миграции. (сохранение версии схемы в постоянной базе данных, затем, когда я открываю эту базу данных, проверяю версию и запускаю сгенерированный код миграции).

Есть что-то, чего я здесь не хватает? Мой подход совершенно неверный?

0

Решение

[конечно, ниже мнение, но вините вопрос, а не я]

Есть что-то, чего я здесь не хватает? Мой подход совершенно неверный?

Совершенно неправильно — нет. Но не лишен рисков.

Один из недостатков вашего подхода (похожего на ORM): каждый раз, когда вы меняете свои структуры, «миграция хранилища данных» становится кошмаром. Или вам придется навязывать пользователям (коллегам-программистам) кошмар работы с различными версиями схемы.

Посмотрите на Google protobuff на вкус проблем с генерируемыми структурами, находящимися в процессе эволюции — они имеют дело не с хранилищем, а с передачей данных. И все же вы должны тщательно ориентироваться (какие участники являются обязательными / необязательными) и соблюдать некоторые строгие правила (например, между версиями вашего протокола, просто добавьте, но никогда не удаляй поля).

Кроме того, существует проблема с метаданными, как определить схему в этой системе?

Разве это не замечательная тема для вашей диссертации? Конечно, это не будет тривиальным, но почему это должно быть?

0

Другие решения

Без генерации кода вам придется выбирать между подходом скомпилированного уровня — с использованием DSL — или подходом, ориентированным на время выполнения, — с использованием некоторого сочетания виртуальных функций, динамического приведения и typeid / typeindex.

Упражнения с DSL — это то, с чем мы столкнулись в этом году, и, как ни странно, они очень тесно связаны с вашим вопросом: конкретно коллекции 1-1, 1-N, N-N. Конечно, это было бы излишним для дипломной работы бакалавра, но вот как это может выглядеть: https://github.com/C5T/Current/blob/1b9716438d323b8b47eb8d5bf5907e98ee3be1dc/Storage/test.cc#L92-L120

В вашем случае я бы начал с непосредственного обращения к руководителю, ищут ли они решение во время компиляции или во время выполнения. Время выполнения, вероятно, проще реализовать с точки зрения времени и LOC, но это даст значительно меньше гарантий, а результат будет менее практичным. Для строки <=> только сопоставления строк, хотя пара коллекций и классы политик с виртуальными ссылками вполне могут справиться с этой задачей.

0

По вопросам рекламы [email protected]