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

udr pascal returning char(x) cannot be converted to bigint [CORE5828] #6089

Closed
firebird-automations opened this issue May 17, 2018 · 11 comments

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @livius2

Attachments:
UdrGenRows.pas
Udr.dll

modify udr pascal sample gen_rows and compile with Delphi (maybe this is unreleated to Delphi)

---------------------------------------------------

change result to:

   result: Array\[0\.199\] of AnsiChar;

---------------------------------------------------

and result declaration of procedure under Firebird

    result CHAR\(200\);

---------------------------------------------------

in fetch procedure put '1635721458409799680' as result

---------------------------------------------------

now try select:

SELECT CAST(CAST(P.RESULT AS VARCHAR(200)) AS BIGINT)
FROM gen_rows_pascal(
1
, 100
) p;

arithmetic exception, numeric overflow, or string truncation
string right truncation
expected length 52, actual 200.

---------------------------------------------------

interesting that CAST(CAST(P.RESULT AS VARCHAR(100)) AS BIGINT)
cause

      expected length 100, actual 100\.

---------------------------------------------------

maybe this is releated to CORE5802 but with bigger problem because here cast fail and this prevent to work with data

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

Where is the udr pascal sample gen_rows that you modified?

@firebird-automations
Copy link
Collaborator Author

@firebird-automations
Copy link
Collaborator Author

Commented by: @livius2

I have attached modified UdrGenRows.pas file
and also generated dll (if you trust me)

----------------------------

declaration of procedure
recreate procedure gen_rows_pascal (
start_n integer not null,
end_n integer not null
) returns (
result integer,
nazwa CHAR(200) CHARACTER SET NONE
)
external name 'udr!gen_rows'
engine udr;

----------------------------
and select:

SELECT p.RESULT, p.NAZWA, CAST(p.NAZWA AS BIGINT)
FROM GEN_ROWS_PASCAL ('1', '5') p;

----------------------------

you got an error:

Arithmetic overflow or division by zero has occurred.

Engine Code : 335544321
Engine Message :
arithmetic exception, numeric overflow, or string truncation
string right truncation
expected length 52, actual 200

@firebird-automations
Copy link
Collaborator Author

Modified by: @livius2

Attachment: UdrGenRows.pas [ 13253 ]

Attachment: Udr.dll [ 13254 ]

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

You use StrPCopy to write to the array, but it will write only the string plus a null termination.

A CHAR(x) buffer requires that you write the string padded with spaces, without the null termination.

So to write '12345' to a buffer of size 200, you should write '12345' plus 195 spaces.

@firebird-automations
Copy link
Collaborator Author

Commented by: @livius2

Yes, that's it.
Padding with spaces do the job :)

I wrongly assumed that this have some relation to previous bug.
Thank you for great udr api it is really usefull.

@firebird-automations
Copy link
Collaborator Author

Modified by: @asfernandes

status: Open [ 1 ] => Resolved [ 5 ]

resolution: Won't Fix [ 2 ]

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

Note that that way to create the UDR (without implement a "setup" method), is not recommended.

You have the same problem as of UDFs. A change in the DDL declaration may cause the code to crash the server.

With a "setup" defining the message, the parts become independent and converted from one to another if necessary.

@firebird-automations
Copy link
Collaborator Author

Modified by: @pcisar

status: Resolved [ 5 ] => Closed [ 6 ]

@firebird-automations
Copy link
Collaborator Author

Commented by: @livius2

>>With a "setup" defining the message, the parts become independent and converted from one to another if necessary.

Sorry for offtopic but
is there some sample about your sentence? What should be defined in setup method?

----

OK i know what you mean and i see that i can simply access to metadata provided
and check if declaration is same as i supposed to work in code.

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

You can check it and read it, but you can also force it to be the way the routine wants.

Check the C++ code in https://github.com/FirebirdSQL/firebird/tree/master/examples/udr

These routines uses FB_UDR_MESSAGE macro to do it more easily.

It creates a setup routine that changes messages via message builder.

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