я не спорю, что pragma это очень важный и нужный инструмент. То же самое можно сказать даже про макросы. Однако речь не об этом, а о том, что при подключении ORM приходится модифицировать код модели. Вот тут https://habrahabr.ru/post/263027/ очень хорошо описано почему так делать не надо
Очень интересный кейс. Чтобы его воспроизвести в sqlite_orm нужно время. А пока в последнем коммите добавлена возможность выбора нескольких колонок как вы и говорили. В конце статьи добавлен пример
нет, не понял ни первое, ни второе. 1) почему прослойка не нужна при использовании статичных С-массивов? 2) "С++ располагает к использованию UserType typeId; вместо int userTypeId; т.е. к использованию иерархического дерева объектов вместо таблиц." — вы про вложенные сущности? Если да, то вложенные сущности это ад. Это понимаешь, когда пытаешься масштабировать систему. Вложенные сущности актуальны в проектах с небольшим сроком жизни. Я не спорю — таких очень много, поэтому на вложенные сущности много кто смотрит как на нечто удобное. Плюс в таком виде как вы показали вложенные сущности не скомпилируются если вложение взаимное. Если я вас понял неверно — поясните пожалуйста.
расскажите поподробнее. Изначально цель sqlite_orm покрыть бОльшую часть использования sqlite3 в приложениях, а значит ваш кейс особенно интересен. Покажите схему как хотите хранить отношения многие ко многим. Отдельным словарем или как?
В вашем примере есть вложенные сущности, а они не поддерживаются в sqlite_orm просто потому что это усложняет основу системы. Более того, взаимновложенные сущности не скомпилируются в С++ вообще (при условии агрегации).
А то, о чем вы говорите, реализуется в sqlite_orm вот так:
struct Book {
int id;
std::string name;
int categoryId;
int createdAt;
};
struct Category {
int id;
std::string name;
};
using namespace sqlite_orm;
auto storage = make_storage("db.sqlite",
make_table("books",
make_column("id", &Book::id, primary_key()),
make_column("name", &Book::name),
make_column("category_id", &Book::categoryId),
make_column("created_at", &Book::createdAt)),
make_table("categories",
make_column("id", &Category::id, primary_key()),
make_column("name", &Category::name)));
// лимита нет, каюсь, в ближайших коммитах будет
auto books = storage.get_all<Book>(order_by(&Book::createdAt));
// теперь вытащим вектор из id категорий
std::vector<decltype(Book::categoryId)> categoryIds;
categoryIds.reserve(books.size());
std::transform(books.begin();
books.end();
std::back_inserter(categoryIds),
[](auto &book) {
return book.categoryId;
});
// std::transform может быть неудобен, но это православная stl-реализация функции map
auto categories = storage.get_all<Category>(where(in(&Category::id, categoryIds)));
// теперь books содержит выбранные книги, а categories - их категории
Или можно сымитировать сложные запрос:
auto books = storage.get_all<Book>(order_by(&Book::createdAt));
auto categories = storage.get_all<Category>(where(in(&Category::id,
storage.select(&Book::categoryId)
)));
Расскажите, пожалуйста, поподробнее про "возможность достать связанные foreign keyем сущности". Я так понимаю это что-то типа взяли юзера, у него есть поле category_id, достали категорию с этим id?
разумное замечание. Сейчас я размышляю сделать так: оставить get_all, добавить auto it = storage.iterate<User>().begin();. Итератор будет хранить в себе statement указатель, оператор* будет возвращать объект, оператор++ будет двигать statement вперед, storage.iterate<T>.end() будет возвращать итератор с нулевым statement. При присвоении итератору .end() или при очередном оператор++ когда достигнут конец таблицы итератор закрывает statement. В общем, получится forward iterator полностью stl-совместимый. Тут, конечно, есть косяк, что итератор хранит важную инфу, что не совсем stl-style, но с другой стороны можно будет делать так:
select присутствует для одной колонки только пока. В ближайших коммитах будет интерфейс для выбора нескольких колонок в std::tuple: auto vectorOfTuples = storage.select(columns(&User::id, &User::firstName));.
Насчет JOIN и GROUP BY покажите примеры из своей практики чтобы я понял вас лучше. Спасибо
в нынешней версии библиотеки связей нет. Вообще уже был запрос один добавить foreign key. В целом это сделать несложно, вопрос в другом — нужно ли это во встраиваемой БД. Лично я не использую связи даже при их логическом наличии, так как это создает runtime overhead. Однако спасибо за отзыв — в дальнейших версиях обязательно будет добавлена функция foreing_key со ссылкой на поле другого класса.
я не спорю, что pragma это очень важный и нужный инструмент. То же самое можно сказать даже про макросы. Однако речь не об этом, а о том, что при подключении ORM приходится модифицировать код модели. Вот тут https://habrahabr.ru/post/263027/ очень хорошо описано почему так делать не надо
Очень интересный кейс. Чтобы его воспроизвести в
sqlite_orm
нужно время. А пока в последнем коммите добавлена возможность выбора нескольких колонок как вы и говорили. В конце статьи добавлен примерПонял, в каком финальном виде вы хотите получить данные?
нет, не понял ни первое, ни второе. 1) почему прослойка не нужна при использовании статичных С-массивов? 2) "С++ располагает к использованию UserType typeId; вместо int userTypeId; т.е. к использованию иерархического дерева объектов вместо таблиц." — вы про вложенные сущности? Если да, то вложенные сущности это ад. Это понимаешь, когда пытаешься масштабировать систему. Вложенные сущности актуальны в проектах с небольшим сроком жизни. Я не спорю — таких очень много, поэтому на вложенные сущности много кто смотрит как на нечто удобное. Плюс в таком виде как вы показали вложенные сущности не скомпилируются если вложение взаимное. Если я вас понял неверно — поясните пожалуйста.
расскажите поподробнее. Изначально цель
sqlite_orm
покрыть бОльшую часть использования sqlite3 в приложениях, а значит ваш кейс особенно интересен. Покажите схему как хотите хранить отношения многие ко многим. Отдельным словарем или как?пунктом про single responsibility
В вашем примере есть вложенные сущности, а они не поддерживаются в
sqlite_orm
просто потому что это усложняет основу системы. Более того, взаимновложенные сущности не скомпилируются в С++ вообще (при условии агрегации).А то, о чем вы говорите, реализуется в
sqlite_orm
вот так:Или можно сымитировать сложные запрос:
Расскажите, пожалуйста, поподробнее про "возможность достать связанные foreign keyем сущности". Я так понимаю это что-то типа взяли юзера, у него есть поле
category_id
, достали категорию с этим id?разумное замечание. Сейчас я размышляю сделать так: оставить
get_all
, добавитьauto it = storage.iterate<User>().begin();
. Итератор будет хранить в себе statement указатель, оператор* будет возвращать объект, оператор++ будет двигать statement вперед,storage.iterate<T>.end()
будет возвращать итератор с нулевым statement. При присвоении итератору .end() или при очередном оператор++ когда достигнут конец таблицы итератор закрывает statement. В общем, получится forward iterator полностью stl-совместимый. Тут, конечно, есть косяк, что итератор хранит важную инфу, что не совсем stl-style, но с другой стороны можно будет делать так:И после break statement закроется, что по сути и есть то, о чем вы говорите — одномоментно в памяти висит только один юзер, а не все сразу.
CREATE TABLE books(id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE categories(id INTEGER, name TEXT)
CREATE TABLE books_categories(category_id INTEGER, book_id INTEGER)
Вы подразумеваете такую схему? И напишите пожалуйста запрос каким бы вы достали данные для пунктов 1 и 2. Спасибо
select
присутствует для одной колонки только пока. В ближайших коммитах будет интерфейс для выбора нескольких колонок вstd::tuple
:auto vectorOfTuples = storage.select(columns(&User::id, &User::firstName));
.Насчет
JOIN
иGROUP BY
покажите примеры из своей практики чтобы я понял вас лучше. Спасибов нынешней версии библиотеки связей нет. Вообще уже был запрос один добавить
foreign key
. В целом это сделать несложно, вопрос в другом — нужно ли это во встраиваемой БД. Лично я не использую связи даже при их логическом наличии, так как это создает runtime overhead. Однако спасибо за отзыв — в дальнейших версиях обязательно будет добавлена функцияforeing_key
со ссылкой на поле другого класса.