Loop End (Column Append)

There is a bug which comes up with alarming regularity in my workflows where the output from the "Loop End (Column Append)" node has "(Iter #50) (Iter #100)" sufixes or similar added to the column names.

I can see no logical reason for why this sometimes happens, as there are not duplicated column names, and its that all the columns have the same iteration number appended.


I can confirm this bug, although i have only encountered it once yet.

I also can cofirm this bug with "Loop End (Column Append)" node:

COL1 (Iter #50) (Iter #100) (Iter #150) (Iter #200) (Iter #250)

This should fix it. (in LoopEndJoinNodeModel of course) Could also be a tiny bit faster that way. Not that on would try joining >=50 columns for performance reasons...

protected BufferedDataTable[] execute(final BufferedDataTable[] inData, final ExecutionContext exec) throws Exception {
  // ...
  if (hasSameRowsInEachIteration) {
  // ...
    if (isCacheNew) {
      ExecutionContext ctx = ...
      cacheTable(ctx); // CHANGED

private BufferedDataTable copy(final BufferedDataTable table, final ExecutionContext exec) throws CanceledExecutionException {
  DataColumnSpec[] colSpecs = new DataColumnSpec[table.getDataTableSpec().getNumColumns()];
  int i = 0;
  for (DataColumnSpec cs : table.getDataTableSpec()) { ... }
  return unsafeCopy(table, new DataTableSpec(colSpecs), exec); // Just refactored

// Replaces copy() where it was used to cache
private void cacheTable(final ExecutionContext exec) throws CanceledExecutionException {
  // possibly add null check?
  specs = m_currentAppendTable.getDataTableSpec(); // Don't need to check
  m_currentAppendTable = unsafeCopy(m_currentAppendTable, specs, exec);

// Refactored former second half of copy()
private BufferedDataTable unsafeCopy(final BufferedDataTable table, final DataTableSpec specs, final ExecutionContext exec) throws CanceledExecutionException {
  BufferedDataContainer container = exec.createDataContainer(specs);
  int i = 0;
  final double rowCount = table.getRowCount();
  for (DataRow r : table) { ... }
  return container.getTable();