inheritance setups - attribute extensions won't randomly
collide with each other. [ticket:1488]
+ - UPDATE and DELETE do not support ORDER BY, LIMIT, OFFSET,
+ etc. in standard SQL. Query.update() and Query.delete()
+ now raise an exception if any of limit(), offset(),
+ order_by(), group_by(), or distinct() have been
+ called. [ticket:1487]
+
- Added AttributeExtension to sqlalchemy.orm.__all__
- Improved error message when query() is called with
"Otherwise, call %s() before limit() or offset() are applied." % (meth, meth)
)
+ def _no_select_modifiers(self, meth):
+ if not self._enable_assertions:
+ return
+ for attr, methname, notset in (
+ ('_limit', 'limit()', None),
+ ('_offset', 'offset()', None),
+ ('_order_by', 'order_by()', False),
+ ('_group_by', 'group_by()', False),
+ ('_distinct', 'distinct()', False),
+ ):
+ if getattr(self, attr) is not notset:
+ raise sa_exc.InvalidRequestError(
+ "Can't call Query.%s() when %s has been called" % (meth, methname)
+ )
+
def _get_options(self, populate_existing=None,
version_check=None,
only_load_props=None,
if synchronize_session not in [False, 'evaluate', 'fetch']:
raise sa_exc.ArgumentError("Valid strategies for session synchronization are False, 'evaluate' and 'fetch'")
+ self._no_select_modifiers("delete")
self = self.enable_eagerloads(False)
#TODO: updates of manytoone relations need to be converted to fk assignments
#TODO: cascades need handling.
+ self._no_select_modifiers("update")
if synchronize_session not in [False, 'evaluate', 'expire']:
raise sa_exc.ArgumentError("Valid strategies for session synchronization are False, 'evaluate' and 'expire'")
'user': relation(User, lazy=False, backref=backref('documents', lazy=True))
})
+ @testing.resolve_artifact_names
+ def test_illegal_operations(self):
+ s = create_session()
+
+ for q, mname in (
+ (s.query(User).limit(2), "limit"),
+ (s.query(User).offset(2), "offset"),
+ (s.query(User).limit(2).offset(2), "limit"),
+ (s.query(User).order_by(User.id), "order_by"),
+ (s.query(User).group_by(User.id), "group_by"),
+ (s.query(User).distinct(), "distinct")
+ ):
+ assert_raises_message(sa_exc.InvalidRequestError, r"Can't call Query.update\(\) when %s\(\) has been called" % mname, q.update, {'name':'ed'})
+ assert_raises_message(sa_exc.InvalidRequestError, r"Can't call Query.delete\(\) when %s\(\) has been called" % mname, q.delete)
+
+
@testing.resolve_artifact_names
def test_delete(self):
sess = create_session(bind=testing.db, autocommit=False)