.CM  SCRIPT , Version - 1.1 , last edited by Manuela Rathmann
.ad 8
.bm 8
.fm 4
.bt $Copyright (c) 1997-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VSP47$
.tt 2 $$$
.TT 3 $$ORACLE-Conversions$1997-07-01$
***********************************************************
.nf

.nf

.nf

    ========== licence begin  GPL
    Copyright (c) 1997-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
.fo


.fo


.fo
.nf
.sp
MODULE  :  ORACLE-Conversions
=========
.sp
Purpose : Conversion from ORACLE to VDN-Number and vice versa
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              s47ogdat (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    VAR res    : tsp00_NumError);
 
        PROCEDURE
              s47ogtim (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    VAR res    : tsp00_NumError);
 
        PROCEDURE
              s47ogstp (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    VAR res    : tsp00_NumError);
 
        PROCEDURE
              s47ognum (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    slen       : integer;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    dlen       : integer;
                    dfrac      : integer;
                    VAR res    : tsp00_NumError);
 
        PROCEDURE
              s47opnum (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    slen       : tsp00_Int2;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    VAR dlen   : tsp00_Int2;
                    dfrac      : integer;
                    VAR res    : tsp00_NumError);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              RTE-Extension-30 : VSP30;
 
        FUNCTION
              s30klen (VAR str : tsp00_MoveObj;
                    val : char; cnt : integer) : integer;
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : 
.sp
.cp 3
Created : 1982-06-28
.sp
.cp 3
Version : 1997-12-23
.sp
.cp 3
Release :  7.0   Date : 1997-07-01
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
.sp;.nf
        PROCEDURE
              s47ogdat (
                    VAR source : tsp00_MoveObj;
                    spos       : integer;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : integer;
                    VAR res    : tsp00_NumError);
.sp
Meaning of the parameters:
.sp
        source : array or record containing the input (ORACLE date)
        spos   : position of the date in this array or record
        dest   : array or record containing the output (VDN date)
        dpos   : position of the date in this array or record
        res    : response concerning success or error situations
.sp;.fo
The ORACLE date value of fixed 7 bytes length is converted to a SQL-DB
date value of fixed 8 bytes length. The first four bytes of the ORACLE date
contain the date, the last three bytes contain a time value.
Each byte of the date part is interpreted as integer and transformed
into it's corresponding two characters.
.sp 2;.nf
        PROCEDURE
              s47ogtim (
                    VAR source : tsp00_MoveObj;
                    spos       : integer;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : integer;
                    VAR res    : tsp00_NumError);
.sp
Meaning of the parameters:
.sp
        source : array or record containing the input (ORACLE date)
        spos   : position of the date in this array or record
        dest   : array or record containing the output (VDN date)
        dpos   : position of the date in this array or record
        res    : response concerning success or error situations
.sp;.fo
The ORACLE date value of fixed 7 bytes length is converted to a SQL-DB
time value of fixed 8 bytes length. The first four bytes of the ORACLE date
contain the date, the last three bytes contain the time.
The first two characters of the SQL-DB time value are always '0'.
Then each byte of the time part is interpreted as integer and transformed
into it's corresponding two characters.
.sp 2;.nf
PROCEDURE
      s47ogstp (
            VAR source : tsp00_MoveObj;
            spos       : integer;
            VAR dest   : tsp00_MoveObj;
            dpos       : integer;
            VAR res    : tsp00_NumError);
.sp
Meaning of the parameters:
.sp
        source : array or record containing the input (ORACLE date)
        spos   : position of the date in this array or record
        dest   : array or record containing the output (VDN date)
        dpos   : position of the date in this array or record
        res    : response concerning success or error situations
.sp;.fo
The ORACLE date value of fixed 7 bytes length is converted to a SQL-DB
timestamp of fixed 20 bytes length. The ORACLE date corresponds
to the first part of a SQL-DB timestamp value,
each ORACLE byte is interpreted as integer and transformed
into it's corresponding two SQL-DB characters.
The missing milli, micro and nano seconds of the timestamp are set to '0'.
.sp 2;.nf
        PROCEDURE
              s47ognum (
                    VAR source : tsp00_MoveObj;
                    spos       : integer;
                    slen       : integer;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : integer;
                    dlen       : integer;
                    dfrac      : integer;
                    VAR res    : tsp00_NumError);
