/** INTERNAL: Write fields needed for insert into the template for with null values. */
  public void writeInsertFieldsIntoRow(AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    record.put(getField(), null);
  }
  /**
   * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain
   * the object. Check for batch + aggregation reading.
   */
  public Object valueFromRow(
      AbstractRecord row,
      JoinedAttributeManager joinManager,
      ObjectBuildingQuery query,
      AbstractSession executionSession)
      throws DatabaseException {
    Ref ref = (Ref) row.get(getField());

    if (ref == null) {
      return null;
    }

    Struct struct;
    try {
      ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession);
      java.sql.Connection connection =
          ((DatabaseAccessor) executionSession.getAccessor()).getConnection();
      struct =
          (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, executionSession, false);
    }
    AbstractRecord targetRow =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .buildRowFromStructure(struct);
    ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount();

    return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager);
  }
  /**
   * INTERNAL: This row is built for shallow insert which happens in case of bidirectional inserts.
   * The foreign keys must be set to null to avoid constraints.
   */
  public void writeFromObjectIntoRowForShallowInsertWithChangeRecord(
      ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    record.put(getField(), null);
  }
  /** INTERNAL: Get a value from the object and set that in the respective field of the row. */
  public void writeFromObjectIntoRow(
      Object object, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    Object referenceObject = getRealAttributeValueFromObject(object, session);

    if (referenceObject == null) {
      // Fix for 2730536, must put something in modify row, even if it is null.
      record.put(getField(), null);
      return;
    }

    Ref ref =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .getRef(referenceObject, session);

    record.put(getField(), ref);
  }
  /** INTERNAL: Get a value from the object and set that in the respective field of the row. */
  public void writeFromObjectIntoRowWithChangeRecord(
      ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    ObjectChangeSet changeSet =
        (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue();
    Object referenceObject = changeSet.getUnitOfWorkClone();

    if (referenceObject == null) {
      return;
    }

    Ref ref =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .getRef(referenceObject, session);

    record.put(getField(), ref);
  }