Re: [sqlalchemy] Slightly confusing error when session set up incorrectly

2011-06-28 Thread Michael Bayer

On Jun 28, 2011, at 9:34 PM, Ben Sizer wrote:

> Hello all,
> 
> When using sqlalchemy 0.7 with sqlite, if I enter the path URI
> incorrectly I will get an error like this:
> 
>OperationalError: (OperationalError) unable to open database file
> None None
> 
> What does the "None None" signify? Would it be possible to change this
> exception to be a bit more descriptive and a little less cryptic? eg.
> Include the URI that failed?

That error is raised by SQLite and we just propagate it out.  DBAPI does not 
have any standardized error codes and there's no clean way for us to "wrap" the 
exception into something new without concealing what the original exception was 
- we "wrap" it in a sqlalchemy.exc.DBAPIError so that an application can catch 
DBAPI exceptions in a generic way (otherwise you'd have to import 
sqlite3.OperationalError), but other than that we don't mess with it.Python 
3 allows exceptions to be "chained" but Python 2 doesn't have a terrific way to 
do it.   The None None is part of DBAPIError's behavior, it illustrates the 
statement and parameters which took place.We can consider not displaying 
this if the statement is None, i agree it's not pleasing to the eye but nobody 
has ever mentioned it before.

> 
> Additionally, I notice that sqlalchemy doesn't attempt to make an
> actual connection to the database until you perform the first query.
> That means that code like this will appear to work:
> 
>Session = sessionmaker()
>engine = create_engine('sqlite:///%s' % "invalid_filename")
>Base.metadata.bind = engine
>db_session = Session(bind=engine)
> 
> Yet eventually, when you make a query within your app code, you'll get
> an exception because the URI was wrong. In my case, due to the
> exception text being a little vague, I thought this was a problem with
> my app's db access patterns (as I do things like delete the database
> file manually) when it was just a problem with the initial connection.

That is true, all connections/transactions are lazy initializing.Sorry this 
was a surprise, though I don't think this is much of an issue once you get used 
to dealing with lazy initializing objects.

The formal pattern at play with SQLAlchemy's connection pool, Engine and 
Session behavior is called the Proxy Pattern, a decent description is at 
http://sourcemaking.com/design_patterns/proxy .

> 
> I found a way to trigger this error earlier, by issuing
> engine.connect() in the above routine, but I notice that this isn't
> explicitly documented in "Using The Session" (http://
> www.sqlalchemy.org/docs/orm/session.html).

the lazy initializing behavior of the Session is documented:

http://www.sqlalchemy.org/docs/orm/session.html#unitofwork-transaction

But that doesn't have anything to do with the Engine, which is its own thing.   
As far as the Engine, the docs currently use the term "connect" in conjunction 
with create_engine() which is for simplicities' sake, but is technically 
inaccurate, perhaps come up with some term other than "connect", "configure a 
connection source" perhaps.   We can add an explicit sentence to the top of 
http://www.sqlalchemy.org/docs/core/connections.html.


> I expect I am not unusual
> in wanting an error in session configuration to fail as soon as
> possible,

Nobody has ever raised this issue before to my recollection.  I'm not sure 
lots of users are phased whether the stack trace starts at the 
Session.configure() line or if it starts later as soon as their first unit test 
tries to hit the database - they get the same error, see that the connection 
URL is bad, and fix it.

> so if it's not possible or efficient to do this
> automatically as part of creating the session,

I suppose inefficiency is the only issue but its so unnecessarily inefficient, 
most people would consider it to be wrong behavior.A Session may be 
configured such that depending on what's requested of it, it can connect to any 
number of different engines - connecting to several/dozens/hundreds of engines 
unconditionally upon construction is not an option. Its usage is such that 
once rollback or commit is called, it's essentially dormant, not using any 
resources, until it's called upon again to do something.   The lazy 
initialization model makes the Session very easy to use as they are cheap to 
create and only establish state with the database as needed, release it as soon 
as it's not.It's a very user-friendly usage model, as long as one is 
comfortable with lazy initialization.  

> perhaps this part of
> the docs could be clarified so that new users in future will know
> exactly what to call to test this configuration?

Feel free to suggest what verbiage you're looking for, it's not hitting me 
strongly what the confusion is - the application failed to connect, you get an 
error describing the problem, the stack trace shows it happened upon connect() 
inside the pool. An application should always have unit

[sqlalchemy] Slightly confusing error when session set up incorrectly

2011-06-28 Thread Ben Sizer
Hello all,

When using sqlalchemy 0.7 with sqlite, if I enter the path URI
incorrectly I will get an error like this:

OperationalError: (OperationalError) unable to open database file
None None

What does the "None None" signify? Would it be possible to change this
exception to be a bit more descriptive and a little less cryptic? eg.
Include the URI that failed?

Additionally, I notice that sqlalchemy doesn't attempt to make an
actual connection to the database until you perform the first query.
That means that code like this will appear to work:

Session = sessionmaker()
engine = create_engine('sqlite:///%s' % "invalid_filename")
Base.metadata.bind = engine
db_session = Session(bind=engine)

Yet eventually, when you make a query within your app code, you'll get
an exception because the URI was wrong. In my case, due to the
exception text being a little vague, I thought this was a problem with
my app's db access patterns (as I do things like delete the database
file manually) when it was just a problem with the initial connection.

I found a way to trigger this error earlier, by issuing
engine.connect() in the above routine, but I notice that this isn't
explicitly documented in "Using The Session" (http://
www.sqlalchemy.org/docs/orm/session.html). I expect I am not unusual
in wanting an error in session configuration to fail as soon as
possible, so if it's not possible or efficient to do this
automatically as part of creating the session, perhaps this part of
the docs could be clarified so that new users in future will know
exactly what to call to test this configuration? (In fact, this part
of the docs is a bit confusing in general - there seem to be a fair
few permutations of how to approach it - pass arguments to
sessionmaker? or to Session.configure? or to Session's constructor? -
and it's not clear why they all have to exist.)

--
Ben Sizer

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.