-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds an api to collect results into direct object and/or its stl-container #122
base: master
Are you sure you want to change the base?
Conversation
@pPanda-beta Thanks for your PR :-) I like your approach, it can save a lot of repetitive patterns. It can be really hard to write a decent true ORM in C++, I think it's better to set up a separate git repository for this ORM and mention it in the project Readme. |
So forget about orm. but the already available library has ability to collect data in tupples. Does'nt that give any hint that its able to fetch whole record at once? |
Aren't they look similar?
And this one
|
Hi, i like it too, its a generic functor creator for standard stuff not an ORM at all. Maybe its a misunderstanding. I too dont like the idea of a "true" ORM in here but this isnt even close to one. |
Humm, yea i get your point @Killili @pPanda-beta Lets just make sure if we need to change anything or not! // From 103
auto stmt = db << "select age,name,weight from user where age > ? ;" << 21;
for(auto &&[age, name, weight] : stmt.as<int, string, double>()) {
} // Interface in this PR
auto stmt = (db << "select age,name,weight from user where age > ? ;" << 21);
for(auto &&[a,n,w] : (stmt >> collect<int,string,double>::as(vector, tuple<int,string,double>)) {
} |
By the way i really liked if we could do list<int> ids;
db << "select id from tbl;" >> ids;
// instead of the current interface
db << "select id from tbl;" >> collect<int>::to(ids); But we can't because |
@Killili |
@aminroosta These are :
|
I just checked because i thought we had something like that already. |
This combines four features:
I like all of them, but I would like them to usable independent of each other. std::shared_ptr<int> shared = db << "SQL;" >> collect<int>::as<std::shared_ptr,int>(); // OK
db << "SQL;" >> shared; // fails
std::unique_ptr<int> unique = db << "SQL;" >> collect<int>::as<std::unique_ptr,int>(); // fails
db << "SQL;" >> unique; // OK So maybe we can split them up? @aminroosta @pPanda-beta Regarding this and #103: For storing things in containers this has a much better interface than #103, but for iterating #103 has the adventage that for large result not all of them have to be stored but are discarded after each step. So they solve different problems. |
@pPanda-beta In your point 3.a the problem is with non-movable classes, there is no reason not to support, e.g. |
@pPanda-beta 1- Drop the
3- support With 2 & 3 i think we almost don't need the 4- Drop support for user defined types! No 5- Change the So an example combining the above would be: vector<int> ids;
db << "select id from tbl;" >> ids;
vector<int> numbers; // this is blob data
db << "select numbers from tbl where id = ?" << 1 >> numbers;
vector<tuple<int,string>> people;
db << "select age, name from tbl;" >> people;
// The ">> vector<T>&&" operator returns the given vector
auto ids = db << "select id from tbl;" >> (vector<int>());
auto numbers = db << "select numbers from tbl where id = ?" << 1 >> (vector<int>());
auto poeple = db << "select age,name from tbl;" >> (vector<tupe<int,string>>()); |
@aminroosta I like 1, 3, 4 and 5. |
@zauguin You are right about checking the number of rows. // single row blob
vector<int> vblob;
db << "select numbers from tbl where id = 1" >> vblob; // SQLITE_BLOB
// multiple row int
vector<int> vrows;
db << "select age from tbl;" >> vrows; // SQLITE_INTEGER
// multiple rows of blob data
vector<vector<int>> vblobrows; // !
db << "select numbers from tbl;" >> vblobrows; Do you think that works for 2? |
If we stop considering user-defined types then there is no requirement of shared_ptr or unique_ptr. So support for both can be omitted together. Now the I've two confusions.
|
@pPanda-beta Why I'm completely with you that using // single row blob
vector<int> vblob;
db << "select numbers from tbl where id = 1" >> vblob;
// multiple row int
vector<int> vrows;
db << "select age from tbl;" >> collect(vrows); Actually I would prefer it the other way around, like // single row blob
vector<int> vblob;
db << "select numbers from tbl where id = 1" >> blob(vblob);
// multiple row int
vector<int> vrows;
db << "select age from tbl;" >> vrows; because extracting all rows is most likely much more common than extracting a single blob. |
When i was writing the proposed interface i only thought about
Yes it is, i actually like the @pPanda-beta The main functional difference between the two interfaces is dropping support for user defined types. I know that's a debatable topic :-) |
@pPanda-beta If we want to keep the user defined type support, we could try to use a type-trait to document the columns required to serialize it. So you could write something like this class user {
public:
user(int id, std::string name) {...}
...
};
namespace sqlite {
template<> struct serialize<user>: serialize<user, int, std::string> {};
}
...
int main() {
...
auto users = db << "SELECT * FROM users;" >> (std::vector<user>());
...
} This would allow us to combine this functionality with the short syntax. What do you think? |
@aminroosta @zauguin Now
or
For me both overloaded >> operator with rvalue [ e.g. vector() ] and this one seems readable. The only part with which I'm still confused is that why not "user-define types"? |
It's a clever idea, but that's very similar to prepared statements syntax so i'm for
Exactly, this will also be part of the suggested interface implementation.
You are right, i am just a little bit reluctant in case of user defined types, because it looks like an ORM! Not that there is something inherently wrong with an ORM, it's just my personal opinion to keep the library as minimal as possible. The proposed interface from @zauguin looks good to me, if you guys think we should support user defined types, i'm OK too :-) |
On a second thought, the cast overload isn't that bad either.
I do think it's a little confusing but the |
Yaay, type-traits are also great. It leaves the implementation of serialization to the user! That's awesome.
but the real question is how the overloaded >> operator will detect which one to use just from a rvalue reference of vector</just/user> |
The idea was that the author of the class decides which constructor should be used and provides one of the two specializations. This is detected by |
Talking about ORM I was looking around hiberlite and ibatis. Now in this collector api
Now about size of code, Btw, I also discovered that just by writing
to
will allow the developer to write
which will return
so with a very little effort we can reduce a lot of pains of developers and the api will be more flexible, like the way they want to use it, without having any restriction! |
but there can be nessecity for both the constructors...
db<<"SELECT name FROM temp_user WHERE otp_verified=true ;"
db<<"SELECT id,name FROM user ;" so the "way of serialization" can vary from query to query, but if we bound it with our api we are restricting it to only one constructor... |
@pPanda-beta Let's drop the traits then. I would prefer to use an interface which doesn't depend on template template arguments, because they are overly restrictive. Custom containers may not be templates to begin with, may need additional arguments etc. vector<tuple<int, string>> vec;
db << "SQL;" >> collect<>::to(vec);
// or
auto vec2 = db << "SQL;" >> collect<>::as<vector<tuple<int, string>>>(); Without user-defined types it could be vector<tuple<int, string>> vec;
db << "SQL;" >> vec;
// or maybe
auto vec2 = db << "SQL;" >> vector<tuple<int, string>>();
// or even
vector<tuple<int, string>> vec3 = db << "SQL;"; I think the second one is much nicer. |
#define __COLLECTOR_CTOR_OF_T(T,X) {X} | ||
#else | ||
#define __COLLECTOR_RETURN_TYPE std::function<void(Args...)> | ||
#define __COLLECTOR_CTOR_OF_T(T,X) T(X) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't these names violate the standard?
I've created this api for a better ORM like solution which works with sqlite_modern_cpp.
This api can collect multiple results
Also this api can collect single results
SUPPORTS BOTH c++11 and c++14.