Bug #9396
Improve Incompatible data types in expression or assignment. (223) error handling
80%
History
#2 Updated by Dănuț Filimon over 1 year ago
- Status changed from New to WIP
- Assignee set to Dănuț Filimon
From #9377-8:
I've created unit tests for testing the behavior of temp-tables fields and literals:| Field type | int | char | date | datetime | datetime-tz | decimal | logical | recid | rowid |
|---|---|---|---|---|---|---|---|---|---|
| int | pass | pass | fail | pass | pass | pass | pass | pass | pass |
| char | pass | pass | fail | pass | pass | pass | pass | pass | pass |
| date | pass | pass | pass | fail | fail | pass | pass | pass | pass |
| datetime | pass | pass | pass | pass | fail | pass | pass | pass | pass |
| datetime-tz | pass | pass | pass | fail | pass | pass | pass | pass | pass |
| decimal | pass | pass | fail | pass | pass | pass | pass | pass | pass |
| logical | pass | pass | fail | pass | pass | pass | pass | pass | pass |
| recid | pass | pass | fail | pass | pass | pass | pass | pass | pass |
| rowid | pass | pass | fail | pass | pass | pass | pass | pass | fail |
There are a few problems I noticed when fixing #9377-8:
- Let's take the following example (lok logical variable, tt9377 temporary table, l1 logical field):
silent(() -> lok.assign(hq.unwrapQuery().prepare("for each tt9377 where l1 = 10")));this should assign false to lok, but it is true because inDynamicQueryConversion.injectVariableHelper()we always have a return value but the processing should stop right there when we get error 223. This can be fixed by throwing an error and catching it inDynamicQueryHelper.parse(). - There's also this case (dtz1 datetime-tz field):
silent(() -> lok.assign(hq.unwrapQuery().prepare("for each tt9377 where dtz1 = DATETIME('05-05-2002 07:15:03')")));where the injected variable is actually a CHARACTER but the conversion should fail because of the datetime function. One possible solution would be to check if the parent is a cast function and then compare it with the sibling type, determining if the types are compatible.
- The additional error case (l1 logical field):
lok = false. DO TRANSACTION: hq:query-prepare("for each tt9377 where l1 = 10"). CATCH ex AS Progress.Lang.Error : Assert:Equals(1, ex:NumMessages). Assert:Equals(223, ex:GetMessageNum(1)). lok = true. END CATCH. END.ex:NumMessagesvalue is 2, the error are:com.goldencode.p2j.NumberedException: ** Incompatible data types in expression or assignment. (223)andcom.goldencode.p2j.NumberedException: ** nullwith the number -1.
I am still thinking on how to fix this (in my opinion this is not a critial issue and removing this assertion fixes all my test cases).
Now for the second bullet point I might be mistaken. In 4gl int64(logical(int64(5))) is valid and I need to test if the first int64 function is the one that determines the data type.
#3 Updated by Dănuț Filimon over 1 year ago
The third bullet point is a regression added in trunk/15456, recordOrShowError throws a DeferredLegacyErrorException which results in the com.goldencode.p2j.NumberedException: ** null error. Added Artur as a watcher as this is related to #8912 changes (8912h branch).
#4 Updated by Dănuț Filimon over 1 year ago
Committed 9396a/15583. This commit fixes all of my testcases related to #9396-2 table (except the 3rd bullet point).
The changes include:- Added a new DynamicQueryException class.
- Stop dynamic query processing when 223 error is thrown (this will make the returned query null) so code like
silent(() -> lok.assign(hq.unwrapQuery().prepare("for each tt9377 where l1 = 10")));will correctly assignlokvalue. - Support error 223 for cast functions (currently only DATETIME and DATETIME-TZ).
- Expand test cases that do not rely on DATETIME and DATETIME-TZ functions and fix any issues.
- Expand test cases to use INT64, DECIMAL, DATE, LOGICAL functions to reveal more incompatibilities and fix those as well.
#5 Updated by Dănuț Filimon over 1 year ago
This turns out to be more complicated for certain cast functions, for example you can have DATETIME(DATE(3,3,2001), 402) which will result in 4 literals to be extracted, then it is possible to have an invalid date format.
#6 Updated by Dănuț Filimon over 1 year ago
- % Done changed from 0 to 50
Dănuț Filimon wrote:
This turns out to be more complicated for certain cast functions, for example you can have
DATETIME(DATE(3,3,2001), 402)which will result in 4 literals to be extracted, then it is possible to have an invalid date format.
I've managed to fix this, find the function for any type of literal then make sure the data type resulted from the function matches the data type of the field. Improved error handling for query-prepare resulted by having a ? value as a predicate (recordOrShowDatabaseError was not used correctly) and it must also throw an error to stop any processing.
I committed 9396a/15584 and expanded my test suite.
Since most of the testing was done using dynamic queries, I must also write similar tests for static queries to make sure my solution does not turn into a regression.
#7 Updated by Dănuț Filimon over 1 year ago
Found the following test:
@Test.
method public void test-logical-logical-func16():
define query q for tt9377.
open query q for each tt9377 where l1 = logical(1).
finally:
close query q.
end finally.
end method.
where it results in the following compilation error:
[javac] /home/ddf/gcd/dataset/src/com/goldencode/dataset/unittests/Test9377Set13.java:464: error: no suitable constructor found for logical(int)
[javac] (P2JQuery.Parameter) () -> new logical(1)
[javac] ^
[javac] constructor logical.logical(BaseDataType) is not applicable
[javac] (argument mismatch; int cannot be converted to BaseDataType)
[javac] constructor logical.logical(boolean) is not applicable
[javac] (argument mismatch; int cannot be converted to boolean)
[javac] constructor logical.logical(logical) is not applicable
[javac] (argument mismatch; int cannot be converted to logical)
[javac] constructor logical.logical(String) is not applicable
[javac] (argument mismatch; int cannot be converted to String)
[javac] constructor logical.logical(character) is not applicable
[javac] (argument mismatch; int cannot be converted to character)
[javac] constructor logical.logical(Boolean) is not applicable
[javac] (argument mismatch; int cannot be converted to Boolean)
The converted query looks like this:
query16.assign(new AdaptiveQuery().initialize(tt9377, "tt9377.l1 = ?", null, "tt9377.recid asc", new Object[]
{
(P2JQuery.Parameter) () -> new logical(1)
}));
while a logical(2.2) uses (P2JQuery.Parameter) () -> new logical(decimal.fromLiteral("2.2"))
The solution is to either add a logical(int) constructor or make conversion changes similar to the decimal (I prefer no conversion changes).
#8 Updated by Dănuț Filimon over 1 year ago
- Status changed from WIP to Review
- % Done changed from 50 to 100
- reviewer Alexandru Lungu added
Committed 9396a/15585. Added logical(int) constructor to fix #9396-7.
All written tests passed (tests cover dynamic conversion between table fields and literals, functions, variables, query-prepare handling of unknown value and static queries - note that the static queries are not targeted by the changes but did manage to reveal a compilation issue).
The changes target dynamic conversion so my test plan includes:- 2x Customer unit tests
- Customer regression tests
- ChUI regression tests
- Harness and reports
- ETF regression tests
Any test recommendation is welcome.
Alexandru, please review.
#9 Updated by Alexandru Lungu over 1 year ago
Review of 9396a
- The logical constructor can be condensed:
assign(value != 0). I agree that the constructor should be added. - I agree with the idea of a
DynamicQueryException.
Before providing a green light, please better explain:
where the injected variable is actually a CHARACTER but the conversion should fail because of the datetime function. One possible solution would be to check if the parent is a cast function and then compare it with the sibling type, determining if the types are compatible.
At dynamic conversion, the literals are extracted as variables and embedded into the FQL. This way, the "convertor" will replace the variables (ex-literals) with substitution parameters. injectVariableHelper is doing this work - replacing literals with variables - but for doing so it needs to infer the data type of the variable. Instead of honoring the data type of the literal, it uses the data type of the field that is checked for equality - which in this case has a mismatch. Your attempt is to also honor the CASTs that are used when comparing that literal with the table field.
So for each tt where f1 = 1 is transformed into def var x as int. x = 1. for each tt where f1 = x. But if f1 was logical, the process would fail at injection time.
My questions:
- Is the literal extraction happening only in
f1 = 1kind is situations? Orf1 + 1 = f2is also a valid case in which1is extracted? - If only
f1 = 1is valid, where are the casts coming from? Or maybef1 = LOGICAL(1)also a valid case in which the extraction is made? If so, can you point out the code in trunk that already bypasses the CASTS when considering a literal for extraction?
#10 Updated by Dănuț Filimon over 1 year ago
- reviewer Andreea Bârzu added
- reviewer deleted (
Alexandru Lungu)
So there are two scenarios which need to be taken into consideration:where the injected variable is actually a CHARACTER but the conversion should fail because of the datetime function. One possible solution would be to check if the parent is a cast function and then compare it with the sibling type, determining if the types are compatible.
- If we define a static query we can't do something like
open query q for each tt9377 where cvar = datetime('05-05-2002 07:15:03')., the code will not compile because of the incompatible data types. - For dynamic query we are allowed to use:
hq:query-prepare("for each tt9377 where cvar = datetime('05-05-2002 07:15:03')").and it will throw an error because the types are not compatible.
def var x as char. x = '05-05-2002 07:15:03'. for each tt9377 where cvar = datetime(x) but this should fail at injection type because cvar is character and this type is incompatible with datetime. In FWD, the cast type function is not considered at all when comparing the data types at injection time, it should not reach DynamicConversionHelper.injectVariable() where it starts to graft the ast for the variable and ends up calling DynamicConversionHelper.injectVariableHelper() with a STRING literalType. My point is that we:
- allow faulty predicates to be parsed and introduce them in a cache;
- misinterpret the data types that should be compared. Fwd should be aware of the exact data type which the extracted variable will take and determine if it's compatible before any other processing is done.
DynamicConversionHelper.injectVariableHelper()only injects a literal variable and that is compared with the sibling type (the cvar), while the cast is what determines the final data type.
Alexandru Lungu wrote:
Is the literal extraction happening only in
f1 = 1kind is situations? Orf1 + 1 = f2is also a valid case in which1is extracted?
f1 = 1scenario: Iff1is logical as you mentioned previously, thelogical f1andint 1will not be compatible (error 223). Iff1is an integer,1will of course be extracted as a NUM_LITERAL.f1 + 1 = f2scenario: Again incompatible types if logical,1will be extracted as a NUM_LITERAL.
It's better if we understand how we find out which one is a literal, this is happening inDynamicQueryHelper.extractParams()where the Ast is parsed and any node with theis-literalannotation is marked as a variable that needs to be injected eventually (there are multiple places whereis-literalis added as an annotation in therules). The short answer: yes.
If only
f1 = 1is valid, where are the casts coming from? Or maybef1 = LOGICAL(1)also a valid case in which the extraction is made? If so, can you point out the code in trunk that already bypasses the CASTS when considering a literal for extraction?
I might have not expressed myself correctly, I am not talking about implicit casts but explicit ones (using functions like INT64, LOGICAL, DATETIME, DATE, DATETIME-TZ, DECIMAL). I did mention above the current problem which can answer these questions, we extract the literal from LOGICAL(1) which is 1 and that it's type (int) is compared with the sibling (should be logical because of the function used).
The "cast" is bypassed in DynamicConversionHelper.injectVariable(), step 2 where it checks the sibling type.
PROCESS_ANNOTATION.timer(() -> ConversionPool.runTask(ConversionProfile.ANNOTATIONS, finalPAst0));is what finally ends up determining that it can't convert the pAst. In some cases this behaves differently (with other types), will have to look into the test cases to find some examples I've already fixed.
#11 Updated by Dănuț Filimon over 1 year ago
- reviewer Alexandru Lungu added
- reviewer deleted (
Andreea Bârzu)
Somehow I modified this, sorry.
#12 Updated by Alexandru Lungu over 1 year ago
Is the literal extraction happening only in f1 = 1 kind is situations? Or f1 + 1 = f2 is also a valid case in which 1 is extracted?
What I meant by this is if the data type checking is done only for very specific patterns like a = b or FWD has a full implementation for any arbitrary expression (e.g. TRUNCATE(LENGTH(CONCAT("a", "b") - 5, 2) = c). Note how literals are character, but the whole left-side expression is an integer after the evaluation of functions (which are not casts). The bottom-line is if you attempt to fix this for a niche (casts) or for a full-set of problems I am not seeing.
The example will extract "a" and "b" as character variables, replacing the literals.
I might have not expressed myself correctly, I am not talking about implicit casts but explicit ones (using functions like INT64, LOGICAL, DATETIME, DATE, DATETIME-TZ, DECIMAL).
I am not sure I follow. The cast seems to be implicit in 4GL, so it is converted to an explicit one in FWD using extractParams. Therefore, casts seem to be fabricated by FWD. The bottom line of this statement is that maybe CASTS shouldn't be handled specifically for injectVariable, but rather fabricated with more care.
LENGTH("ABC") uses a CHAR literal, but returns a INTEGER):
- If
LENGTHcase works because it comes from the converted code, it means that a cast should work exactly the same, without extra special handling. Thus the problem may reside in the synthetic casts fromextractParams. - If
LENGTHcase doesn't work, it means this is a more general problem in which literals are incorrectly extracted. In this case, I would rather avoid extracting the literal altogether or find a unified solution to fix them all.
#13 Updated by Dănuț Filimon over 1 year ago
Alexandru, you are right. The problem also happens with other functions, the example:
silent(() -> lok.assign(hq.unwrapQuery().prepare("for each tt9377 where c1 = LENGTH('abc')")));
should not result in a query.
I'll have to work on another solution, I expect a lot of changes from this...
#14 Updated by Alexandru Lungu over 1 year ago
- % Done changed from 100 to 80
- Status changed from Review to WIP
Danut, lets go for to the more evident fix of not allowing the literals to be extracted in such complex scenarios. This is a good fix for now, as it will simply let the literal inlined, which is functionally OK. Lets defer the work on implementing the functions and more complex expressions for now. But first and foremost, lets do an analysis on how often such constructs appear. I don't want to rule out all functions and be victim to a large performance hit.
This means that we need to fine tune the literal detection and not consider all literals as being extract-able.
Ovidiu, can you provide an insight for this matter?
#15 Updated by Dănuț Filimon over 1 year ago
- % Done changed from 80 to 100
Alexandru Lungu wrote:
Danut, lets go for to the more evident fix of not allowing the literals to be extracted in such complex scenarios. This is a good fix for now, as it will simply let the literal inlined, which is functionally OK. Lets defer the work on implementing the functions and more complex expressions for now. But first and foremost, lets do an analysis on how often such constructs appear. I don't want to rule out all functions and be victim to a large performance hit.
This means that we need to fine tune the literal detection and not consider all literals as being extract-able.
Got it! My idea was to remove the current literal checking changes and move the work to another branch (9396b - not created yet).
#16 Updated by Dănuț Filimon over 1 year ago
- % Done changed from 100 to 80
I also committed the logical(int) constructor change to 9396a/15586.
Adjusted Done%.
#17 Updated by Dănuț Filimon over 1 year ago
FUNCTION(literal) constructs (the scenario involves the extended performance test of a customer, warmup + 10 runs):
| Type | Count | Percentage from total (%) |
|---|---|---|
| No construct | 30716 | 87.236 % |
| With construct | 4490 | 12.752 % |
| No construct, but the sibling type is not taken in consideration | 4 | 0.0113 % |
The results are based on the assumption that in DynamicConversionHelper.injectVariable(), in the second step where the parent is checked that it will try to check the sibling when no construct is available. When a construct is used, then it will not check the sibling (as the parent should be an operator). The last table row is represented by cases where the sibling is checked but it is either null or the conditions are not fulfilled.
#18 Updated by Alexandru Lungu over 1 year ago
Can you check what the construct is in that case? I expect to see UPPER) kind of combination in 99% of that cases.
#19 Updated by Dănuț Filimon over 1 year ago
Alexandru Lungu wrote:
Retested #9396-17, the new results:Can you check what the construct is in that case? I expect to see UPPER) kind of combination in 99% of that cases.
| Type | Count | Percentage from total (%) |
|---|---|---|
| No construct | 30597 | 87.352 % |
| With construct | 4426 | 12.635 % |
| No construct, but the sibling type is not taken in consideration | 4 | 0.0114 % |
- 528 - 4359 times (ProgressParserTokenTypes.KW_AND)
- 152 - 62 times (ProgressParserTokenTypes.EXPRESSION)
- 544 - 3 times (ProgressParserTokenTypes.KW_BEGINS)
- 377 - 2 times (ProgressParserTokenTypes.FUNC_POLY)
#20 Updated by Alexandru Lungu over 1 year ago
528 - 4359 times (ProgressParserTokenTypes.KW_AND)
I wonder if this is something line tt.f1 = 1 and true kind of construct ... doesn't make much sense to extract anyway. I think it is safe to go ahead with the plan of omitting the extraction for such literals.
#21 Updated by Dănuț Filimon over 1 year ago
Alexandru Lungu wrote:
528 - 4359 times (ProgressParserTokenTypes.KW_AND)
I wonder if this is something line
tt.f1 = 1 and truekind of construct ... doesn't make much sense to extract anyway. I think it is safe to go ahead with the plan of omitting the extraction for such literals.
Committed the changes to 9396a/15587, the test plan remains #9396-8.
Another commit will follow to remove unnecessary changes from previous commits that are not hit anymore.
#22 Updated by Dănuț Filimon over 1 year ago
- Status changed from WIP to Review
- % Done changed from 80 to 100
Committed the changes to 9396a/15588. Partially reverted changes from 15583 and 15584 revisions.
Please review.
L.E. injectVariable() is used in other FWD code, so I am not certain that the step 2 switch case can be removed.
#23 Updated by Ovidiu Maxiniuc over 1 year ago
Alexandru Lungu wrote:
Ovidiu, can you provide an insight for this matter?
First, a bit of wisdom :) from my experience working with dynamic queries: when dealing with issues in dynamic queries, run the static variant of the query firstly. It will help you see more easily how the query looks under-the-hood. (Of course, it can be done directly from DynamicQueryHelper, but debug code must be activated.)
For a long time, FWD was developed with the following paradigm: the customer MUST use valid 4GL code for conversion. This seems logical, because the source code is assumed to have already been used on a 4GL native box. Otherwise: garbage in - garbage out. As result, a lot of validations and data type checks were ignored during conversion assuming the 4GL compiler have already identified these issues and the programmers resolved them.
However, things got complicated with the introduction of dynamic support for temp-tables, find procedures and queries. We were grad when we took the static conversion and reuse it directly, but as noted above, it lacks the validations and data type checks which the 4GL compiler does in both cases (static and dynamic). The FWD runtime (for both compiled static and interpreted dynamic) is actually unchanged and the type from this PoV is undifferentiable. It assumes the code was semantically checked and executes it identically in both cases.
The problem is not only with the literals. We can add a lot of heuristic filters for them but we will not cover all the cases. There are constructs which do not involve the presence of literals. Take the following example:
DEFINE TEMP-TABLE tt003
FIELD l1 AS LOGICAL
FIELD c1 AS CHARACTER
FIELD c2 AS CHARACTER.
[...]
h:QUERY-PREPARE("for each tt003 where c1 = length(c2)") // dynamic query
[...]
FOR EACH tt003 WHERE c1 = LENGTH(c2): // static query, non compilable in 4GL, but convertible by FWD
[...]
END.In both these cases, the where predicate is something like: "upper(tt003.c1) = lengthOf(upper(tt003.c2))" and, although the Java code is valid, and also intermediary processing, only H2 (in this case it's a temp-table) will be able to realize the problem.
My conclusion is that we need to add the full type checking during standard conversion with error reporting if we want to have a fully compatible runtime for dynamic queries (and not only).
#24 Updated by Alexandru Lungu over 1 year ago
DynamicQueryHelper. for each tt where tt.f1 = 1 has different Java outputs in static conversion vs dynamic conversion.
- static conversion will generate
tt.f1 = 1where clause. - dynamic conversion will generate
tt.f1 = ?where clause and a fabricatedxwill be used as substitution parameter.
- as
DynamicQueryHelperhas this literal extraction routine which already does the data type checking and little effort can be done to set this straight, lets go with such quick win. - for general case as you mentioned, a real type checking system is required. Unfortunately, some things can go as POLY and we can't perfectly state if the query is OK or not until the execution time. Anyway, for this case, maybe we can catch an invalid syntax from SQL and presume that the query was simply prepared in a bad way. Of course, we can LOG SEVERE and turn up all the red lights, but as a safety net, we can at least provide a minimal syntax checking through the SQL parser.
- In a near future, we will need that type checking system.
#25 Updated by Alexandru Lungu over 1 year ago
Review of 8396a
- While the approach should fix the evident problem, I think it is too relaxed. Mind that
1 + 1 = 2is also a valid syntax, but the two1values will be considered complex, because their parent is+. This is not wrong per-se, but please mindinjectVariableimplmenetation:
int var4glType = literalType;
switch (litAst.getParent().getType())
{
case ProgressParserTokenTypes.KW_EQ:
case ProgressParserTokenTypes.EQUALS:
case ProgressParserTokenTypes.KW_NE:
case ProgressParserTokenTypes.NOT_EQ:
case ProgressParserTokenTypes.KW_LT:
case ProgressParserTokenTypes.LT:
case ProgressParserTokenTypes.KW_LTE:
case ProgressParserTokenTypes.LTE:
case ProgressParserTokenTypes.KW_GT:
case ProgressParserTokenTypes.GT:
case ProgressParserTokenTypes.KW_GTE:
case ProgressParserTokenTypes.GTE:
ProgressAst sibling = getSibling(litAst);
if (sibling != null)
{
if (sibling.getType() > ProgressParserTokenTypes.BEGIN_FIELDTYPES &&
sibling.getType() < ProgressParserTokenTypes.END_FIELDTYPES)
{
// only fields are taken into consideration to avoid database CASTing issues
var4glType = sibling.getType();
}
else if (sibling.getType() == ProgressParserTokenTypes.FUNC_RECID)
{
// we want our operand to be bigint to match the record.id field in db
var4glType = ProgressParserTokenTypes.NUM_LITERAL;
}
}
break;
}
The var4glType is different from literalType only when:
- it is recid, so the variable type will be num.
- it is compared with a field type (aka
tt.f1kind of syntax).
In all other cases, literalType and var4glType will match. So I suggest having this switch-case from injectVariable fine tuned.
Please investigate why tt.f1 = LENGTH('abc') is hitting the switch-case, making var4glType different from literalType.
#26 Updated by Ovidiu Maxiniuc over 1 year ago
Alexandru Lungu wrote:
Ovidiu, the work-flow of static and dynamic queries in FWD differs a bit, especially throughActually, the conversion is the same. The difference you see is due to intermediary-processing (DynamicQueryHelper.for each tt where tt.f1 = 1has different Java outputs in static conversion vs dynamic conversion.
- static conversion will generate
tt.f1 = 1where clause.- dynamic conversion will generate
tt.f1 = ?where clause and a fabricatedxwill be used as substitution parameter.
extractParams() / injectVariable()) executed on the AST tree. At any rate, this processing maintains the expression validity by keeping the same type of the literal for the new substitution variable. When the type-checking occurs in TRPL (after the injection, I admit) it should realize the incorrect match and report as an error (223). This would throw an exception which will either:
- stop the static conversion (or at least log a serious warning) or
- be caught by dynamic query helper and raise a runtime error condition and return
false.
The _poly case, by its nature, is resolved at runtime in 4GL as well. We will do this likewise.
This is the ideal/general way to fix the problem. As a temporary short-cut we can check the compatibility of operand types in a quick pass for a set of operators. In my testcase, for = operator, since type(c1) differs from type(length(...)) error 223 should be raised, regardless of the parameters of length. In fact, this is just a fragment of the final solution, where the types of functions/methods/object methods will have to be checked based on their signature. Yet, IIRC, I think we are doing this at some point during conversion, but probably the algorithm is not covering all the cases.
#27 Updated by Greg Shah over 1 year ago
My conclusion is that we need to add the full type checking during standard conversion with error reporting if we want to have a fully compatible runtime for dynamic queries (and not only).
We will indeed be doing this, but not in this task. See #3882 which is itself dependent upon other rework like #1757.
#28 Updated by Dănuț Filimon over 1 year ago
- % Done changed from 100 to 80
- Status changed from Review to WIP
Resuming work for #9396-25.
#29 Updated by Dănuț Filimon over 1 year ago
Alexandru Lungu wrote:
This does not happen, the literal type remains STRING. Do you have an example where this happens?Please investigate why
tt.f1 = LENGTH('abc')is hitting the switch-case, makingvar4glTypedifferent fromliteralType.
Scenario:
- 9396a/15582: Reaches DynamicConversionHelper.injectVariable(), in step 2 the var4glType is assigned a STRING and the switch case is not hit.
- 9396a/15588: Reaches DynamicConversionHelper.isComplexVariableInjection(), the ast.getType() is STRING and does not change.
#30 Updated by Alexandru Lungu over 1 year ago
Danut, I am trying to drag the discussion to the point where proving that the error occurs only when var4glType and literalType are different. You stated in #9396-13 that the example with LENGTH should fail - this means that var4glType and literalType are different, right?
#31 Updated by Dănuț Filimon over 1 year ago
Alexandru Lungu wrote:
Danut, I am trying to drag the discussion to the point where proving that the error occurs only when
var4glTypeandliteralTypeare different. You stated in #9396-13 that the example with LENGTH should fail - this means thatvar4glTypeandliteralTypeare different, right?
var4glType and literalType should be different indeed.
#32 Updated by Dănuț Filimon over 1 year ago
I thought about this and found that we have a map storing function definitions in SignatureHelper (map_func), this can get the return type needed to check against the other side of the operation. But a better idea is to check this in DynamicQueryHelper.extractParams() when iterating the literals by taking a look at the parent and checking if it's a function available in the map_func.