I realized that having just copied and modified my old SQL example [now snipped from the quoted reply], that I had overlooked the added requirement in this scenario to account for the input pDecPrecision value. That requirement actually complicates arithmetic expressions which would need to maintain the precision; the scale and precision for the builtin casting functions of the SQL can not be variables, which could make that easier. A simple alternative is to just rebuild the character string representation of the decimal numeric from the HEX() of the raw packed BCD data, and have that string [with a minus symbol and decimal point, as required,] cast directly to the DECIMAL(30,09). The following example uses a string expression, but includes an updated [and this time hopefully correct] arithmetic expression in comments; pHex as raw, pDecLen as decLen, and pDecPrecision as decPrc:


d rtn30p09 s 30p09
d rawLen s 5i00
d rawDig s 5i00
d rawHex s 32a varying
/free
rawLen=%div(decLen:2)+1; // byte length of raw data
rawDig=decLen; // assume odd decLen; no extra zero
if %rem(decLen:2)=0; // even decLen; revise assumption
rawDig=decLen+1; // account extra zero, left pad
endif;
Exec SQL
Set Option Commit=*NONE, Naming=*SYS, DecmPt=*PERIOD;
Exec SQL
set :rawHex=hex( substr( :raw, 1, :rawLen ) );
Exec SQL
set :rtn30p9=cast(
case when right( :rawHex, 1 ) in ('B', 'D')
then '-' else '' end
concat insert( left( :rawHex, :rawDig )
, :rawDig - :decPrc + 1 , 0 , '.' )
/* -- or by arithmetic; replaces snipped version
( dec( left( :rawHex, :rawDig ) , 21, 0 )
* case when right( :rawHex, 1 ) in ('B', 'D')
then -1. else 1. end
) / ( dec( 10**(:decPrc), 10, 00 ) )
*/
as decimal(30, 09) ) ;
// deal with sqlcode\sqlstate as necessary; e.g. overflow
// if more than 21 significant digits
return rtn30p09;


Using the cast to decimal from a string also allows for the input precision to approach or even match the max length of 21 digits for the integer portion; truncated, as coded above. Of course the typed decimal data *DTAARA support only allows up to DEC(24, 9) where each numeric value is the maximum.

Regards, Chuck

On 23 Apr 2012 11:55, CRPence wrote:
<<SNIP>>

On 23 Apr 2012 09:04, Matt Lavinder wrote:
<<SNIP>>
I am trying to write a generic procedure to retrieve a data area
that is a decimal value. Currently, we have to adjust the procedure
every time we need to handle a new size, and then we have to add
variables and specific code for that size.

I am trying to use the QWCRDTAA to retrieve the value and
ultimately want return a decimal of 30p 9 that contains what ever
was found in the data area. Problem is, the data comes back as hex
from QWCRDTAA (the raw decimal data). Obviously I could just MOVE
the data if I wanted to define decimals of all possible sizes, but
then I am back to the very thing I am trying to avoid.

As a part of my procedure, I pass in the definition of the data
area, so I know that at run time. What is the quickest way to get
that raw/hex data into a decimal variable I can work with? If you
were to put the logic I am looking for into a procedure, the
prototype to convert this character/hex data would need to look
something like this:

D HexToPacked pi 30p 9
D pHex 2000a
D pDecLen 5i 0
D pDecPrecision 5i 0

<<SNIP>>


This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].