Open saki7 opened 8 years ago
@zussel said in the issue #56 that you can't mix query<T>
and object_view<T>
, but I'd suggest it to create a base class representing composed queries then make query<T>
and object_query<T>
(the new class, or whatsoever) inherit it to avoid duplicate in the implementation...
object_query<t>
came to my mind as well. Good suggestion.
I can't derive form query<T>
because query<T>
contains beside the select interfaces all other statement interfaces (like create
, drop
, ...). So I'll implement the few methods right away.
The lazy loading issue might be a bigger one when it comes to relations and dereferencing them. Just have a look at the docs (has_one
and has_many
).
But after our discussion that feature looks really promising and tangible to me.
I thought not to derive from query<T>
(sorry for my bad English), I meant something like this:
template<class T, class Self>
class basic_query
{
public:
typedef Self self_type;
template<class COND>
self_type& where(COND const& cond)
{
// Just an another pseudo-code here
conds_.push_back(cond);
return *static_cast<self_type*>(this);
}
self_type& limit(unsigned count)
{
conds_.push_back(oos::limit(count));
return *static_cast<self_type*>(this);
}
// Other SQL related common methods go here...
};
template<class T>
class object_query : public basic_query<T, object_query<T>>
{
public:
object_view<T> execute()
{
// Since session::select() is intended to return this class (object_query<T>),
// the internal persistence object should be available here
publish_sql(persistence_);
}
};
template<class T>
class query : public basic_query<T, query<T>>
{
public:
void create() { /* do something */ }
void drop() { /* do something */ }
result<T> execute(connection& c)
{
// You know, a `connection` is required for query<T>s.
publish_sql(c);
}
};
Chaining + inheritance = wizardly code I guess...
I think that the downcasting of static_cast<self_type*>(this)
is well-formed since we already know the target class is derived from basic_query<T>
. Or I may be missing something.
This way I think you can avoid the statement function duplicates for object_query<T>
and query<T>
.
And for dereferencing relations in lazy loading you can google "N+1 problem" - the library should have an eager-loading feature to avoid it.
It's quite easy though - just publish SELECT "books".* FROM "books" WHERE "books"."id" IN (45, 56, 98, ...)
The model objects in Ruby on Rails (ActiveRecord) have a method includes("related_table_name")
to set which table to load. You don't need to eager load all relations in a query; just specify the ones you need and it's ok.
Oh yes, I know this pattern. It's called _Curiously recurring template pattern_. And I used it at some places in my code. That's indeed a good possibility to "derive" from this kind of interface.
Didn't know the N+1 problem. I'll take a look at it. Maybe it can solve the lazy loading problem with it. Thank you for the hint!
As for the next release there are just to issues to solve:
So things developing well :smile:
Motivation
query<T>
already has a SQL-friendly fluent interfacesession::select<T>()
returnsobject_view<T>
instead ofquery<T>
object_view<T>
does not have a friendly interface for querying (however it's still good at filtering)object_view<T>
What to do
session::select<T>()
fluent and equal asquery<T>
object_query<T>
for the return type and leaveobject_view<T>
for the return type ofexecute()
is a good ideaexecute()
)The API
See also
The issue #56.