| 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 Customer
Support
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
![]() |
![]() |