def test_bad_sql(self): """ Regression for #11900: If a block wrapped by commit_on_success writes a transaction that can't be committed, that transaction should be rolled back. The bug is only visible using the psycopg2 backend, though the fix is generally a good idea. """ with self.assertRaises(IntegrityError): with transaction.commit_on_success(): cursor = connection.cursor() cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');") transaction.set_dirty() transaction.rollback()
def results_iter(self): """ Returns an iterator over the results from executing this query. """ resolve_columns = hasattr(self, 'resolve_columns') fields = None has_aggregate_select = bool(self.query.aggregate_select) # Set transaction dirty if we're using SELECT FOR UPDATE to ensure # a subsequent commit/rollback is executed, so any database locks # are released. if self.query.select_for_update and transaction.is_managed(self.using): transaction.set_dirty(self.using) for rows in self.execute_sql(MULTI): for row in rows: if resolve_columns: if fields is None: # We only set this up here because # related_select_fields isn't populated until # execute_sql() has been called. if self.query.select_fields: fields = self.query.select_fields + self.query.related_select_fields else: fields = self.query.model._meta.fields # If the field was deferred, exclude it from being passed # into `resolve_columns` because it wasn't selected. only_load = self.deferred_to_columns() if only_load: db_table = self.query.model._meta.db_table fields = [f for f in fields if db_table in only_load and f.column in only_load[db_table]] row = self.resolve_columns(row, fields) if has_aggregate_select: aggregate_start = len(self.query.extra_select) + len(self.query.select) aggregate_end = aggregate_start + len(self.query.aggregate_select) row = tuple(row[:aggregate_start]) + tuple([ self.query.resolve_aggregate(value, aggregate, self.connection) for (alias, aggregate), value in zip(self.query.aggregate_select.items(), row[aggregate_start:aggregate_end]) ]) + tuple(row[aggregate_end:]) yield row
def execute_bad_sql(self): cursor = connection.cursor() cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');") transaction.set_dirty()