+static struct ovsdb_error * WARN_UNUSED_RESULT
+determine_changes(struct ovsdb_txn *txn, struct ovsdb_txn_row *txn_row)
+{
+ struct ovsdb_table *table;
+
+ table = (txn_row->old ? txn_row->old : txn_row->new)->table;
+ if (txn_row->old && txn_row->new) {
+ struct shash_node *node;
+ bool changed = false;
+
+ SHASH_FOR_EACH (node, &table->schema->columns) {
+ const struct ovsdb_column *column = node->data;
+ const struct ovsdb_type *type = &column->type;
+ unsigned int idx = column->index;
+
+ if (!ovsdb_datum_equals(&txn_row->old->fields[idx],
+ &txn_row->new->fields[idx],
+ type)) {
+ bitmap_set1(txn_row->changed, idx);
+ changed = true;
+ }
+ }
+
+ if (!changed) {
+ /* Nothing actually changed in this row, so drop it. */
+ ovsdb_txn_row_abort(txn, txn_row);
+ }
+ } else {
+ bitmap_set_multiple(txn_row->changed, 0,
+ shash_count(&table->schema->columns), 1);
+ }
+
+ return NULL;
+}
+