Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Usenet -> c.d.o.server -> Re: HPUX-Oracle8: forcing fixed width 2-byte char string over SqlNet/Net8
Marc,
You didn't really ask a question... simply stated what you were trying to do... and you also didn't state what problem you are having, other than you can't find documentation. Perhaps something in the following will help you understand what's going on...
Other than that, ASK A QUESTION!
Good luck!
David R.
Title: Fortran OCI Guidelines on HP MPE Creation Date: 10 May 1994 Abstract: This article shows how to use the Oracle Call Interfaces with Fortran 77/iX. EQUIVALENCE forces alignment of INTEGER*2 variables on word boundaries. All OCI routine parameters are required. Source code of a sample Fortran OCI program is included.Keywords: HP;MPE;FORTRAN;ORACLE;CALL;INTERFACES;PROGRAMMING;LANGUAGE
Fortran OCI Guidelines on HP MPE
Problem: A Fortran OCI program on HP MPE aborts and dumps.
ABORT: FSAMPBAD.OCI.CSUPPORT
NM USER 370.00307abc ocirlo+$94
NM PROG 5b9.00005fe4 main__+$2bc
Program terminated in an error state. (CIERR 976)
:
Discussion:
For backward compatibility and memory conservation, Fortran 77/iX
aligns
INTEGER*2 arrays on half-word, or two-byte, boundaries. However, the
C routines that comprise OCI expect all variables to be aligned on
full-word, or four-byte, boundaries.
Solution:
INTEGER*4 foo(16) INTEGER*2 LDA(32) EQUIVALENCE (foo,LDA) INTEGER*4 foo2(16,2) INTEGER*2 CURS(32,2) EQUIVALENCE (foo2,CURS)
Parameters to some OCI routines documented as optional in the Programmer's Guide are in fact required for OCI programs on HP MPE. The ODEFIN, ODSC, OBNDRV and OBNDRN routines require at least dummy variables for all parameters. Square brackets in the documentation indicate that the parameter is an address.
C routines expect parameters to be passed by reference or by value. Fortran 77/iX passes all parameters by reference by default. HP provides two mechanisms for controlling the default: the $ALIAS compiler directive and the %REF/%VAL parameter modifiers. The sample uses the %REF/%VAL extensions as available on some other platforms. For example:
CALL OLON(LDA(1), %REF(UID), %VAL(UIDL), %REF(PSW), %VAL(PSWL), 1 %VAL(0)) In conclusion, Fortran OCI programs can be used on HP MPE systems once some platform-specific necessities are taken into account. The sample program, once prepared according to the above guidelines, runs correctly.
:run fsampprg
Logged on to ORACLE as user: SCOTT
Enter employee name (or 0 to QUIT) : Burdman
Enter employee job : Tech
Enter employee salary: 4321
Enter employee dept : 40
Burdman added to the OPERATIONS department as employee# 7954
Enter employee name (or 0 to QUIT) : 0 STOP End of the FORTRAN/ORACLE example program.
END OF PROGRAM
:
Sample Fortran Source Code
C ===================== start of Fortran source code $tables on PROGRAM FSAMP
C
C FSAMP IS A SIMPLE EXAMPLE PROGRAM WHICH ADDS NEW EMPLOYEE C ROWS TO THE PERSONNEL DATA BASE. CHECKING C IS DONE TO INSURE THE INTEGRITY OF THE DATA BASE. C THE EMPLOYEE NUMBERS ARE AUTOMATICALLY SELECTED USING C THE CURRENT MAXIMUM EMPLOYEE NUMBER AS THE START. C IF ANY EMPLOYEE NUMBER IS A DUPLICATE, IT IS SKIPPED. C THE PROGRAM QUERIES THE USER FOR DATA AS FOLLOWS: C C Enter employee name : C Enter employee job : C Enter employee salary: C Enter employee dept : C C IF "0" IS ENTERED FOR THE EMPLOYEE NAME, THEN THE PROGRAM C TERMINATES. C C IF THE ROW IS SUCCESSFULLY INSERTED, THE FOLLOWING C IS PRINTED: C C ENAME added to DNAME department as employee # NNNNN C C THE MAXIMUM LENGTHS OF THE 'ENAME', 'JOB', AND 'DNAME' C COLUMNS WILL BE DETERMINED BY THE ODSC CALL. C C NOTE: VAX FORTRAN, BY DEFAULT, PASSES ALL CHARACTER STRING VARIABLES C (i.e. VARIABLES DECLARED AS CHARACTER*N) BY DESCRIPTOR. SINCE OCI C ADDRESS PARAMETERS MUST BE PASSED BY REFERENCE, ALL CHARACTER C STRING VARIABLES IN THE FOLLOWING PROGRAM ARE PASSED USING THE C VAX FORTRAN EXTENSION: %REF. C TO COMPILE THIS PROGRAM ON OTHER PORTS, SIMPLY REMOVE THE C REFERENCES TO %REF.
IMPLICIT INTEGER (A-Z)
C MPE/iX need these EQUIVALENCES to force Fortran to align the arrays
to
C 4-byte boundary as expected C.
INTEGER*4 foo(16) INTEGER*2 LDA(32) EQUIVALENCE (foo,LDA) INTEGER*4 foo2(16,2) INTEGER*2 CURS(32,2) EQUIVALENCE (foo2,CURS) CHARACTER*5 UID, PSW INTEGER*4 UIDL, PSWL
C character string vars to hold the SQL statements
CHARACTER*38 SMAX CHARACTER*26 SEMP C CHARACTER*89 INS
CHARACTER*92 INS CHARACTER*38 SEL
C (MPE/iX) These variables are needed for calls to ODEFIN, ODSC,
OBNDRV and
C OBNDRN because they need pointers to valid addresses. Parameters are
not
C optional. Square brackets in doc indicates the parameter is an
address.
INTEGER*2 INDP INTEGER*2 RETL INTEGER*2 RCODE INTEGER*2 FSIZE INTEGER*2 DBTYPE CHARACTER*40 CBUF INTEGER*2 CBUFL INTEGER*2 DSIZE
C integer vars to the length of the SQL statements
INTEGER*4 SMAXL, SEMPL, INSL, SELL C program vars to be bound to SQL substitution vars and select-list fields
INTEGER*4 EMPNO, DEPTNO, SAL CHARACTER*10 ENAME CHARACTER*9 JOB CHARACTER*14 DNAME
C actual lengths of columns
INTEGER*2 ENAMES, JOBS, DNAMES C maximum lengths of program vars
INTEGER*4 ENAMEL, JOBL, DNAMEL, SALL, EMPNOL, DEPTL C character strings for SQL substitution vars
CHARACTER*6 ENON CHARACTER*6 ENAN CHARACTER*4 JOBN CHARACTER*4 SALN CHARACTER*7 DEPTN
C lengths of character strings for SQL substitution vars
INTEGER*4 ENONL, ENANL, JOBNL, SALNL, DEPTNL C
C INITIALIZE VARIABLES
C
SMAX = 'SELECT NVL(MAX(EMPNO),0) FROM EMP' SMAXL = 33 SEMP = 'SELECT ENAME,JOB FROM EMP' SEMPL = 26 C INS = 'INSERT INTO EMP(EMPNO,ENAME,JOB,SAL, C 1 DEPTNO) VALUES (:EMPNO,:ENAME,:JOB,:SAL,:DEPTNO)' C INSL = 89
INS = 'INSERT INTO EMP(EMPNO,ENAME,JOB,SAL,DEPTNO) VALUES 1(:EMPNO,:ENAME,:JOB,:SAL,:DEPTNO)' INSL = 92 SEL = 'SELECT DNAME FROM DEPT WHERE DEPTNO=:1' SELL = 38 ENAMEL = 10 JOBL = 9 DNAMEL = 14 EMPNOL = 4 DEPTL = 4 SALL = 4 ENON = ':EMPNO' ENAN = ':ENAME' JOBN = ':JOB' SALN = ':SAL' DEPTN = ':DEPTNO' ENONL = 6 ENANL = 6 JOBNL = 4 SALNL = 4 DEPTNL = 7
C
C LOGON TO ORACLE
C
UID = 'SCOTT' UIDL = 5 PSW = 'TIGER' PSWL = 5
C Note: %REF is a VAXISM (see discussion at the beginning of the program)
C MPE/iX Fortran pass parameters by reference, unless %VAL is used.
CALL OLON(LDA(1), %REF(UID), %VAL(UIDL), %REF(PSW), %VAL(PSWL), 1 %VAL(0)) IF (LDA(1).NE.0) THEN CALL ERRLDA(LDA(1)) GO TO 700 END IF WRITE(*, 11) UID
C
C OPEN TWO CURSORS FOR THE PERSONNEL DATA BASE C
CALL OOPEN(CURS(1,1), LDA)
IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF CALL OOPEN(CURS(1,2), LDA(1)) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF
C
C TURN OFF AUTO-COMMIT. NOTE: THE DEFAULT IS OFF, SO THIS COULD
BE OMITTED
C
CALL OCOF(LDA(1))
IF (LDA(1).NE.0) THEN CALL ERRLDA(LDA) GO TO 700 END IF
C
C RETRIEVE THE CURRENT MAXIMUM EMPLOYEE NUMBER C
C parse the SQL statement. Note that %REF is a VAXISM (see
discussion at
C the beginning of the program).
CALL OSQL3(CURS(1,1), %REF(SMAX), %VAL(SMAXL))
IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF
C define a buffer to receive the MAX(EMPNO) from ORACLE
C (MPE/iX) These parameters must be provided.
CALL ODEFIN(CURS(1,1), %VAL(1), EMPNO, %VAL(EMPNOL), %VAL(3), 1 0, INDP, 0, 0, 0, RETL, RCODE) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF
C execute the SQL statement
CALL OEXEC(CURS(1,1))
IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C fetch the data from ORACLE into the defined buffer CALL OFETCH(CURS(1,1)) IF (CURS(1,1).EQ.0) GO TO 50 IF (CURS(7,1).NE.1403) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C a cursor return code of 1403 means that no row satisfied the query, C so generate the first empno EMPNO=10
C DETERMINE THE MAX LENGTH OF THE EMPLOYEE NAME AND JOB TITLE. C PARSE THE SQL STATEMENT - IT WILL NOT BE EXECUTED C DESCRIBE THE TWO FIELDS SPECIFIED IN THE SQL STATEMENTC
C Note: %REF is a VAXISM (see discussion at the beginning of the program).
CALL OSQL3(CURS(1,1), %REF(SEMP), %VAL(SEMPL))
IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C (MPE/iX) These parameters must be provided. CBUFL = 40 CALL ODSC(CURS(1,1), %VAL(1), ENAMES, FSIZE, RCODE, DBTYPE, 1 %REF(CBUF), CBUFL, DSIZE) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF IF (ENAMES .GT. ENAMEL) THEN WRITE(*, 21) 21 FORMAT('ENAME too large for buffer.') GO TO 700 END IF C (MPE/iX) These parameters must be provided. CBUFL = 40 CALL ODSC(CURS(1,1), %VAL(2), JOBS, FSIZE, RCODE, DBTYPE, 1 %REF(CBUF), CBUFL, DSIZE) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF IF (JOBS .GT. JOBL) THEN WRITE(*, 31) 31 FORMAT('JOB too large for buffer.') GO TO 700 END IF
C
C PARSE THE INSERT AND SELECT STATEMENTS C
C Note: %REF is a VAXISM (see discussion at the beginning of the program
CALL OSQL3(CURS(1,1), %REF(INS), %VAL(INSL))
IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF
C Note: %REF is a VAXISM (see discussion at the beginning of the program
CALL OSQL3(CURS(1,2), %REF(SEL), %VAL(SELL))
IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF
C
C BIND ALL SQL SUBSTITUTION VARIABLES. C Note: %REF is a VAXISM (see discussion at the beginning of theprogram).
C (MPE/iX) These parameters must be provided.
CALL OBNDRV(CURS(1,1), %REF(ENON), %VAL(ENONL), EMPNO, 1 %VAL(EMPNOL), %VAL(3), 0, INDP, 0, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C (MPE/iX) These parameters must be provided. CALL OBNDRV(CURS(1,1), %REF(ENAN), %VAL(ENANL), %REF(ENAME), 1 %VAL(ENAMEL), %VAL(1), 0, INDP, 0, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C (MPE/iX) These parameters must be provided. CALL OBNDRV(CURS(1,1), %REF(JOBN), %VAL(JOBNL), %REF(JOB), 1 %VAL(JOBL), %VAL(1), 0, INDP, 0, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C (MPE/iX) These parameters must be provided. CALL OBNDRV(CURS(1,1), %REF(SALN), %VAL(SALNL) ,%REF(SAL), 1 %VAL(SALL), %VAL(3), 0, INDP, 0, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF C (MPE/iX) These parameters must be provided. CALL OBNDRV(CURS(1,1), %REF(DEPTN), %VAL(DEPTNL), DEPTNO, 1 %VAL(DEPTL), %VAL(3), 0, INDP, 0, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF
C
C BIND THE DEPTNO VARIABLE
C
C (MPE/iX) These parameters must be provided.
CALL OBNDRN(CURS(1,2), %VAL(1), DEPTNO, %VAL(DEPTL), %VAL(3), 1 0, INDP, 0, 0, 0) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF
C
C DESCRIBE THE 'DNAME' COLUMN - ONLY THE LENGTH IS OF CONCERN C
C (MPE/iX) These parameters must be provided.
CBUFL = 40 CALL ODSC(CURS(1,2), %VAL(1), DNAMES, FSIZE, RCODE, DBTYPE, 1 %REF(CBUF), CBUFL, DSIZE) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF IF (DNAMES .GT. DNAMEL) THEN WRITE(*, 32) 32 FORMAT('DNAME too large for buffer.') GO TO 700 END IF
C
C DEFINE THE BUFFER TO RECEIVE 'DNAME' C
C Note: %REF is a VAXISM (see discussion at the beginning of the program).
C (MPE/iX) These parameters must be provided.
CALL ODEFIN(CURS(1,2), %VAL(1), %REF(DNAME), %VAL(DNAMEL), 1 %VAL(1), 0, INDP, 0, 0, 0, RETL, RCODE) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF
C
C READ THE USER'S INPUT
C
100 CONTINUE
WRITE (*, 120)
120 FORMAT('$Enter employee name (or 0 to QUIT) : ')
READ (*, 130) ENAME
130 FORMAT(A10)
IF (ENAME .EQ. '0') GO TO 700 WRITE (*, 140) 140 FORMAT('$Enter employee job : ') READ (*, 145) JOB 145 FORMAT(A9) WRITE (*,155) 155 FORMAT('$Enter employee salary: ') READ (*, 160) SAL
READ (*, 168) DEPTNO
168 FORMAT(I4)
C
C CHECK FOR A VALID DEPARTMENT# BY EXECUTING THE SELECT STATEMENT C
CALL OEXEC(CURS(1,2))
IF (CURS(1,2).NE.0) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF
C
C FETCH THE ROWS - DEPTNO IS A PRIMARY KEY, SO A MAX OF ONE ROW WILL BE
C FETCHED C IF CURSOR RETURN CODE IS 1403 THEN NO SUCH DEPARTMENT EXISTS.C
CALL OFETCH(CURS(1,2))
IF (CURS(1,2).EQ.0) GO TO 500 IF (CURS(7,2).NE.1403) THEN CALL ERRRPT(CURS(1,2), 2) GO TO 700 END IF WRITE (6,400) 400 FORMAT(1X, 'No such department number') GO TO 300
C
C INCREMENT EMPNO BY 10 C EXECUTE THE INSERT STATEMENT
500 EMPNO = EMPNO + 10
CALL OEXEC(CURS(1,1)) IF (CURS(1,1).EQ.0) GO TO 600
C
C IF THE CALL RETURNS CODE 1 (DUPLICATE VALUE IN INDEX), THEN C GENERATE THE NEXT POSSIBLE EMPLOYEE NUMBERC
IF (CURS(7,1).NE.1) THEN CALL ERRRPT(CURS(1,1), 1) GO TO 700 END IF EMPNO=EMPNO+10 GO TO 500
1 ' department as employee# ', I4, /)
C
C THE ROW HAS BEEN ADDED - COMMIT THIS TRANSACTION. C
CALL OCOM(LDA(1))
IF (LDA(1).NE.0) THEN CALL ERRLDA(LDA(1)) GO TO 700 END IF GO TO 100
C
C EITHER A FATAL ERROR HAS OCCURRED OR THE USER TYPED "0" FOR THE
ENAME.
C REPORT IT TO THE OPERATOR AND EXIT.
C
700 CONTINUE C
C CLOSE THE CURSORS
C
CALL OCLOSE(CURS(1,1)) IF (CURS(1,1).NE.0) CALL ERRRPT(CURS(1,1), 1) CALL OCLOSE(CURS(1,2)) IF (CURS(1,2).NE.0) CALL ERRRPT(CURS(1,2), 2)
C
C LOGOFF FROM ORACLE
C
CALL OLOGOF(LDA(1)) IF (LDA(1).NE.0) CALL ERRLDA(LDA(1)) STOP 'End of the FORTRAN/ORACLE example program.' END SUBROUTINE ERRRPT(CURS, N)
C
C ERRRPT PRINTS THE CURSOR NUMBER, THE ERROR CODE, AND THE C ORACLE FUNCTION CODE. C C CURS IS A CURSOR C N IS THE CURSOR NUMBER
INTEGER*2 CURS(32) CHARACTER*70 ERRMSG
300 WRITE (*, 400) N, CURS(7), CURS(6) 400 FORMAT(1X, 'ORACLE error on cursor ', I1,
1 ': code is ',I5,', op is ',I5)
C Note: %REF is a VAXISM (see discussion at the beginning of the program).
CALL OERMSG(%VAL(CURS(7)), %REF(ERRMSG)) WRITE (*, 20) ERRMSG
C ERRLDA PRINTS THE ERROR CODE, AND THE ORACLE FUNCTION CODE. C
INTEGER*2 LDA(32) CHARACTER*70 ERRMSG WRITE (*, 10) LDA(7)
C Note: %REF is a VAXISM (see note at the beginning of the program).
CALL OERMSG(%VAL(LDA(7)), %REF(ERRMSG)) WRITE (*, 20) ERRMSG
C ===================== End of Fortran source code
References:
Oracle WorldWide CustomerSupport
On Wed, 5 May 1999 16:41:11 -0400, <coopman_at_ix.netcom.com> wrote:
>Hi, > >I am trying to configure a client and server environment to communicate >using fixed width 2 byte character strings over an OCI connection. > >The client runs on HPUX 11.0 as well as the server, but not necessarily on >the same host. >The server is Oracle 8.0.4, but the client may be 7.3.x > >The database characterset is WE8DEC and the client's NLS_LANG is >America_American.WE8DEC. > >I believe that that use of the 2-byte representation is due to some >configuration or compilation option of the client program, which takes >advantage of HP's wchar_t (wide character, 16-bit) implementation, when the >client and server are on similar HP platforms. > >Note: This is not a simple NLS questions, but a lower-level OCI protocol >issue (possibly realted to SqlNet/Net8 data type negotiation/conversion). > >I have been through numerous docs, trial-and-error configurations, and >scanned related usenet groups, but have not found much. Any help would be >appreciated. > >Marc > > >Received on Tue May 18 1999 - 18:06:15 CDT
![]() |
![]() |