/**
  * @return Numeric meta data information for the channel or <code>null</code>
  * @throws Exception on error
  */
 private Display determineDisplay() throws Exception {
   // Try numeric meta data
   final PreparedStatement statement =
       reader.getConnection().prepareStatement(reader.getSQL().numeric_meta_sel_by_channel);
   try {
     statement.setInt(1, channel_id);
     final ResultSet result = statement.executeQuery();
     if (result.next()) {
       final NumberFormat format = NumberFormats.format(result.getInt(7)); // prec
       return ValueFactory.newDisplay(
           result.getDouble(1), // lowerDisplayLimit
           result.getDouble(5), // lowerAlarmLimit
           result.getDouble(3), // lowerWarningLimit
           result.getString(8), // units
           format, // numberFormat
           result.getDouble(4), // upperWarningLimit
           result.getDouble(6), // upperAlarmLimit
           result.getDouble(2), // upperDisplayLimit
           result.getDouble(1), // lowerCtrlLimit
           result.getDouble(2)); // upperCtrlLimit
     }
   } finally {
     statement.close();
   }
   // No numeric display meta data
   return null;
 }
  Object calculateImpl(final String newName) {
    // If the name does not match, disconnect and connect
    if (!Objects.equals(newName, previousName)) {
      if (currentExpressions != null) {
        for (DesiredRateExpression<?> desiredRateExpression : currentExpressions) {
          if (desiredRateExpression != null) {
            getDirector().disconnectReadExpression(desiredRateExpression);
          }
        }
      }

      List<DesiredRateExpression<?>> newExpressions = new ArrayList<>();
      if (newName != null) {
        newExpressions.addAll(Collections.nCopies(3, (DesiredRateExpression<?>) null));
      }

      // Connect new expressions
      if (newName != null) {
        DesiredRateExpression<?> newExpression = channel(newName, Object.class);
        getDirector().disconnectReadExpression(newExpression);
        newExpressions.set(0, newExpression);
        newExpression = channel(newName + ".LLIM", Object.class);
        getDirector().disconnectReadExpression(newExpression);
        newExpressions.set(1, newExpression);
        newExpression = channel(newName + ".ULIM", Object.class);
        getDirector().disconnectReadExpression(newExpression);
        newExpressions.set(2, newExpression);
      }

      previousName = newName;
      currentExpressions = newExpressions;
    }

    // No return value
    if (newName == null) {
      return null;
    }

    // Extract values
    VNumberArray array = (VNumberArray) currentExpressions.get(0).getFunction().readValue();
    VNumber lowerRange = (VNumber) currentExpressions.get(1).getFunction().readValue();
    VNumber upperRange = (VNumber) currentExpressions.get(2).getFunction().readValue();
    if (array == null || lowerRange == null || upperRange == null) {
      return null;
    }

    return ValueFactory.newVNumberArray(
        array.getData(),
        array.getSizes(),
        Arrays.asList(
            ValueFactory.newDisplay(
                VTableFactory.range(
                        lowerRange.getValue().doubleValue(), upperRange.getValue().doubleValue())
                    .createListNumber(array.getSizes().getInt(0) + 1),
                "")),
        array,
        array,
        array);
  }
 /**
  * @param reader RDBArchiveReader
  * @param channel_id ID of channel
  * @throws Exception on error
  */
 AbstractRDBValueIterator(final RDBArchiveReader reader, final int channel_id) throws Exception {
   this.reader = reader;
   this.channel_id = channel_id;
   try {
     this.display = determineDisplay();
     this.labels = determineLabels();
   } catch (final Exception ex) {
     // Set iterator to empty
     close();
     if (!RDBArchiveReader.isCancellation(ex)) throw ex;
     // Else: Not a real error, return empty iterator
   }
   if (labels == null && display == null)
     display =
         ValueFactory.newDisplay(
             0.0, 0.0, 0.0, "", NumberFormats.format(0), 0.0, 0.0, 10.0, 0.0, 10.0);
 }