Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusing message (conversion error from STRING " ") when use parametrized ES and "?" has no explicit CAST() [CORE6463] #6696

Open
firebird-automations opened this issue Jan 6, 2021 · 4 comments

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @pavel-zotov

Run this on 2.5, 3.x and 4.x:

set sqlda_display on;
set term ^;
execute block returns(o_rel_id int) as
begin
execute statement ('select iif(1 <= ?, ?, null) from rdb$database') (2, 3) into o_rel_id;
suspend;
end
^
set term ;^

Output:
1) on 2.5:

INPUT SQLDA version: 1 sqln: 10 sqld: 0

OUTPUT SQLDA version: 1 sqln: 20 sqld: 1
01: sqltype: 497 LONG Nullable sqlscale: 0 sqlsubtype: 0 sqllen: 4
: name: (8)O_REL_ID alias: (8)O_REL_ID
: table: (0) owner: (0)

O\_REL\_ID 

============
Statement failed, SQLSTATE = HY004
Dynamic SQL Error
-SQL error code = -804
-Data type unknown
-At block line: 3, col: 5

2) on 3.x and 4.x:

INPUT message field count: 0

OUTPUT message field count: 1
01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
: name: O_REL_ID alias: O_REL_ID
: table: owner:

O\_REL\_ID 

============
Statement failed, SQLSTATE = 22018
conversion error from string " "
-At block line: 3, col: 5

One need to know in advance that NULL w/o CAST() is considered as CHAR(1), but i could not find this in the $FB_HOME/doc/* and in https://www.firebirdsql.org/file/documentation/html/en/firebirddocs/nullguide/firebird-null-guide.html
Phrase: conversion error from string " " -- definitely looks weird (there is no any text variables / parameters in this example).

Perhaps, it will be better to change this message back to 2.5.x ?

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

"One need to know in advance that NULL w/o CAST() is considered as CHAR(1)", why do you think that is the case? As far as I know it shouldn't have any type in this situation. It looks to me like the behaviour in 2.5 is correct (where it cannot infer the datatype), and the behavior in 3.0 and 4.0 is wrong.

Instead, it looks to me that maybe the datatype is inferred as SQL_NULL, which shouldn't be usable in this context, which is then coerced to a string which is then not convertible to an integer.

@firebird-automations
Copy link
Collaborator Author

Commented by: @pavel-zotov

> why do you think that is the case? // char(1)

Because when i explicitly cast NULL to required datatype (int) then all works fine:

set term ^;
execute block returns(o_rel_id int) as
begin
execute statement ('select iif(1 <= ?, ?, cast(null as int) ) from rdb$database') (2, 3) into o_rel_id;
suspend;
end
^

INPUT message field count: 0

OUTPUT message field count: 1
01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
: name: O_REL_ID alias: O_REL_ID
: table: owner:

O\_REL\_ID 

============
3

PS.
Maybe subject of this ticket is also confusing as null cast/missed cast... :-)

Once again:
1) execute statement ('select iif(1 <= ?, ?, null) from rdb$database') (2, 3) into o_rel_id; ==> Statement failed, SQLSTATE = 22018 / conversion error from string " "
2) execute statement ('select iif(1 <= ?, ?, cast(null as int) ) from rdb$database') (2, 3) into o_rel_id; ==> all OK.

Here we can see nothing about cast parameters ("?"); rather it's about cast NULL literal :-)

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

As I said in my previous comment, it looks like the second parameter is inferred as type SQL_NULL, which isn't usable in this context. When the parameter is then assigned, it gets the value 'not null' instead of 3, that is then coerced to a string which is then not convertible to an integer. The behaviour of 2.5 should probably be retained in this case, or at least SQL_NULL should not be allowed in this context.

I have confirmed this by preparing the statement select iif(1 <= ?, ?, cast(null as int) ) from rdb$database using Jaybird, and checking the type of the second parameter, which is 32767, or a (nullable) SQL_NULL.

@firebird-automations
Copy link
Collaborator Author

Commented by: @mrotteveel

The reason the cast works, is that changes the inference of the parameter to SQL_LONG instead of SQL_NULL (just as would have been if you used iif(1 <= ?, cast(? as int), null)), that is because in an expression like iif(..., ?, VAL), the type of the parameter is inferred from the type of VAL, and if VAL is NULL, then it can only infer SQL_NULL (where in 2.5 it couldn't derive a datatype, so it produced a datatype unknown error), unless you explicitly cast that null to an explicit type.

Repeating my check in Jaybird, the type of the second parameter is (nullable) SQL_LONG in both

select iif(1 <= ?, ?, cast(null as int)) from rdb$database

and

select iif(1 <= ?, cast(? as int), null) from rdb$database

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant