def _emit_update_statements(base_mapper, uowtransaction, cached_connections, mapper, table, update): """Emit UPDATE statements corresponding to value lists collected by _collect_update_commands().""" needs_version_id = mapper.version_id_col is not None and \ table.c.contains_column(mapper.version_id_col) def update_stmt(): clause = sql.and_() for col in mapper._pks_by_table[table]: clause.clauses.append(col == sql.bindparam(col._label, type_=col.type)) if needs_version_id: clause.clauses.append(mapper.version_id_col ==\ sql.bindparam(mapper.version_id_col._label, type_=col.type)) return table.update(clause) statement = base_mapper._memo(('update', table), update_stmt) rows = 0 for state, state_dict, params, mapper, \ connection, value_params in update: if value_params: c = connection.execute( statement.values(value_params), params) else: c = cached_connections[connection].\ execute(statement, params) _postfetch( mapper, uowtransaction, table, state, state_dict, c.context.prefetch_cols, c.context.postfetch_cols, c.context.compiled_parameters[0], value_params) rows += c.rowcount if connection.dialect.supports_sane_rowcount: if rows != len(update): raise orm_exc.StaleDataError( "UPDATE statement on table '%s' expected to " "update %d row(s); %d were matched." % (table.description, len(update), rows)) elif needs_version_id: util.warn("Dialect %s does not support updated rowcount " "- versioning cannot be verified." % c.dialect.dialect_description, stacklevel=12)
def _emit_delete_statements(base_mapper, uowtransaction, cached_connections, mapper, table, delete): """Emit DELETE statements corresponding to value lists collected by _collect_delete_commands().""" need_version_id = mapper.version_id_col is not None and \ table.c.contains_column(mapper.version_id_col) def delete_stmt(): clause = sql.and_() for col in mapper._pks_by_table[table]: clause.clauses.append( col == sql.bindparam(col.key, type_=col.type)) if need_version_id: clause.clauses.append( mapper.version_id_col == sql.bindparam( mapper.version_id_col.key, type_=mapper.version_id_col.type ) ) return table.delete(clause) for connection, del_objects in delete.iteritems(): statement = base_mapper._memo(('delete', table), delete_stmt) rows = -1 connection = cached_connections[connection] if need_version_id and \ not connection.dialect.supports_sane_multi_rowcount: # TODO: need test coverage for this [ticket:1761] if connection.dialect.supports_sane_rowcount: rows = 0 # execute deletes individually so that versioned # rows can be verified for params in del_objects: c = connection.execute(statement, params) rows += c.rowcount else: util.warn( "Dialect %s does not support deleted rowcount " "- versioning cannot be verified." % connection.dialect.dialect_description, stacklevel=12) connection.execute(statement, del_objects) else: c = connection.execute(statement, del_objects) if connection.dialect.supports_sane_multi_rowcount: rows = c.rowcount if rows != -1 and rows != len(del_objects): raise orm_exc.StaleDataError( "DELETE statement on table '%s' expected to " "delete %d row(s); %d were matched." % (table.description, len(del_objects), c.rowcount) )
def _run_crud(self, uowcommit, secondary_insert, secondary_update, secondary_delete): connection = uowcommit.transaction.connection(self.mapper) if secondary_delete: associationrow = secondary_delete[0] statement = self.secondary.delete(sql.and_(*[ c == sql.bindparam(c.key, type_=c.type) for c in self.secondary.c if c.key in associationrow ])) result = connection.execute(statement, secondary_delete) if result.supports_sane_multi_rowcount() and \ result.rowcount != len(secondary_delete): raise exc.StaleDataError( "DELETE statement on table '%s' expected to delete %d row(s); " "Only %d were matched." % (self.secondary.description, len(secondary_delete), result.rowcount) ) if secondary_update: associationrow = secondary_update[0] statement = self.secondary.update(sql.and_(*[ c == sql.bindparam("old_" + c.key, type_=c.type) for c in self.secondary.c if c.key in associationrow ])) result = connection.execute(statement, secondary_update) if result.supports_sane_multi_rowcount() and \ result.rowcount != len(secondary_update): raise exc.StaleDataError( "UPDATE statement on table '%s' expected to update %d row(s); " "Only %d were matched." % (self.secondary.description, len(secondary_update), result.rowcount) ) if secondary_insert: statement = self.secondary.insert() connection.execute(statement, secondary_insert)
def test_staledata_error_caught(self): e = exc.StaleDataError() self.assertIsNone(self._decorated_function(1, e))