Bug #9034
FindQuery unique fails in a self join context
100%
History
#2 Updated by Artur Școlnic almost 2 years ago
This ticket is derived from #8912-188.
#3 Updated by Artur Școlnic almost 2 years ago
define temp-table tt no-undo
field f1 as character
index idx is primary unique f1.
create tt.
assign
tt.f1 = ?.
create tt.
assign
tt.f1 = ?.
define buffer btt for tt.
for each tt on error undo, throw:
find btt where btt.f1 = tt.f1 no-error.
if ambiguous btt then do:
message "ambiguous".
end.
end.
message "finished".
In 4GL the program above outputs
ambiguous 2 times and then finished.In FWD, only
finished is displayed.
If instead of the find btt where btt.f1 = tt.f1, we use find btt of tt, there is also a conversion issue. Instead of the field f1, the recid is used in the where clause of the find query.
First I will investigate the runtime issue.
#4 Updated by Artur Școlnic almost 2 years ago
In this case, DirectAccessHelper.findByUniqueIndex() is used, it assumes that if there is a unique index, only one record can be accessed with the same value for the indexed field. getUniqueRow is used and the response is returned, I added a simple check to see if there are more results after the first record is accessed
if( driver.nextPrimaryKey(tableName, response.getRecid().intValue(), true) != 0){
throw new DirectAccessException("Error direct accessing for finding record by unique index. More than one records found.");
}
The test case in #9034-3 matches the behavior in 4GL with this change.
#5 Updated by Artur Școlnic almost 2 years ago
- Status changed from WIP to Review
I committed a better version of the change from #9034-4 to 9034a, I did some initial testing and it looks ok.
The conversion fix just omits the transforming of the of clause for non meta tables, I committed it to 9034b. For testing, I converted some test cases, the conversion went fine.
Both task branches are ready for review.
#6 Updated by Artur Școlnic almost 2 years ago
Using 9034b this query
define buffer btt for tt.
...
find btt of tt no-error.
is converted as
silent(() -> new FindQuery(btt, (String) null, null, "btt.f1 asc", tt).unique());
#7 Updated by Eric Faulhaber almost 2 years ago
Alexandru, please review 9034a/15373. The only issue I see is a minor coding standard format issue, but you are more familiar with the H2 direct access interface.
The minor format issue:
if( response.getRecid() ...
should be:
if (response.getRecid() ...
#8 Updated by Eric Faulhaber almost 2 years ago
Code review 9034b/15373:
The conversion change looks good.
#9 Updated by Alexandru Lungu almost 2 years ago
- % Done changed from 0 to 80
- Status changed from Review to WIP
Review of 9034a:
I understand the problem; the direct-access presumed that a unique index look-up would find one single record. Apparently, it may found more due to the fact that one field may be unknown.
- First of all, it doesn't compile.
nextPrimaryKeydoes not exist. The only signature available in FWD-H2 is:public long nextPrimaryKey(String tableName, int multiplex)
- Even if it would match, it is not clear to me the intent:
nextPrimaryKeyis retrieving the next PK available to that table and reserves it. It is like doing a NEXT VALUE on a sequence and is usually prior to INSERT statements. - Also, even if we would detect this case, I think the implementation should go in direct-access layer instead of fall-backing to the SQL one. I want to purely drop the index look-up spent time and start all over again due to the exception. Lets improve the direct-access layer to cover this case
Please check-out FWD-H2 (code/p2j_repo/fwd-h2/trunk) and attempt to change FWDDirectAccessDriver to provide this hint back to DirectAccessHelper (maybe add in response an "ambiguous" flag for your case). In that case, you shall use something like Persistence.uniqueResultViolation and, in essence, behave like RandomAccessQuery when finding more "unique" records. Use H2_Database_Fork for more details on FWD-H2 development.
#10 Updated by Artur Școlnic almost 2 years ago
- Status changed from WIP to Review
I committed 9034a/15373 and 9034a_h2/51, added support for identifying ambiguous unique find.
#11 Updated by Eric Faulhaber almost 2 years ago
Alexandru, please review.
#12 Updated by Alexandru Lungu almost 2 years ago
- % Done changed from 80 to 100
- I am a bit confused with the state of this branch. I already reviewed 9034a/15373 in #9034-9. Maybe you missed committing the changes as 9034a/ 15374?
- The changes are functionally good.
- Please fix the formatting. Even if there are no explicit formatting rules for the FWD-H2 code, please attempt to keep an homogeneous formatting. Specially, the FWD extensions should respect the FWD formatting standards, whereas the rest of FWD-H2 should simply look the same.
- The opening brace of
getAmbiguous()should be on a new line. - Add
returnandparamtags for the javadoc of the setters/getters - Keep the javadoc of ambigous on a single line
- The opening brace of
#13 Updated by Artur Școlnic almost 2 years ago
Alexandru Lungu wrote:
- I am a bit confused with the state of this branch. I already reviewed 9034a/15373 in #9034-9. Maybe you missed committing the changes as 9034a/ 15374?
Sorry for that, I indeed forgot to commit, 9034a/15374 is now committed.
#14 Updated by Alexandru Lungu over 1 year ago
- Status changed from Review to WIP
- % Done changed from 100 to 90
- remove oo imports from RAQ
- add history entry for
DirectAccessHelper - remove changes from ErrorManager (empty line)
Please commit required changes to 9034a_h2 according to #9034-12.
#15 Updated by Alexandru Lungu over 1 year ago
Review of 9034a:
These were change local on my side, ignore review.
#16 Updated by Artur Școlnic over 1 year ago
Alexandru, during testing of 9134a_h2, I encountered some issue with the next method in TreeCursor:
if (beforeFirst) {
beforeFirst = false;
if (node == null) {
return false;
}
I think this conditional needs to be refactored to:
if (node == null) {
return false;
}
if (beforeFirst) {
beforeFirst = false;
considering that I added an extra
cursor.next() in FWDDirectAccessDriver.retrieve(). For the second next, beforeFirst will be false and the null checking will not be performed.#17 Updated by Alexandru Lungu over 1 year ago
This is how the code looked before any FWD-H2 specific changes:
| @Override
| public boolean next() {
| if (beforeFirst) {
| beforeFirst = false;
| if (node == null) {
| return false;
| }
| if (first != null && tree.compareRows(node.row, first) < 0) {
| node = next(node);
| }
| } else {
| node = next(node);
| }
| if (node != null && last != null) {
| if (tree.compareRows(node.row, last) > 0) {
| node = null;
| }
| }
| return node != null;
| }
You are suggesting changing the code H2, which doesn't seem right. I think the problem is node.active false without a null-check. It should be rewritten as node != null && node.active false.
#18 Updated by Artur Școlnic over 1 year ago
#19 Updated by Alexandru Lungu over 1 year ago
- % Done changed from 90 to 100
- Status changed from WIP to Internal Test
I am OK with the changes in 9034a_h2. Please go ahead and merge to the FWD_H2 trunk. From my understanding, 9034a should reach FWD trunk after the H2 is upgraded. We will honor that.
Please let me know if more testing is required.
#20 Updated by Artur Școlnic over 1 year ago
I am ready to merge 9034a_h2.
#21 Updated by Alexandru Lungu over 1 year ago
Please go ahead and merge 9034a_h2 to FWD-H2 trunk.
#22 Updated by Artur Școlnic over 1 year ago
9034a_h2 was merged to FWD-H2 trunk as rev 54.
#23 Updated by Alexandru Lungu over 1 year ago
- Status changed from Internal Test to Merge Pending
Please merge 9034a after 9263a to trunk.
#24 Updated by Artur Școlnic over 1 year ago
- Status changed from Merge Pending to Test
9034a was merged to trunk as rev 15593.