/** This method updates the inverse columns of a 1-M related object with the given oid. */
  private void updateInverse(
      StoreContext ctx,
      Object inverse,
      ClassMapping rel,
      RowManager rm,
      OpenJPAStateManager sm,
      int idx)
      throws SQLException {
    OpenJPAStateManager invsm = RelationStrategies.getStateManager(inverse, ctx);
    if (invsm == null) return;

    ValueMapping elem = field.getElementMapping();
    ForeignKey fk = elem.getForeignKey();
    ColumnIO io = elem.getColumnIO();
    Column order = field.getOrderColumn();

    int action;
    boolean writeable;
    boolean orderWriteable;
    if (invsm.isNew() && !invsm.isFlushed()) {
      // no need to null inverse columns of new instance
      if (sm == null || sm.isDeleted()) return;
      writeable = io.isAnyInsertable(fk, false);
      orderWriteable = _orderInsert;
      action = Row.ACTION_INSERT;
    } else if (invsm.isDeleted()) {
      // no need to null inverse columns of deleted instance
      if (invsm.isFlushed() || sm == null || !sm.isDeleted()) return;
      writeable = true;
      orderWriteable = false;
      action = Row.ACTION_DELETE;
    } else {
      if (sm != null && sm.isDeleted()) sm = null;
      writeable = io.isAnyUpdatable(fk, sm == null);
      orderWriteable = field.getOrderColumnIO().isUpdatable(order, sm == null);
      action = Row.ACTION_UPDATE;
    }
    if (!writeable && !orderWriteable) return;

    assertInversable();

    // if this is an update, this might be the only mod to the row, so
    // make sure the where condition is set
    Row row = rm.getRow(fk.getTable(), action, invsm, true);
    if (action == Row.ACTION_UPDATE) row.wherePrimaryKey(invsm);

    // update the inverse pointer with our oid value
    if (writeable) row.setForeignKey(fk, io, sm);
    if (orderWriteable) row.setInt(order, idx);
  }