summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sqlalchemy/engine/base.py2
-rw-r--r--lib/sqlalchemy/exceptions.py2
-rw-r--r--lib/sqlalchemy/orm/dynamic.py2
-rw-r--r--lib/sqlalchemy/orm/mapper.py2
-rw-r--r--lib/sqlalchemy/orm/session.py6
-rw-r--r--lib/sqlalchemy/orm/strategies.py4
-rw-r--r--lib/sqlalchemy/schema.py20
-rw-r--r--lib/sqlalchemy/sql/expression.py8
-rw-r--r--test/engine/bind.py59
9 files changed, 89 insertions, 16 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 733d77a69..2bbbf398d 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -484,7 +484,7 @@ class Compiled(object):
e = self.bind
if e is None:
- raise exceptions.InvalidRequestError("This Compiled object is not bound to any Engine or Connection.")
+ raise exceptions.UnboundExecutionError("This Compiled object is not bound to any Engine or Connection.")
return e._execute_compiled(self, multiparams, params)
def scalar(self, *multiparams, **params):
diff --git a/lib/sqlalchemy/exceptions.py b/lib/sqlalchemy/exceptions.py
index eda368d7c..7bac05c26 100644
--- a/lib/sqlalchemy/exceptions.py
+++ b/lib/sqlalchemy/exceptions.py
@@ -55,6 +55,8 @@ class NoSuchTableError(InvalidRequestError):
database, but the table doesn't exist.
"""
+class UnboundExecutionError(InvalidRequestError):
+ """SQL was attempted without a database connection to execute it on."""
class AssertionError(SQLAlchemyError):
"""Corresponds to internal state being detected in an invalid state."""
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py
index a5e1a8467..98702ecb0 100644
--- a/lib/sqlalchemy/orm/dynamic.py
+++ b/lib/sqlalchemy/orm/dynamic.py
@@ -128,7 +128,7 @@ class AppenderQuery(Query):
try:
sess = object_mapper(instance).get_session()
except exceptions.InvalidRequestError:
- raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (mapperutil.instance_str(instance), self.attr.key))
+ raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (mapperutil.instance_str(instance), self.attr.key))
return sess.query(self.attr.target_mapper).with_parent(instance, self.attr.key)
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 1489ef65e..b99e736b3 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -1555,7 +1555,7 @@ def _load_scalar_attributes(instance, attribute_names):
try:
session = mapper.get_session()
except exceptions.InvalidRequestError:
- raise exceptions.InvalidRequestError("Instance %s is not bound to a Session, and no contextual session is established; attribute refresh operation cannot proceed" % (instance.__class__))
+ raise exceptions.UnboundExecutionError("Instance %s is not bound to a Session, and no contextual session is established; attribute refresh operation cannot proceed" % (instance.__class__))
state = instance._state
if '_instance_key' in state.dict:
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index b689b2441..c75b78664 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -695,7 +695,7 @@ class Session(object):
if self.bind is not None:
return self.bind
else:
- raise exceptions.InvalidRequestError("This session is unbound to any Engine or Connection; specify a mapper to get_bind()")
+ raise exceptions.UnboundExecutionError("This session is unbound to any Engine or Connection; specify a mapper to get_bind()")
elif len(self.__binds):
if mapper is not None:
@@ -713,7 +713,7 @@ class Session(object):
if self.bind is not None:
return self.bind
elif mapper is None:
- raise exceptions.InvalidRequestError("Could not locate any mapper associated with SQL expression")
+ raise exceptions.UnboundExecutionError("Could not locate any mapper associated with SQL expression")
else:
if isinstance(mapper, type):
mapper = _class_mapper(mapper)
@@ -721,7 +721,7 @@ class Session(object):
mapper = mapper.compile()
e = mapper.mapped_table.bind
if e is None:
- raise exceptions.InvalidRequestError("Could not locate any Engine or Connection bound to mapper '%s'" % str(mapper))
+ raise exceptions.UnboundExecutionError("Could not locate any Engine or Connection bound to mapper '%s'" % str(mapper))
return e
def query(self, mapper_or_class, *addtl_entities, **kwargs):
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 908c43feb..3b3c86d1a 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -192,7 +192,7 @@ class LoadDeferredColumns(object):
session = sessionlib.object_session(self.instance)
if session is None:
- raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (self.instance.__class__, self.key))
+ raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (self.instance.__class__, self.key))
query = session.query(localparent)
if not self.optimizing_statement:
@@ -438,7 +438,7 @@ class LoadLazyAttribute(object):
try:
session = instance_mapper.get_session()
except exceptions.InvalidRequestError:
- raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key))
+ raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key))
q = session.query(prop.mapper).autoflush(False)
if self.path:
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 0d626397f..44dcb5755 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -1336,5 +1336,21 @@ class SchemaVisitor(visitors.ClauseVisitor):
def _bind_or_error(schemaitem):
bind = schemaitem.bind
if not bind:
- raise exceptions.InvalidRequestError("This SchemaItem is not connected to any Engine or Connection.")
- return bind \ No newline at end of file
+ name = schemaitem.__class__.__name__
+ label = getattr(schemaitem, 'fullname',
+ getattr(schemaitem, 'name', None))
+ if label:
+ item = '%s %r' % (name, label)
+ else:
+ item = name
+ if isinstance(schemaitem, MetaData):
+ bindable = "the %s's .bind" % name
+ else:
+ bindable = "this %s's .metadata.bind" % name
+
+ msg = ('The %s is not bound to an Engine or Connection. '
+ 'Execution can not proceed without a database to execute '
+ 'against. Either execute with an explicit connection or '
+ 'assign %s to enable implicit execution.') % (item, bindable)
+ raise exceptions.UnboundExecutionError(msg)
+ return bind
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 2e5797b34..ee867a2f9 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -1002,7 +1002,13 @@ class ClauseElement(object):
e = self.bind
if e is None:
- raise exceptions.InvalidRequestError("This Compiled object is not bound to any Engine or Connection.")
+ label = getattr(self, 'description', self.__class__.__name__)
+ msg = ('This %s is not bound to an Engine or Connection. '
+ 'Execution can not proceed without a database to execute '
+ 'against. Either execute with an explicit connection or '
+ 'bind the MetaData of the underlying tables to enable '
+ 'implicit execution.') % label
+ raise exceptions.UnboundExecutionError(msg)
return e.execute_clauseelement(self, multiparams, params)
def scalar(self, *multiparams, **params):
diff --git a/test/engine/bind.py b/test/engine/bind.py
index 7e716ba9d..c273bdb05 100644
--- a/test/engine/bind.py
+++ b/test/engine/bind.py
@@ -34,7 +34,6 @@ class BindTest(PersistTest):
for meth in [
metadata.create_all,
- table.exists,
metadata.drop_all,
table.create,
table.drop,
@@ -42,8 +41,53 @@ class BindTest(PersistTest):
try:
meth()
assert False
- except exceptions.InvalidRequestError, e:
- assert str(e) == "This SchemaItem is not connected to any Engine or Connection."
+ except exceptions.UnboundExecutionError, e:
+ self.assertEquals(
+ str(e),
+ "The MetaData "
+ "is not bound to an Engine or Connection. "
+ "Execution can not proceed without a database to execute "
+ "against. Either execute with an explicit connection or "
+ "assign the MetaData's .bind to enable implicit execution.")
+
+ for meth in [
+ table.exists,
+ # future:
+ #table.create,
+ #table.drop,
+ ]:
+ try:
+ meth()
+ assert False
+ except exceptions.UnboundExecutionError, e:
+ self.assertEquals(
+ str(e),
+ "The Table 'test_table' "
+ "is not bound to an Engine or Connection. "
+ "Execution can not proceed without a database to execute "
+ "against. Either execute with an explicit connection or "
+ "assign this Table's .metadata.bind to enable implicit "
+ "execution.")
+
+ @testing.future
+ def test_create_drop_err2(self):
+ for meth in [
+ table.exists,
+ table.create,
+ table.drop,
+ ]:
+ try:
+ meth()
+ assert False
+ except exceptions.UnboundExecutionError, e:
+ self.assertEquals(
+ str(e),
+ "The Table 'test_table' "
+ "is not bound to an Engine or Connection. "
+ "Execution can not proceed without a database to execute "
+ "against. Either execute with an explicit connection or "
+ "assign this Table's .metadata.bind to enable implicit "
+ "execution.")
@testing.uses_deprecated('//connect')
def test_create_drop_bound(self):
@@ -157,8 +201,13 @@ class BindTest(PersistTest):
assert e.bind is None
e.execute()
assert False
- except exceptions.InvalidRequestError, e:
- assert str(e) == "This Compiled object is not bound to any Engine or Connection."
+ except exceptions.UnboundExecutionError, e:
+ assert str(e).endswith(
+ 'is not bound to an Engine or '
+ 'Connection. Execution can not proceed without a '
+ 'database to execute against. Either execute with '
+ 'an explicit connection or bind the MetaData of the '
+ 'underlying tables to enable implicit execution.')
finally:
if isinstance(bind, engine.Connection):