.sp
Meaning of the parameters:
.sp
        source : array or record containing the input (ORACLE number)
        spos   : position of the number in this array or record
        slen   : length of the number in bytes
        dest   : array or record containing the output (VDN number)
        dpos   : position of the number in this array or record
        dlen   : length of the number in digits
        dfrac  : fraction of the number resp. float_frac
        res    : response concerning success or error situations
.sp;.fo
The ORACLE number is converted to a SQL-DB number of the size
specified via "dlen" and "dfrac". The result is equivalent
to that of any VSP41 procedure.
.sp 2;.nf
        PROCEDURE
              s47opnum (
                    VAR source : tsp00_MoveObj;
                    spos       : tsp00_Int4;
                    slen       : tsp00_Int2;
                    VAR dest   : tsp00_MoveObj;
                    dpos       : tsp00_Int4;
                    VAR dlen   : tsp00_Int2;
                    dfrac      : integer;
                    VAR res    : tsp00_NumError);
.sp
Meaning of the parameters:
.sp
        source : array or record containing the input (VDN number)
        spos   : position of the number in this array or record
        slen   : length of the number in digits
        dest   : array or record containing the output (ORACLE number)
        dpos   : position of the number in this array or record
        dlen   : in:  max. length of the number in bytes of output area
                 out: length of the number in bytes used (zero's truncated
        res    : response concerning success or error situations
.sp;.fo
The internal number is converted to an ORACLE number of the size
specified via "dlen".
.sp 2
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description                                        :
 
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
(*------------------------------*) 
 
PROCEDURE
      s47ogdat (
            VAR source : tsp00_MoveObj;
            spos       : tsp00_Int4;
            VAR dest   : tsp00_MoveObj;
            dpos       : tsp00_Int4;
            VAR res    : tsp00_NumError);
 
VAR
      i        : integer;
      j        : tsp00_Int4;
      help     : ARRAY [1..4] OF integer;
 
BEGIN
(* oracle date = 7 binary bytes : *)
(* Century, Year, Month, Day, hour, minute, second *)
(* sqldb date = 8 char bytes : *)
(* 4 bytes Year incl. century, 2 bytes Month, 2 bytes Day *)
res := num_ok;
FOR i := 0 TO 1 DO
    IF  ord (source [spos + i]) >= 100
    THEN
        (* oracle century = 119 instead of 19, year = 185 instead of 85 *)
        help [i + 1] := ord (source [spos + i]) MOD 100
    ELSE
        help [i + 1] := ord (source [spos + i]);
    (*ENDIF*) 
(*ENDFOR*) 
FOR i := 2 TO 3 DO
    help [i + 1] := ord (source [spos + i]);
(*ENDFOR*) 
j := dpos;
FOR i := 1 TO 4 DO
    BEGIN
    IF  help [i] > 99
    THEN
        res := num_invalid
    ELSE
        BEGIN
        dest [  j  ] := chr (help [i] DIV 10 + ord ('0'));
        dest [j + 1] := chr (help [i] MOD 10 + ord ('0'));
        j := j + 2;
        END;
    (*ENDIF*) 
    END;
(*ENDFOR*) 
END; (* s47ogdat *)
 
(*------------------------------*) 
 
PROCEDURE
      s47ogtim (
            VAR source : tsp00_MoveObj;
            spos       : tsp00_Int4;
            VAR dest   : tsp00_MoveObj;
            dpos       : tsp00_Int4;
            VAR res    : tsp00_NumError);
 
VAR
      hours    : integer;
      minutes  : integer;
      seconds  : integer;
 
BEGIN
(* oracle date = 7 binary bytes : *)
(* century, year, month, day, Hour, Minute, Second *)
(* ATTENTION! reason for integer transformation:   *)
(*       Oracle stores time values like 12h29m60s! *)
(* sqldb time = 8 char bytes : *)
(* 4 bytes Hour, 2 bytes Minute, 2 bytes Second *)
seconds := (3600 * (ord (source [spos + 4]) - 1))
      + (60 * (ord (source [spos + 5]) - 1))
      + (ord (source [spos + 6]) - 1);
hours := seconds DIV 3600;
seconds := seconds - (hours * 3600);
minutes := seconds DIV 60;
seconds := seconds - (minutes * 60);
dest [dpos]     := '0';
dest [dpos + 1] := '0';
dest [dpos + 2] := chr (hours DIV 10 + ord ('0'));
dest [dpos + 3] := chr (hours MOD 10 + ord ('0'));
dest [dpos + 4] := chr (minutes DIV 10 + ord ('0'));
dest [dpos + 5] := chr (minutes MOD 10 + ord ('0'));
dest [dpos + 6] := chr (seconds DIV 10 + ord ('0'));
dest [dpos + 7] := chr (seconds MOD 10 + ord ('0'));
res := num_ok;
END; (* s47ogtim *)
 
(*------------------------------*) 
 
PROCEDURE
      s47ogstp (
            VAR source : tsp00_MoveObj;
            spos       : tsp00_Int4;
            VAR dest   : tsp00_MoveObj;
            dpos       : tsp00_Int4;
            VAR res    : tsp00_NumError);
 
VAR
      i : integer;
 
BEGIN
(* oracle date = 7 binary bytes : *)
(* Century, Year, Month, Day, Hour, Minute, Second *)
(* sqldb timestamp = 20 char bytes : *)
(* first 14 bytes corresponding to the 7 binary bytes, *)
(* last 6 bytes milli-, micro- and nano seconds *)
s47ogtim (source, spos, dest, dpos + 6, res);
IF  res = num_ok
THEN
    s47ogdat (source, spos, dest, dpos, res);
(*ENDIF*) 
IF  res = num_ok
THEN
    FOR i := 15 TO mxsp_timestamp DO
        dest [dpos + i - 1] := '0';
    (*ENDFOR*) 
(*ENDIF*) 
END; (* s47ogstp *)
 
(*------------------------------*) 
 
PROCEDURE
      s47ognum (
            VAR source : tsp00_MoveObj;
            spos       : tsp00_Int4;
            slen       : integer;
            VAR dest   : tsp00_MoveObj;
            dpos       : tsp00_Int4;
            dlen       : integer;
            dfrac      : integer;
            VAR res    : tsp00_NumError);
 
VAR
      i        : integer;
      j        : integer;
      digit    : integer;
      shift    : integer;
      sdigs    : integer;
      sfrac    : integer;
      hi_dig   : integer;
      lo_dig   : integer;
      negative : boolean;
      all_done : boolean;
      mantissa : ARRAY [1..40] OF integer;
 
BEGIN
res := num_ok;
IF  source [spos] = csp_zero_exponent
THEN
    BEGIN
    (* ZERO *)
    dest [dpos] := source [spos];
    FOR i := 1 TO (dlen + 1) DIV 2 DO
        dest [dpos + i] := chr (0);
    (*ENDFOR*) 
    all_done := true;
    END
ELSE
    all_done := false;
(*ENDIF*) 
IF  NOT all_done
THEN
    BEGIN
    IF  source [spos] > csp_zero_exponent
    THEN
        BEGIN
        shift := ord (source [spos]) - csp_zero_exp_value - 64;
        negative := false;
        END
    ELSE
        BEGIN
        shift := 127 - 64 - ord (source [spos]);
        negative := true;
        IF  source [spos + slen - 1] = chr (102)
        THEN
            (* 102 is stop signal for lt maxlen negative numbers *)
            slen := slen - 1;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    sdigs := 0;
    FOR i := 1 TO slen - 1 DO
        BEGIN
        (* to avoid binary zeros 1 has been added to value of digit *)
        digit := ord (source [spos + i]) - 1;
        IF  negative
        THEN
            (* a negative digit is the 100's complement of the corresponding *)
            (* positive digit *)
            digit := 100 - digit;
        (*ENDIF*) 
        mantissa [sdigs + 1] := digit DIV 10;
        mantissa [sdigs + 2] := digit MOD 10;
        sdigs := sdigs + 2;
        END;
    (*ENDFOR*) 
    shift := shift * 2; (* oracle shift = * 100, sqldb shift = * 10 *)
&   ifdef trace
    writeln ('vsp47 sfrac ', sfrac);
&   endif
    WHILE mantissa [sdigs] = 0 DO
        sdigs := sdigs - 1;
    (*ENDWHILE*) 
    sfrac := abs (shift - sdigs);
    IF  mantissa [1] = 0
    THEN
        BEGIN
        sdigs := sdigs - 1;
        IF  shift >= 0
        THEN
            shift := shift - 1;
        (*ENDIF*) 
        END;
&   ifdef trace
    (*ENDIF*) 
    writeln ('vsp47 sdigs ', sdigs);
    writeln ('vsp47 shift ', shift);
    writeln ('vsp47 mantissa ');
    FOR i := 1 TO sdigs + 1 DO
        write (mantissa [i] : 3);
    (*ENDFOR*) 
    writeln;
&   endif
    IF  (shift < - 63) OR (shift > + 63)
    THEN
        BEGIN
        res := num_overflow;
        all_done := true;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  NOT all_done
THEN
    IF  dfrac = csp_float_frac
    THEN
        BEGIN
        IF  sdigs > dlen
        THEN
            res := num_trunc;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  (sdigs - sfrac) > (dlen - dfrac)
        THEN
            BEGIN
            res := num_overflow;
            all_done := true;
            END
        ELSE
            IF  sfrac > dfrac
            THEN
                res := num_trunc;
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDIF*) 
IF  NOT all_done
THEN
    BEGIN
    IF  negative
    THEN
        dest [dpos] := chr (csp_zero_exp_value - 64 - shift)
    ELSE
        dest [dpos] := chr (csp_zero_exp_value + 64 + shift);
    (*ENDIF*) 
    IF  mantissa [1] = 0
    THEN
        BEGIN
        i := 1;
        sdigs := sdigs + 1;
        IF  NOT odd (sdigs)
        THEN
            BEGIN
            sdigs := sdigs + 1;
            mantissa [sdigs] := 0;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        i := 0;
        IF  odd (sdigs)
        THEN
            BEGIN
            sdigs := sdigs + 1;
            mantissa [sdigs] := 0;
            END;
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    j := 1;
    WHILE (i + 2 <= sdigs) AND (j <= (dlen + 1) DIV 2) DO
        BEGIN
        hi_dig := mantissa [i + 1];
        lo_dig := mantissa [i + 2];
&       ifdef trace
        writeln ('vsp47 hi_dig, lo_dig ', hi_dig:3, lo_dig:3);
&       endif
        dest [dpos + j] := chr (hi_dig * 16 + lo_dig);
        i := i + 2;
        j := j + 1;
        END;
    (*ENDWHILE*) 
    FOR i := j TO (dlen + 1) DIV 2 DO
        dest [dpos + i] := chr (0);
    (*ENDFOR*) 
    IF  negative
    THEN
        sp47_complement (dest, dpos + 1, (dlen + 1) DIV 2);
    (*ENDIF*) 
    END;
(*ENDIF*) 
END; (* s47ognum *)
 
(*------------------------------*) 
 
PROCEDURE
      sp47_complement (
            VAR dest : tsp00_MoveObj;
            mstart   : tsp00_Int4;
            mlen     : integer);
 
VAR
      last  : tsp00_Int4;
      low   : integer;
      high  : integer;
      i     : tsp00_Int4;
      a     : integer;
 
BEGIN
last := mstart + mlen - 1;
WHILE (ord (dest [last] ) = 0) AND (last >= mstart) DO
    last := last - 1;
(*ENDWHILE*) 
IF  last >= mstart
THEN
    BEGIN
    a := ord (dest [last] );
    IF  (a MOD 16) = 0
    THEN
        a := a - 7
    ELSE
        a := a - 1;
    (*ENDIF*) 
    dest [last] := chr (a);
    FOR i := mstart TO last DO
        BEGIN
        high := 9 - ord (dest [i] ) DIV 16;
        low  := 9 - ord (dest [i] ) MOD 16;
        dest [i] := chr (high * 16 + low);
        END;
    (*ENDFOR*) 
    END;
(*ENDIF*) 
END; (* sp47_complement *)
 
(*------------------------------*) 
 
PROCEDURE
      s47opnum (
            VAR source : tsp00_MoveObj;
            spos       : tsp00_Int4;
            slen       : tsp00_Int2;
            VAR dest   : tsp00_MoveObj;
            dpos       : tsp00_Int4;
            VAR dlen   : tsp00_Int2;
            dfrac      : integer;
            VAR res    : tsp00_NumError);
 
VAR
      i        : integer;
      j        : integer;
      shift    : integer;
      digit    : integer;
      sfrac    : integer;
      mantissa : ARRAY [1..40] OF integer;
      negative : boolean;
      zero_flg : boolean;
 
BEGIN
res := num_ok;
shift       := 0;
negative    := FALSE;
zero_flg    := FALSE;
IF  source [spos] = csp_zero_exponent
THEN
    BEGIN
    (* ZERO *)
    slen        := 0;
    zero_flg    := TRUE;
    END
ELSE
    BEGIN
    (* Truncate trailing zero bytes because Oracle doesn't store them *)
    i := s30klen( source, chr(0), spos + (slen+1) DIV 2 );
    slen := (i-spos)*2;
    (* Truncate trailing zero in last Byte *)
    IF  ( ord(source[spos + (slen DIV 2)]) MOD 16 ) = 0
    THEN
        slen := slen -1;
    (*ENDIF*) 
    IF  source [spos] > csp_zero_exponent
    THEN
        BEGIN
        (* POSITIVE *)
        shift := ord( source [spos] ) - csp_zero_exp_value - 64;
        negative:=false;
        mantissa[1] := 0;
        i := 1;
        WHILE ( i <= slen ) DO
            BEGIN
            digit := ord (source [spos+(i+1) DIV 2]);
            mantissa[i+1] := digit DIV 16;
            mantissa[i+2] := digit MOD 16;
            i := i + 2;
            END;
        (*ENDWHILE*) 
        mantissa[slen+2] := 0;
        END
    ELSE
        BEGIN
        (* NEGATIVE *)
        shift := csp_zero_exp_value - 64 - ord( source [spos] );
        negative:=true;
        mantissa[1] := 0;
        i := 1;
        WHILE ( i <= slen ) DO
            BEGIN
            digit := ord (source [spos+(i+1) DIV 2]);
            mantissa[i+1]   := 9 - digit DIV 16;
            mantissa[i+2]   := 9 - digit MOD 16;
            i := i + 2;
            END;
        (*ENDWHILE*) 
        mantissa[slen+1] := mantissa[slen+1] + 1;
        mantissa[slen+2] := 0;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
sfrac := abs(shift-slen);
(* Each Oracle Digit is a base 100 digit   (out DB has base 10) *)
(* therefore a '0' digit may have to be prefixed     *)
i := 1;
IF  (( shift MOD 2 ) = 1 )
THEN
    BEGIN
    (* prefix zero digit *)
    i     := 0;
    shift := shift + 1;
    END;
(* dlen includes the sign/exponent byte *)
(*ENDIF*) 
IF  ( dfrac  = csp_float_frac )
THEN
    BEGIN
    IF  (( (slen + 1) DIV 2) > dlen )
    THEN
        res := num_trunc;
    (*ENDIF*) 
    END
ELSE
    BEGIN
    IF  ( shift > (dlen-1)*2 )
    THEN
        res := num_overflow
    ELSE
        IF  sfrac > dfrac
        THEN
            res := num_trunc;
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  ( res <> num_overflow )
THEN
    BEGIN
    IF  ( negative )
    THEN
        BEGIN
        dest[dpos] := chr(127 - 64 - (shift+1) DIV 2);
        j := 1;
        WHILE ( i <= slen ) DO
            BEGIN
            dest[dpos+j] := chr(100 - (mantissa[i+1]*10 +
                  mantissa[i+2] - 1 ));
            i := i+2;
            j := j+1;
            END;
        (*ENDWHILE*) 
        IF  ( j < dlen )
        THEN
            BEGIN
            dest[dpos+j] := chr(102);
            dlen := j+1;
            END;
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  ( zero_flg )
        THEN
            dest [dpos] := csp_zero_exponent
        ELSE
            dest[dpos] := chr(csp_zero_exp_value + 64 + (shift+1) DIV 2);
        (*ENDIF*) 
        j := 1;
        WHILE ( i <= slen ) DO
            BEGIN
            dest[dpos+j] := chr(mantissa[i+1]*10 +
                  mantissa[i+2] + 1 );
            i := i+2;
            j := j+1;
            END;
        (*ENDWHILE*) 
        dlen := j;
        END;
    (*ENDIF*) 
    END;
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :        188
*-PRETTY-*  lines of code :        527        PRETTY  3.09 
*-PRETTY-*  lines in file :        788         1992-11-23 
.PA 
