Bug #9133
Array subscript is out of range stops the evaluation of other expressions in the where clause
0%
Related issues
History
#1 Updated by Lorian Sandu almost 2 years ago
create test_table. test_table.f1[1] = 10. test_table.f1[2] = 20. test_table.f1[3] = 30. release test_table. def buffer buf1 for test_table. def var i1 as int initial 0. def var i2 as int initial 2. find first buf1 where i2 = 2 or buf1.f1[i1] ne 0 no-error. if available buf1 then do: message "found". end.
in 4gl found is printed.
in fwd there is nothing printed on the screen.
f1[i1] throws error but it is silent and because the other expression (i2 = 2) is true, find first is able to find the record.
In fwd the execution of find first stops when the error is encountered (the same happens for both persistent tables and temp-tables).
#3 Updated by Ovidiu Maxiniuc almost 2 years ago
This is actually happening in the case of one of our customer, so it needs to be fixed. See #7143-1204.
The (anonymized) generated FQL is: "miTable.sField = false and (? or miTable.dField[?] = true)". The parameters are: isEqual(i, 0) and minus((i), 1). At the moment of execution, i is 0. Even more, the query is a FOR EACH, not even in NO-ERROR mode.
The HQLAst is:
and [AND]
= [EQUALS]
miTable [ALIAS]
sField [PROPERTY]
false [BOOL_FALSE]
( [LPARENS]
or [OR] // <---- the OR to be short-cut
? [SUBST] // <---- the first operand with YES/TRUE value
= [EQUALS] // <---- this node and its subtree should NOT be processed
miTable [ALIAS]
dField [PROPERTY]
[ [LBRACKET]
? [SUBST]
true [BOOL_TRUE]
Because the first parameter, isEqual(i, 0) is evaluated to true, the second operand of or should not be evaluated (this is why the first operand of or, (i eq 0) is guarding) since the value of the or node is already known. The problem is that FQLPreprocessor is not taking this into consideration and will blindly attempt to process that subtree.
Probably, a similar thing happens for AND(FALSE, T).
#5 Updated by Ovidiu Maxiniuc almost 2 years ago
- Priority changed from Normal to Urgent
For awareness, I am raising the priority of this task in relation to #9189.
#6 Updated by Lorian Sandu almost 2 years ago
- Status changed from New to WIP
I looked into how AbstractQuery.preprocessSubstituionArguments behaves in terms of error handling. I found out that the preprocessing of the where clause is implicitly run in silent mode .
I think that we need to do the same for FQLPreprocessor.inlineDenormalizedField because the error should not appear on the screen when we are processing the where clause.
RecordBuffer rbuff = lookupBuffer(alias);
+ ErrorManager.ErrorHelper errHlp = rbuff.getBufferManager().getTxHelper().errHlp;
String denormalizedProperty = TableMapper.getDenormalizedProperty(rbuff, ast.getText(), extentIndex);
- if (denormalizedProperty == null)
- {
- ErrorManager.recordOrThrowError(26, String.valueOf(extentIndex + 1), "");
- // ** Array subscript <extentIndex> is out of range. (26)
-
- return;
- }
- ast.setText(denormalizedProperty);
- ast.removeChildren();
- ast.putAnnotation("inlined", Boolean.TRUE);
- inline = true;
+
+ boolean success = true;
+ success = !errHlp.silent(() -> {
+ if (denormalizedProperty == null)
+ {
+ ErrorManager.recordOrThrowError(26, String.valueOf(extentIndex + 1), "");
+ // ** Array subscript <extentIndex> is out of range. (26)
+ }
+ });
+ if (success)
+ {
+ ast.setText(denormalizedProperty);
+ ast.removeChildren();
+ ast.putAnnotation("inlined", Boolean.TRUE);
+ inline = true;
+ }
+ else
+ {
+ //TO-DO : remove the whole node from the ast OR set the node to be false
+ }
+
}
#7 Updated by Alexandru Lungu almost 2 years ago
Lorian, please put this change in a branch and move this into Review.
#8 Updated by Lorian Sandu almost 2 years ago
- Status changed from WIP to Review
Committed to 9133a / rev 15454
Ovidiu/Alexandru: Please review.
#9 Updated by Alexandru Lungu almost 2 years ago
- Status changed from Review to WIP
- % Done changed from 0 to 80
I don't think changing the grandparent is always correct.Ovidiu/Alexandru: Please review.
- You can have
for each tt where true or tt.f1[i0], considering thatf1is an extent of logical. This will override the entireorclause, which is not correct. - You can have more complex expressions like
for each tt where true or tt.f1[i0] + 1 = 2. This will result infalse = 2according to your changes (which is a syntax error)
f1[i1] throws error but it is silent and because the other expression (i2 = 2) is true, find first is able to find the record.
I think this case is a bit trickier. Check:
define temp-table test_table field f1 as int extent 5 field f2 as int field f3 as int.
do transaction:
create test_table.
test_table.f1[1] = 10.
test_table.f1[2] = 20.
test_table.f1[3] = 30.
test_table.f2 = 0.
release test_table.
create test_table.
test_table.f1[1] = 100.
test_table.f1[2] = 200.
test_table.f1[3] = 300.
test_table.f2 = 0.
release test_table.
create test_table.
test_table.f1[1] = 1000.
test_table.f1[2] = 2000.
test_table.f1[3] = 3000.
test_table.f2 = 1.
release test_table.
end.
def buffer buf1 for test_table.
def var i1 as int initial 0.
def var i2 as int initial 2.
for each buf1 where buf1.f2 = 0 or buf1.f1[i1] ne 0:
message buf1.f1[1].
end.
Note how 10 and 100 are printed, but the error occurs at the third iteration as f2 is no longer equal to 0. Yet, if your first clause is static (i2 = 0), then it is evaluated only once at the query opening (not at each iteration of the for-each). This means that you will always have 0 = 0 or ..., so the second part of the clause is not evaluated.
I don't think it is about the fact that the clause is evaluated in silent mode; it simply shouldn't be evaluated for some rows.
- In
FqlPreprocessor, we already havetrySimplifyBooleansthat would resolvetrue or ...to true. This should have fixed the issue in the first place. I don't know yet why your case is not honoring this conditional. IstrySimplifyBooleanapplied later thaninlineDenormalizedField? Or maybei1 = 0is not resolved totruestraight-away? Anyway, this is targeting only a trivial case. - There are cases where
buf1.f2 = 0is evaluated to true/false depending on DB data. This makesFqlPreprocessoruseless.- For some cases, FWD has "checkError" UDF in
mainWalk. This will wrap the expression incheckErroror mark the UDF as guarded. But as you guessed it, this is only related to UDFs and only at SQL execution. The de-normalization is happening before that.
- For some cases, FWD has "checkError" UDF in
In theory, we can apply your changes, but replace the bad AST (i.e. buf1.f1[i1]) with something like udf.throw_error instead of false. This will ensure that if that part of the SQL will be evaluated, it will throw an error. I am imagining the final SQL as:
select * from test_table where test_table.f2 = 0 or udf.throw_error(26) ne 0
Note that 26 is the error code. Anyway, check the conclusions chapter.
Extra experiments¶
What happens if the index is dynamic (a.k.a for each buf1 where buf1.f2 = 0 or buf1.f1[buf1.f2] ne 0)? In this case, we can't know at the time of preprocessing that the clause will have a bad index. Is this resolved as a client where? If so, can we maybe consider resolving static "array subscript" issues through client where as well?
Lorian please, do such experiment and post the Java conversion of buf1.f1[i1] vs buf1.f1[buf1.f2]. Are these processed differently as query parameters vs inlined FQL?
Conclusions for throw_error¶
We are still seeing the tip of the iceberg here. From my POV, this test-case can get very nasty to the level where FWD is relying on the PostgreSQL planning. Even with my solution above, the results will be evaluated in a non-deterministic order by PostgreSQL (considering an arbitrary plan) and so the error may/or may not appear depending on the index selectivity.
As a summary: if I use an index on f2, PostgreSQL may choose a tree-index cursor to iterate only on the right f2 fields, so the de-normalization error would never occur. In 4GL however, because the DB planning may be different so it uses the scan index for example, the error might occur. This can hold vice-versa (4GL will chose a favorable plan while Progress wouldn't).
I need more feedback from Ovidiu on this one.
Conclusions for short-circuit¶
I refer to reduction true or ... to true.
Even if this may fix #9133-1, it won't fix #9133-3. So we can drop this lead.
Conclusions for client-where¶
I think we are forced to extract the extent access to FWD code rather than integrating it in the FQL. We can be eager and inline only extent access that we know are right. If we have doubts on that, we shall extract the extent access onto a client-where. But I really fear the performance after. We can proceed with such idea after the experiments are conducted.
#10 Updated by Lorian Sandu almost 2 years ago
Lorian please, do such experiment and post the Java conversion of buf1.f1[i1] vs buf1.f1[buf1.f2]. Are these processed differently as query parameters vs inlined FQL?
Thanks Alex for the investigation. My implementation was too trivial and for sure did not solve all the edge cases. The issue seems more complex than i thought it was. I tested a bit the scenario you mentioned and this is the java converted code:
buf1.f1[buf1.f2]query0.initialize(buf1, ((String) null), () -> or(isEqual(buf1.getF2(), 0), () -> isNotEqual(buf1.getF1(minus((buf1.getF2()), 1)), 0)), "buf1.recid asc");
- The extent access is extracted onto a
client whereand the output from FWD is the same as in 4GL.
query1.initialize(buf1, "buf1.f2 = 0 or buf1.f1[?] != 0", null, "buf1.recid asc", new Object[] { minus((i1), 1) });
- The extent access is extracted onto
inline FQLand the issues arrise.
Probably, as you said, the solution would be most of the time to extract the extent access into a client where and avoid FQLPreprocessor.
I will look into the rules and find a way of changing the extent access.
#11 Updated by Alexandru Lungu almost 2 years ago
I really fear the impact of client where. For the first query you posted: if that query would run over a persistent database, it would basically fetch all records in the memory. This may be huge. Also, the client-where for such extent usage would be unbounded. While previously was only about dynamic indexes, using this now for static indexes would make all extents be evaluated at server-side - yikes!
Also, using throw_error is a bad idea due to https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-EXPRESS-EVAL This means that SQL is not short-circuiting OR from left-to-right necessary. So the core principle is flawed.
- Maybe we can implement a system that will transform an FQL to a client where at run-time. This way we generate the slow query due to invalid extent index only when we detect such case.
#12 Updated by Ovidiu Maxiniuc almost 2 years ago
- % Done changed from 80 to 0
tablename table with a extField and a local integer variable id whose value is 0:
- for
tablename.extField[id]the code before #9095 generated incorrect SQLs (liketablename.null) when the index of the extent was out of range. What this task did was to raise the error condition in these cases; - a customer had a case when the above event was guarded (
id = 0 or tablename.extField[id]), and now, even if the right side of the or is not supposed to be processed in 4GL and FWD, we do it since we need to create a valid SQL to send to SQL server. #9095 caused the node to be processed and incorrectly trigger the error; - the initial solution I proposed for this task, was to identify the left-side of the
oras being a constant and evaluate the whole tree to a specific value using simplification rules. For example:true or tablename.extField[id]-->true;false and tablename.extField[id]-->false;
Of course, this is not the general case, but it's the exact customer case and the pressure would be relieved for they, allowing us to think more and come with a better general solution;
- the second approach was to detect the
tablename.extField[id]cases and instead of generating invalid column name, just to replace the node with anull(unknown) value. This would also fix the above issue (SQL will use the simplification rules and actually skip the evaluation), but we hide the cases where the error condition should actually be raised; - a third solution which was implemented in #9133-6 was to isolate the extent node processing in a silent bracket. This is incorrect:
- only the current node should have been evaluated to
null, allowing the simplification of the parent node to be performed by SQL (resulting in atrueorfalse, as seen above) - there is no check for existence of the grandparent;
- the error is hidden back again. In the event the error should have been raised, it is just recorded.
- only the current node should have been evaluated to
Alexandru Lungu wrote:
- You can have
for each tt where true or tt.f1[i0], considering thatf1is an extent of logical. This will override the entireorclause, which is not correct.
Cases like these are resolved at conversion time, and they are simplified, directly to for each tt where true. The conversion already has the simplification rules implemented;
- You can have more complex expressions like
for each tt where true or tt.f1[i0] + 1 = 2. This will result infalse = 2according to your changes (which is a syntax error)
The processing is done with the full expression parsed. If the simplification is applied, the full tt.f1[i0] + 1 = 2 expression is dropped.
- In
FqlPreprocessor, we already havetrySimplifyBooleansthat would resolvetrue or ...to true. This should have fixed the issue in the first place. I don't know yet why your case is not honoring this conditional. IstrySimplifyBooleanapplied later thaninlineDenormalizedField? Or maybei1 = 0is not resolved totruestraight-away? Anyway, this is targeting only a trivial case.
inlineDenormalizedField() is executed the as the last operation in mainWalk. However, trySimplifyBoolean ONLY take into consideration hardcoded values (nodes with BOOL_FALSE and BOOL_TRUE types). In out case, we have a SUBST. And this is a interesting note. I think we can implement the solution from item 3 above, by adding SUBST checks in trySimplifyBoolean().
- There are cases where
buf1.f2 = 0is evaluated to true/false depending on DB data. This makesFqlPreprocessoruseless.
Yes, this is a problem since the guard is not known to FQLPreprocessor.
- For some cases, FWD has "checkError" UDF in
mainWalk. This will wrap the expression incheckErroror mark the UDF as guarded. But as you guessed it, this is only related to UDFs and only at SQL execution. The de-normalization is happening before that.
Good point. There is another idea I had but was afraid to speak of, because of the possible performance penalty. Instead of resolving the extents on FWD side, I wonder if it is possible to defer it to SQL, by using an UDF. For tt.f1[expr], we would emit index('tt', 'f1', sqlExpr), assuming expr would be completely converted to sqlExpr. With Java UDF, this is probably not feasible, but with native UDFs it may work.
In cases expr cannot be converted to SQL, client-side where might be a necessity.
In theory, we can apply your changes, but replace the bad AST (i.e.
buf1.f1[i1]) with something likeudf.throw_errorinstead offalse. This will ensure that if that part of the SQL will be evaluated, it will throw an error. I am imagining the final SQL as:
I think this is similar to item 4. udf.throw_error(26) is even better than original null because this is the actual way to thrown the error when needed. The only problem I see here is writing throw_error method to return a _poly value. Even if will not actually return anything, it must honour the SQL syntax and match the expected type.
The evaluation order (#9133-11) might be a problem in PSQL. BUT we need to test. I assume the planner has a priority for evaluating these nodes and the UDFs have probably a very low one. The example you linked sustains my assumption: it chooses the evaluation of true node first, it is logical that the literals to have highest priority from this PoV.
I need more feedback from Ovidiu on this one.
I refer to reductiontrue or ...totrue.
Even if this may fix #9133-1, it won't fix #9133-3. So we can drop this lead.
From my PoV, #9133-1 and #9133-3 are the same. Nuanced, the root from #9133-1 is a subtree of #9133-3, but doing the right reduction should make both of them work, in this particular case.
Conclusions for client-where
I think we are forced to extract the extent access to FWD code rather than integrating it in the FQL. We can be eager and inline only extent access that we know are right. If we have doubts on that, we shall extract the extent access onto aclient-where. But I really fear the performance after. We can proceed with such idea after the experiments are conducted.
I strongly agree here. We will probably be forced to do that, but let's try to limit the cases where the correctness cannot be achieved otherwise. And, ad Eric mentioned in daily meet, these events MUST be reported at conversion time.
PS: sorry for the long but at the same time information-dense post.
#13 Updated by Ovidiu Maxiniuc almost 2 years ago
I think I have the question for why before 9095a the incorrect FQL (containing references of form <tablename>.null) was not a problem.
The response can be found in AdaptiveComponent.prepareHQLPreprocessor(). At that point, there are two FQLPreprocessor constructed, using different parameter sets. The call from super will invoke FQLPreprocessor.get() with true as the 7th parameter (inline), while if fallback and the first FQLPreprocessor was inlined, a new dynamic version is constructed which should NOT permit inlining of arguments.
- if the invalid index is detected, the process will stop with error;
- if not, the invalid column name will be used, meaning a broken FQL string.
In the customer application, the second preprocessor, even if it is created, it is never actually used. This is why it worked. Have it been used, the incorrect FQL would have been converted to an incorrect SQL and the invalid syntax error would have been issued when the latter is executed.
I have 2 questions now:- if the
inlineparameter isfalsefor the dynamic processor, is it normal to do the 'inlining' for the name of the expanded fields? The dynamic version should NOT take into consideration the current parameters. It is not correct to ignore the value ofi2in left but to usei1on the right side of OR (in testcase #9133-1); - why are we so eager to construct the
AdaptiveComponent.dynamicFQLPreprocessorif it will NOT be used? The process (assuming it is corrected) is time consuming (the FQL string is parsed,HQLAsttree constructed and walked multiple times).
#14 Updated by Alexandru Lungu almost 2 years ago
In the customer application, the second preprocessor, even if it is created, it is never actually used. This is why it worked. Have it been used, the incorrect FQL would have been converted to an incorrect SQL and the invalid syntax error would have been issued when the latter is executed.
This seems like a "it works by chance" case in the customer application. I would rely on it as before, but we should hurry up on fixing it in the near future. This includes the two questions asked - I don't have an answer right now; it needs specialized investigation and testing.
I think this is similar to item 4. udf.throw_error(26) is even better than original null because this is the actual way to thrown the error when needed. The only problem I see here is writing throw_error method to return a _poly value. Even if will not actually return anything, it must honour the SQL syntax and match the expected type.
I think #9133-11 should dismiss this approach. If the official documentation states that it has non-deterministic results, I won't rely on that then. Even with index('tt', 'f1', sqlExpr), I think it falls into the same dilema. Note that this is only for PostgreSQL; SQL standard doesn't guarantee such evaluation order. I don't know more about MariaDB or other dialects. Anyway, this is a solution that is flawed right from the start, so lets abandon it.
You can have more complex expressions like for each tt where true or tt.f1[i0] + 1 = 2. This will result in false = 2 according to your changes (which is a syntax error)
The processing is done with the full expression parsed. If the simplification is applied, the full tt.f1[i0] + 1 = 2 expression is dropped.
the initial solution I proposed for this task, was to identify the left-side of the or as being a constant and evaluate the whole tree to a specific value using simplification rules. For example:
Yeah, I was rather thinking of more complex cases like for each tt where tt.f2 = 1 or tt.f1[i0] + 1 = 2, in which we can't do any reduction. For this case, tt.f1[i0] is still not converting properly to SQL.
On a more general scale, for x or y in SQL, FWD should generate or(<expr1>, () -> <expr2>) in SQL. The problem is that there is no lazy evaluation possibility in SQL (i.e. () -> <expr2>), the OR UDF should guard the evaluation of the second operand and this might be very slow anyway. Using the native SQL OR doesn't guarantee any evaluation order.
I strongly agree here. We will probably be forced to do that, but let's try to limit the cases where the correctness cannot be achieved otherwise. And, ad Eric mentioned in daily meet, these events MUST be reported at conversion time.
1) Do you have some rules in mind. From my POV, only a static correct index can emit FQL in this scenario (i.e. tt.f1[1]). This means we need to infer the data-type of that, check the extent, and ensure it is in bounds. In all other cases, we should emit a client-where. From my POV, all other cases seem like 99% of the cases :) I am afraid of the performance draw-back in the end.
the second approach was to detect the tablename.extField[id] cases and instead of generating invalid column name, just to replace the node with a null (unknown) value.
2) I really like this! It will generate a correct SQL and in most cases it will return an accurate set of results. The flaw is indeed that using an invalid index will not generate an error - it will simply bypass that. Functionally, it is not perfect as it probably returns more results than intended. But, we can do a SEVERE log for that - when id is 0 in tablename.extField[id]?
Solution 1) is functionally perfect, but very slow in 99% of the cases. Solution 2) is fast, but not functionally correct in some edge cases. Any both cases the customer will be recommended to rewrite the code (due to conversion warning or run-time SEVERE log). I think we are left only with these two cases.
I am inclined to go with 2) because none of the edge cases of 2) were found in a customer application. With 1), the performance impact will affect most of the cases in the customer application.
Lorian, please attempt 2) in 9133a. It means replacing invalid tablename.extField[id] with ? and that is all. Put it in the branch and more to Review.
#15 Updated by Lorian Sandu almost 2 years ago
Alexandru Lungu wrote:
Lorian, please attempt 2) in 9133a. It means replacing invalid
tablename.extField[id]with?and that is all. Put it in the branch and more to Review.
I replaced tablename.extField[id] with null since i was not able to find UNKNOWN type for nodes:
Original where clause : buf1.f2 = 0 and buf1.f1[?] != 0
Generated fql : buf1.f2 = 0 and (null != 0 or null is null) (null is null is an augmentation that is added before inlineDenormalizedField() is called)
Generated SQL :
select
testtable_0_.recid as col0_0_
from
test_table testtable_0_
where
testtable_0_.f2 = 0 and (0 is not null or null is null)
order by
testtable_0_.recid asc
I'll try to find if there is a way to skip adding that null is null condition, because that will always be true and therefore the whole expression in parenthesis will be evaluated as true which is not correct.
#16 Updated by Lorian Sandu almost 2 years ago
I looked into FQLPreprocessor.mainWalk() and found out how we handle the cases tablename.extField[?] , where the index has unknown value.
// Possibly inline certain query substitution parameters.
case SUBST:
parent = (HQLAst) next.getParent();
if (parent != null)
{
int index = ((Long) next.getAnnotation("index")).intValue();
Object param = parameters[index];
[....]
// check for unknown value
if (param instanceof BaseDataType &&
I tried to force the cases where we have an index < 0 to behave similar as it had unknown value.
The problem is that these type of cases are resolved like this : they are removed from the fql at all they are simplified (simplifyUnknowns())
// get rid of unknowns
if (unknowns != null)
{
Set<HQLAst> createdBooleans = simplifyUnknowns(unknowns);
if (createdBooleans != null)
{
if (needSimplification == null)
{
needSimplification = new HashSet<>();
}
needSimplification.addAll(createdBooleans);
}
}
I will investigate deeper to see if this case is simplified as BOOL_FALSE
#17 Updated by Lorian Sandu almost 2 years ago
Lorian Sandu wrote:
I will investigate deeper to see if this case is simplified as
BOOL_FALSE
Actually, this is simplified as BOOL_TRUE and therefore will be removed from the fql.
Our case is something like this ? != 0 :
// we have a simple "? <comparison operator> {CONST|SUBST}" statement
if (pType == EQUALS)
{
disposition = BOOL_FALSE;
}
else if (pType == NOT_EQ)
{
----> disposition = BOOL_TRUE;
}
#18 Updated by Alexandru Lungu almost 2 years ago
Hmm I see. This is because it will end up as null ne 0 and this is basically true. This you also happen for cases where we compare the extent field with null (tablename.extField[id] = ?) - it will evaluate to true.
This gets trickier. I suppose this is in fact an edge case of the functionality. So I think we are back on the drawing board with #9133-14 (?).
#19 Updated by Lorian Sandu almost 2 years ago
Alexandru Lungu wrote:
The point is that with the current implementation ofHmm I see. This is because it will end up as
null ne 0and this is basically true. This you also happen for cases where we compare the extent field with null (tablename.extField[id] = ?) - it will evaluate to true.
This gets trickier. I suppose this is in fact an edge case of the functionality. So I think we are back on the drawing board with #9133-14 (?).
FQLPreprocessor we cannot
#20 Updated by Alexandru Lungu almost 2 years ago
So this means that converting to client where is the only way to go here? I suppose so.
#21 Updated by Alexandru Lungu almost 2 years ago
- Priority changed from Urgent to Normal
I am moving this to Normal priority as the regression in #9189 was fixed by reverting the original changes. We can have this fixed on a lower priority.
#22 Updated by Alexandru Lungu over 1 year ago
I put some thinking into this again, but (again) I can't see a clear implementation for this. Can we have a log SEVERE for this case in trunk until a proper solution is found?
If the extent parameter is out-of-bounds, log that severe message. This way, we can troubleshoot the issue better when we will encounter it.
Because the extents are expanded, this makes it even harder to support.
Short term: I would document this as an unsupported functionality of expanded extents. FWD will simply preprocess the FQL and will fail if a bad extent is used, even if in an OR clause. It is like attempting to generate an invalid SQL, but rely that "the bad part of the SQL will not get reached due to OR short-circuits". This is simply not possible due to the strong typing of SQL and the non-deterministic order of processing the OR clauses.
Long term: I suppose we can convert the FQL to a Java client where at run-time and interpret it. This way, we don't generate the client where for all queries with extents at conversion time. However, this will be a new functionality of FWD: converting only an FQL to a Java expression (client-side where) and interpreted dynamically.
#23 Updated by Lorian Sandu over 1 year ago
- Status changed from WIP to Review
- reviewer Alexandru Lungu added
Alexandru Lungu wrote:
Committed toI put some thinking into this again, but (again) I can't see a clear implementation for this. Can we have a log SEVERE for this case in trunk until a proper solution is found?
If the extent parameter is out-of-bounds, log that severe message. This way, we can troubleshoot the issue better when we will encounter it.
9133b / rev 15624 :
- Added severe logging when denormalizing a property with an out of bounds index.
Please review.
#24 Updated by Alexandru Lungu over 1 year ago
- Status changed from Review to Internal Test
I am OK with the changes in 9133b. Only thing is that the arguments should be aligned to String.format first argument.
Please do a slim test to see the log in action only for the desired cases.
If that goes well, we can go ahead with merge.
#25 Updated by Lorian Sandu over 1 year ago
9133b / rev 15656 : if (index == null || index < 0)
{
LOG.severe(String.format("Failed to denormalize %s.%s[%d]. Index is out of bounds or is null.",
- recBuf.getLegacyName(),
- property,
- index));
+ recBuf.getLegacyName(),
+ getLegacyFieldName(recBuf, property),
+ index != null ? index + 1 : null));
return null;
}
DmoMeta dmoInfo = recBuf.getDmoInfo();
- changed the field name that is logged to match exactly the name in the original 4GL code
- incremented the logged index to match the indexing value from 4GL
If the 4GL code looks like buf1.f1_ext[0] , the FWD log is : | SEVERE | com.goldencode.p2j.persist.TableMapper | .... | Failed to denormalize buf1.f1_ext[0]. Index is out of bounds or is null..
It would be then easier to find the problematic 4GL code when debugging if we know how it looks like from the log.
#26 Updated by Lorian Sandu over 1 year ago
Serban, can you test the scenario from #9189-1 with 9133b , please?
I expect to see some SEVERE logs of this format : | SEVERE | com.goldencode.p2j.persist.TableMapper | .... | Failed to denormalize buf1.f1_ext[0]. Index is out of bounds or is null..
#27 Updated by Alexandru Lungu 12 months ago
- Related to Bug #10360: FOR loop WHERE condition evaluation issue added