Project

General

Profile

Bug #8101

Issue with temp-table defined as reference-only

Added by Theodoros Theodorou over 2 years ago. Updated over 2 years ago.

Status:
Closed
Priority:
Normal
Target version:
-
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
reviewer:
production:
No
env_name:
topics:

History

#1 Updated by Theodoros Theodorou over 2 years ago

An exception is thrown when TestCodepageConversions.cls is executed regarding temp-tables.

Ovidiu Maxiniuc wrote:

The problem is that, in TestCodepageConversions, the CodepageMatch temp-table is defined as reference-only. It cannot be used until it is bound to a 'true' temp-table. This is done by passing that table as a parameter with BIND option.

I reviewed at the code and there are some pieces of code which were temporarily commented out because it regresses other BIND and REFERENCE-ONLY cases.

The good part is that we can and hopefully will use this testcase to adjust the code to make all these cases to work.

#2 Updated by Theodoros Theodorou over 2 years ago

I think I found the issue. In the TemporaryBuffer.java

/**
 * Open a new buffer scope for this record buffer.  Open a new multiplex
 * scope and assign a multiplex ID the first time we are invoked for a
 * buffer instance.
 */
protected void openScope() {
   BufferManager.registerScopeable(bufferManager);

   if (referenceOnly) return;

When I comment out the if (referenceOnly) return; it works, although I am not sure if I should remove it and if this is the right approach to the solution.

#3 Updated by Greg Shah over 2 years ago

This isn't likely to be a FWD issue. Don't make edits there yet. It is more likely a dependency on the 4GL code side that is not being processed as expected.

Please post the details of the failure itself and what specific 4GL code fails. Marian can help explain how that code is supposed to work.

#4 Updated by Theodoros Theodorou over 2 years ago

The failure comes from the line boolean hasRecords = local.nonEmptyTableFlags.contains(multiplexID); in TemporaryBuffer.java. It throws a NullPointerException because the private Integer multiplexID is null.

I created a small dummy test based on TestCodepageConversions.cls to track down the issue.

using Progress.Lang.*.
using OpenEdge.Core.Assert from propath.
using support.test.* from propath.

routine-level on error undo, throw.

class examples.MyTest:

  define temp-table TempTableReference reference-only
      field src as integer.

  define static temp-table StaticTempTable
      field src as integer.

  method public static void emptyStaticTempTable(output table StaticTempTable bind):
    empty temp-table StaticTempTable.
  end.

  @Test.
  method public void testTempTable():
    empty temp-table StaticTempTable.
    emptyStaticTempTable(output table TempTableReference bind).
  end method.

end class.

This test works with OE. With FWD, it fails at empty temp-table StaticTempTable inside the emptyStaticTempTable() method.

As I understand, the output table TempTableReference bind fails in FWD because define temp-table TempTableReference is reference-only. In TemporaryBuffer.openScope() the line if (referenceOnly) return; blocks the execution of TemporaryBuffer.openMultiplexScope() which sets the value of private Integer multiplexID.

#5 Updated by Theodoros Theodorou over 2 years ago

The above 4gl code generates the following java code.

private static ContextLocal<Statictemptable_1_1.Buf> statictemptable = new ContextLocal<Statictemptable_1_1.Buf>()
{
   protected Statictemptable_1_1.Buf initialValue()
   {
      return TemporaryBuffer.define(MyTest.class, Statictemptable_1_1.Buf.class, "statictemptable", "StaticTempTable", false);
   }
};

private Temptablereference_1_1.Buf temptablereference = TemporaryBuffer.define(MyTest.class, Temptablereference_1_1.Buf.class, "temptablereference", "TempTableReference", false);
...
public static void emptyStaticTempTable(final OutputTableParameter statictemptableBuf2)
{
   ObjectOps.load(MyTest.class);

   internalProcedure(MyTest.class, "emptyStaticTempTable", new Block((Init) () -> 
   {
      TemporaryBuffer.associate(statictemptableBuf2, statictemptable.get(), ParameterOption.BIND);
   }, 
   (Body) () -> 
   {
      statictemptable.get().deleteAll();
   }));
}

public void testTempTable() // this is the entry point
{
   internalProcedure(MyTest.class, this, "testTempTable", new Block((Body) () -> 
   {
      statictemptable.get().deleteAll();
      emptyStaticTempTable(new OutputTableParameter(temptablereference, ParameterOption.BIND));
   }));
}

statictemptable.get() inside testTempTable() and in emptyStaticTempTable() are different. This is because TemporaryBuffer.associate(...); is called. As I understand, temptablereference is the reference which should point to statictemptable. I think statictemptable shouldn't be modified inside TemporaryBuffer.associate(). I tried to dig into TemporaryBuffer.associateImpl() but the code is too complicated. Can someone have a look at this?

#7 Updated by Constantin Asofiei over 2 years ago

  • Status changed from New to Closed
  • Assignee changed from Theodoros Theodorou to Constantin Asofiei
  • % Done changed from 0 to 100

Fixed in trunk rev 15028 via 8329a.

Also available in: Atom PDF