Bug #9465
Emit the right errors when binding datasets
0%
History
#1 Updated by Andrei Plugaru over 1 year ago
There are some edge cases for binding datasets that throw errors in 4GL, however FWD doesn't handle at all these cases.
The cases I have investigated so far are when either the dataset on the caller or called side is REFERENCE-ONLY and BIND keyword is not used on both sides. The errors that should be thrown are: 13015, 13161, 13010, 13012.
#2 Updated by Andrei Plugaru over 1 year ago
I have found a useful comment in DataSet.isCompatibleWith which clarifies why my initial attempt to throw the error using ErrorManager.recordOrThrowError failied:
// The use of ErrorManager.recordOrThrowError() is not very effective here because in FWD
// the bind is done after the called procedure has already started. The ErrorManager will
// stop only the execution of the called procedure/method. In 4GL the associate / bind
// operation is performed in caller and, in case of errors the caller is stopped before
// the invocation of the called method
TransactionManager.triggerErrorInCaller(12314, ErrorManager.replaceTokens(12314));
So, switching to TransactionManager.triggerErrorInCaller should allow me to suppress the error when called with no-error and further check if the thrown error is the right one using support.test.AssertExt:Error.
#3 Updated by Andrei Plugaru over 1 year ago
Committed 15 tests to tests.dataset.parameter.inout.TestHandleDatasetBind. Currently 4 of them fail all regarding the errors not being thrown. However, in the whole test suite for datasets 37/84 tests fail.
Created task branch 9465a to work on the error managing.
#4 Updated by Andrei Plugaru over 1 year ago
13012 should now be emitted in the right situation with the appropriate message. The logic for emitting this situation existed, however I have improved it by:
- modified the condition for emitting the error to better match 4GL
- used
TransactionManager.triggerErrorInCallerinstead ofErrorManager.recordOrThrowError - used
EnvironmentOps.getSourceName(new integer(1))in order to get the procedure name where the dataset is defined.
I have committed these changes in 9465a/15619. However, these changes don't improve the number of passing unit tests, as those tests also depend on the other error cases to be handled right.
#5 Updated by Andrei Plugaru over 1 year ago
- When the datasets are the same. I suspect that in this situation in 4GL, the binding doesn't actually happen. This is only a hypothesis, as I am not sure how to test this. In FWD, however, the binding is done, so a
reference-onlydataset is bound to areference-onlyone, which is a little strange in my opinion :) - When the datasets are different. In this case, 4GL throws an error:
12765. It seems that in FWD we don't emit this error at all.
Currently, I am thinking that StaticDataSet.bind is a good place to have some validation for these situations. So, I am thinking to first check if both datasets are reference-only . If that is the case and the datasets are the same, just return from that method. On the other hand, if both datasets are reference-only and they are different datasets, throw 12765.
#6 Updated by Andrei Plugaru over 1 year ago
- Status changed from New to WIP
#7 Updated by Andrei Plugaru over 1 year ago
- File 9465_same_ref_dataset.p
added - File 9465_different_ref_dataset.p
added
Here are the testcases I used to test #9465-5.
#8 Updated by Andrei Plugaru over 1 year ago
9265a/15620. Main changes:
- Implemented what I described in #9465-5
- Validate the case when the BIND option is set on only one side in
DataSet.validateDataSetParamand emit the right errors(13015,13161)
As a result, all tests written by me pass and also 1 more test that was already written passes. However, even though the number of new tests(from the previously written ones) is low, it seems that the previously written tests now fail later, so there is an improvement on that.
#9 Updated by Andrei Plugaru over 1 year ago
While running the dataset unit tests, I came across this exception in server.log I would also want to investigate:
Caused by: java.lang.ClassCastException: class com.goldencode.p2j.persist.TempTableBuilder cannot be cast to class com.goldencode.p2j.persist.DataSet (com.goldencode.p2j.persist.TempTableBuilder and com.goldencode.p2j.persist.DataSet are in unnamed module of loader 'app')
at com.goldencode.p2j.persist.DataSetParameter.<init>(DataSetParameter.java:353)
at com.goldencode.p2j.persist.DataSetParameter.<init>(DataSetParameter.java:334)
at com.goldencode.p2j.persist.DataSetParameter.<init>(DataSetParameter.java:304)
at com.goldencode.dataset.tests.dataset.parameter.output.TestOutputDynamicDsInDynamicProc.lambda$passInvalidDataset$33(TestOutputDynamicDsInDynamicProc.java:350)
at com.goldencode.p2j.util.ErrorManager.silentWorker(ErrorManager.java:4363)
at com.goldencode.p2j.util.ErrorManager.silent(ErrorManager.java:724)
at com.goldencode.dataset.tests.dataset.parameter.output.TestOutputDynamicDsInDynamicProc.lambda$passInvalidDataset$35(TestOutputDynamicDsInDynamicProc.java:350)
at com.goldencode.p2j.util.Block.body(Block.java:636)
at com.goldencode.p2j.util.BlockManager.processBody(BlockManager.java:9336)
at com.goldencode.p2j.util.BlockManager.topLevelBlock(BlockManager.java:8960)
at com.goldencode.p2j.util.BlockManager.internalProcedure(BlockManager.java:888)
at com.goldencode.p2j.util.BlockManager.internalProcedure(BlockManager.java:861)
at com.goldencode.dataset.tests.dataset.parameter.output.TestOutputDynamicDsInDynamicProc.passInvalidDataset(TestOutputDynamicDsInDynamicProc.java:348)
at com.goldencode.dataset.tests.dataset.parameter.output.TestOutputDynamicDsInDynamicProcMethodAccess.invoke(Unknown Source)
at com.goldencode.p2j.util.ControlFlowOps$InternalEntryCaller.invokeImpl(ControlFlowOps.java:9705)
at com.goldencode.p2j.util.ControlFlowOps$InternalEntryCaller.invoke(ControlFlowOps.java:9661)
at com.goldencode.p2j.util.ControlFlowOps.invokeLegacyMethod(ControlFlowOps.java:5215)
... 24 more
#10 Updated by Andrei Plugaru over 1 year ago
- reviewer Ovidiu Maxiniuc added
I further investigate the exception presented in #9465-9. Up until now, in the constructor for DataSetParameter we made the (logical) assumption that the received handle is for a DataSet and we made an unchecked cast to DataSet. It seems that 4GL, at compile-time, allows the handle to be for a different object, however fails at runtime with 12314 error. In order to solve this error, I added this:
=== modified file 'src/com/goldencode/p2j/persist/DataSetParameter.java' --- old/src/com/goldencode/p2j/persist/DataSetParameter.java 2024-08-13 13:53:45 +0000 +++ new/src/com/goldencode/p2j/persist/DataSetParameter.java 2024-12-18 14:58:48 +0000 @@ -349,8 +349,17 @@ public DataSetParameter(handle dsHandle, EnumSet<ParameterOption> options, boolean input, boolean output) { BufferManager.registerScopeable(null); - - this.originalDataSet = (DataSet)dsHandle.getResource(); + WrappedResource wrappedResource = dsHandle.getResource(); + + if (wrappedResource != null && !(wrappedResource instanceof DataSet)) + { + ErrorManager.recordOrThrowError(12314); + } + else + { + this.originalDataSet = (DataSet) wrappedResource; + } + this.dataset = dsHandle; this.options = options; // TODO: check default value for mode if ParameterOption.NONE is passed in this.input = input;
Apart from this, in 9465a/15621, I fixed some small issue that appeared from my last changes and also changed another instance of ErrorManager.recordOrThrowError to TransactionManager.triggerErrorInCaller. The current changes reduce the number of failing tests to 28/85.
Ovidiu, even though I am still working on this, can you please take a quick look over my current changes, just to check if there isn't something fundamentally wrong with what I have done so far.