Hey,

2009/12/26 OvermindDL1 <[email protected]>:
> I have started looking at Wt::DBO to replace my sqlite marshaller and
> I notice something odd right off the bat.
> It seems there can only be one session at a time?

Not at all, a bit unexpectedly, the blog on our homepage (which uses
Wt::Dbo) was hit by slashdot and handled the many concurrent sessions
very well.

> Rather, more specifically, I would have to use some type of locking
> queue of connections, and pull from it each time I wish to create a
> session, and it kind of looks like it would be rather heavy to create
> a session object each time as well.  So I can either use a pool of
> connections and create sessions on demand from a connection in that
> pool (with the running of many mapClass's), or I could make a pool of
> sessions, each attached to its own connections, and use the sessions
> from the pool as necessary, and so on and so forth.  The two files I

The idea is to create a dbo::Session per user session. What is
currently lacking is a ConnectionPool object (as it is only an
optimization), which allows sessions to only use a connection during
an active transaction. But everything has been implemented with a
connection pool in mind. In the future we might also consider sharing
a kind of ObjectRegistry between sessions for read-only objects.

W.r.t. locking: the current implementation only implements optimistic
database locking, which is what in our experience is what is most
often used in web applications since it does not require native
database locks (making is scalable).

We've been working on a tutorial on Dbo that motivates the current
design and our ideas on future improvements:
http://www.webtoolkit.eu/wt/doc/tutorial/dbo/tutorial.html

> found that demonstrate how to use the DBO are just test frameworks and
> it is quite obvious that this is not how it was designed to be used,
> so is there an actual example somewhere that demonstrates its real
> use, or should I just create a pool of session objects as I was
> initially thinking?

See the blog/ example.

> Also, the createtables, does it destructively recreate the tables, as
> in deleting the existing data, or if the table already exists does it
> do nothing, or what if the table layout is different, does it do
> nothing, or does it create/remove columns as it needs, and is that
> destructive or not to the existing data, and is there a method to drop
> tables as well?

Currently it only naively tries to create all tables. It will either
entirely succeed or entirely fail (because of the transaction). It is
just there to get going quickly, but is not usable for migrating
schemas.

> You might look at the Python library SQLAlchemy, it handles all of
> this extremely well (and I have actually linked in Python into some of
> my C++ projects *just* so I could use sqlalchemy, it is that nice to
> use, although a slight bit of an overhead since it is, well, python).

I looked at SQL alchemy just recently, and I agree it deserves very
well the praise it receives! I would not mind Wt::Dbo being compared
with that library some day :-)

> I started looking at how DBO was implemented.
>
> In Cession.c:194, the parseSql function.  The parsing seems a bit
> heavy.  If you do not mind a requirement on a more recent version of

As you point out,, that check is wrong. It should read:

  std::size_t selectPos = sql.find("select ");
  if (selectPos != 0)
    throw std::logic_error("Session::query(): query should start with 'select '"
                           " (sql='" + sql + "'");

Thus even a boost::starts_with() would be more appropriate here.

The rest of the 'parsing' is indeed very ad-hoc, and especially when
start wanting to understand the queries better, an approach based on
Boost.Spirit will be preferred.

> Boost then I can Spirit'ify it, which can fill the final values with
> what they should be directly, instead of filling up temporaries and
> multiple finds over a string.  Also it mentions that it should start
> with select (would be nice to have a way to mutate values without
> needing to fetch them...  A counter is a good example of why this
> would be good), but the select test just looks to see if "select "

True, and there is in fact little reason why we require a "select " to
be there (but we can only bind result values if it is a select query).

> appears anywhere in the sql string at all, what if it was in a string
> blob, or someone had a cell name of myselect, that would mess it up
> pretty well.  If I wrote a full Spirit.Qi parser then there would be
> no such issue, but that requires a newer version of Boost then what
> your current requirements state.

I think with what we currently need to parse (and taking into account
the correction of above), there is little need for a more involved
parsing. We currently require boost 1.35 or higher. How would that
change if we want to use spirit for query parsing later on (since Wt
already uses boost.spirit) ?

> Also, SqlConnection:69, the line:
> typedef std::map<std::string, SqlStatement *> StatementMap;
> With potentially a lot of entries (as I plan to do, no point
> recreating often-used statements), would not boost::unordered_map be
> faster?  Perhaps even a ternary tree?  Boost.Spirit has a wonderful
> ternary tree that would also work quite well (wish it was in the main
> boost namespace, but boost does not have a generic tree container yet
> like it has unordered_map and such).
>
> At the very least, perhaps change it to boost::unordered_map (while
> including boost/unordered_map.hpp)?  It provides a speed boost over
> std::map and is identical to tr1::unordered_map (as it was modeled on
> boost's version).  I think boost's unordered_map is a using
> declaration of tr1::unordered_map if your compiler has tr1.

Note that the prepared statement map is maintained behind the scenes
automatically for you (when using Session::query() or Session::find()
methods), It also already takes into account later usage of a session
pool by not assuming that a statement that was already prepared will
be prepared in the next transaction because it may (in general) be
using a different connection.

Potentially, yes, at least it seems unordered_map will do the job. In
general, I do prefer to do optimizations like these based on profiling
run results...

Regards,
koen

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
witty-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to