Programmer's Guide to the Oracle7 Server Call Interface | ![]() Library |
![]() Product |
![]() Contents |
![]() Index |
Each of these sample programs is available online. The exact name and storage location of these progams is system dependent. Refer to your Oracle installation or user's guide for details.
This appendix contains listings for the following files:
PROGRAM FDEMO1 *--------------------------------------------------------------- * FDEMO1 is a demonstration program that adds new employee * rows to the personnel data base. Checking * is done to insure the integrity of the data base. * The employee numbers are automatically selected using * the current maximum employee number as the start. * If any employee number is a duplicate, it is skipped. * The program queries the user for data as follows: * * Enter employee name : * Enter employee job : * Enter employee salary: * Enter employee dept : * * If just <cr> is entered for the employee name, * the program terminates. * * If the row is successfully inserted, the following * is printed: * * ENAME added to DNAME department as employee N. * * The maximum lengths of the 'ename', 'job', and 'dname' * columns are determined by an ODESCR call. * * Note: VAX FORTRAN, by default, passes all CHARACTER variables * (variables declared as CHARACTER*N) by descriptor. * To compile this program on systems that pass character * variables by descriptor, insert %REF() where necessary. *--------------------------------------------------------------- IMPLICIT INTEGER (A-Z) INTEGER*2 LDA(32) INTEGER*2 CURS(32,2) INTEGER*2 HDA(256) CHARACTER*20 UID, PSW INTEGER*4 NOBLOK * CHARACTER string vars to hold the SQL statements CHARACTER*60 SMAX CHARACTER*60 SEMP CHARACTER*150 INS CHARACTER*60 SEL INTEGER*4 SMAXL, SEMPL, INSL, SELL * Program vars to be bound to SQL placeholders and * select-list fields. INTEGER*4 EMPNO, DEPTNO, SAL CHARACTER*10 ENAME CHARACTER*10 JOB CHARACTER*14 DNAME * Actual lengths of columns. INTEGER*4 ENAMES, JOBS, DNAMES * Character strings for SQL placeholders. CHARACTER*6 ENON CHARACTER*6 ENAN CHARACTER*4 JOBN CHARACTER*4 SALN CHARACTER*7 DEPTN * Lengths of character strings for SQL placeholders. INTEGER*4 ENONL, ENANL, JOBNL, SALNL, DEPTNL * Parameters for OPARSE. INTEGER*4 NODEFP, V7FLAG * Parameters for ODESCR. INTEGER*2 DTYPE, PREC, SCALE, NULLOK INTEGER*4 DSIZE, CNAMEL CHARACTER*80 CNAME *--------------------------------------------------------------- * Initialize variables. *--------------------------------------------------------------- SMAX = 'SELECT NVL(MAX(EMPNO),0) FROM EMP' SMAXL = LEN_TRIM(SMAX) SEMP = 'SELECT ENAME,JOB FROM EMP' SEMPL= LEN_TRIM(SEMP) INS = 'INSERT INTO EMP(EMPNO,ENAME,JOB,SAL, + DEPTNO) VALUES (:EMPNO,:ENAME,:JOB,:SAL,:DEPTNO)' INSL = LEN_TRIM(INS) SEL = 'SELECT DNAME FROM DEPT WHERE DEPTNO = :1' SELL = LEN_TRIM(SEL) * All in Deferred Mode NODEFP = 1 V7FLAG = 2 ENAMEL = 10 JOBL = 10 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 *--------------------------------------------------------------- * Connect to ORACLE in non-blocking mode. * HDA must be initialized to all zeros before call to OLOG. *--------------------------------------------------------------- UID = 'SCOTT' PSW = 'TIGER' NOBLOK = 0 DATA HDA/256*0/ CALL OLOG(LDA, HDA, UID, LEN_TRIM(UID), + PSW, LEN_TRIM(PSW), 0, -1, NOBLOK) IF (LDA(7).NE.0) THEN CALL ERRRPT(LDA(1), LDA(1)) GO TO 900 END IF WRITE (*, '(1X, A, A20)') 'Logged on to ORACLE as user ', + UID *--------------------------------------------------------------- * Open two cursors for the personnel data base. *--------------------------------------------------------------- CALL OOPEN(CURS(1,1), LDA, 0, -1, -1, 0, -1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OOPEN(CURS(1,2),LDA(1),0, -1, -1, 0, -1) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF *--------------------------------------------------------------- * Turn off auto-commit. Note: the default is off, * so this could be omitted. *--------------------------------------------------------------- CALL OCOF(LDA(1)) IF (LDA(1).NE.0) THEN CALL ERRRPT(LDA(1), LDA(1)) GO TO 700 END IF *--------------------------------------------------------------- * Retrieve the current maximum employee number. *---------------------------------------------------------------- * Parse the SQL statement. CALL OPARSE(CURS(1,1), SMAX, SMAXL, NODEFP, V7FLAG) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF * Define a buffer to receive the MAX(EMPNO) from ORACLE. CALL ODEFIN(CURS(1,1), 1, EMPNO, 4, 3, -1, 0, 0, + -1, -1, 0, 0) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF * Execute the SQL statement. CALL OEXEC(CURS(1,1)) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF * 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(LDA(1), CURS(1,1)) GO TO 700 END IF * A cursor return code of 1403 means that no row * satisfied the query, so generate the first empno. EMPNO=10 50 CONTINUE *--------------------------------------------------------------- * Determine the max length of the employee name and job title. * Parse the SQL statement - it will not be executed. * Describe the two fields specified in the SQL statement. *---------------------------------------------------------------- CALL OPARSE(CURS(1,1), SEMP, SEMPL, NODEFP, V7FLAG) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CNAMEL = 80 CALL ODESCR(CURS(1,1), 1, ENAMES, DTYPE, CNAME, + CNAMEL, DSIZE, PREC, SCALE, NULLOK) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF IF (ENAMES .GT. ENAMEL) THEN WRITE (*, '(1X, A, I2, A, I2)') 'ENAME too large (', + ENAMES, ' for buffer (', ENAMEL, ').' GO TO 700 END IF CNAMEL = 80 CALL ODESCR(CURS(1,1), 2, JOBS, DTYPE, CNAME, + CNAMEL, DSIZE, PREC, SCALE, NULLOK) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF IF (JOBS .GT. JOBL) THEN WRITE (*, '(1X, A, I2, A, I2)') 'JOB too large (', + JOBS, ' for buffer (', JOBL, ').' GO TO 700 END IF *-------------------------------------------------------------- * Parse the insert and select statements. *-------------------------------------------------------------- CALL OPARSE(CURS(1,1), INS, INSL, NODEFP, V7FLAG) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OPARSE(CURS(1,2), SEL, SELL, NODEFP, V7FLAG) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF *-------------------------------------------------------------- * Bind all placeholders. *-------------------------------------------------------------- CALL OBNDRV(CURS(1,1),ENON,LEN(ENON),EMPNO,EMPNOL,3,-1, + 0,0,-1,-1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OBNDRV(CURS(1,1),ENAN,ENANL,ENAME,ENAMEL,1,-1, + 0,0,-1,-1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OBNDRV(CURS(1,1),JOBN,JOBNL,JOB,JOBL,1,-1,0,0,-1,-1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OBNDRV(CURS(1,1),SALN,SALNL,SAL,SALL,3,-1,0,0,-1,-1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF CALL OBNDRV(CURS(1,1),DEPTN,DEPTNL,DEPTNO,DEPTL,3,-1, + 0,0,-1,-1) IF (CURS(1,1).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF *-------------------------------------------------------------- * Bind the DEPTNO variable. *-------------------------------------------------------------- CALL OBNDRN(CURS(1,2), 1, DEPTNO, DEPTL, 3,-1,0,0,-1,-1) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF *-------------------------------------------------------------- * Describe the DNAME column - get the name and length. *-------------------------------------------------------------- DNAMEL = 14 CALL ODESCR(CURS(1,1), 1, DNAMES, DTYPE, DNAME, + DNAMEL, DSIZE, PREC, SCALE, NULLOK) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF IF (DNAMES .GT. DNAMEL) THEN WRITE (*, '(1X, A)') 'DNAME too large for buffer.' GO TO 700 END IF *-------------------------------------------------------------- * Define the buffer to receive DNAME. *-------------------------------------------------------------- CALL ODEFIN(CURS(1,2),1,DNAME,DNAMEL,1,-1,0,0,-1,-1,0,0) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF *-------------------------------------------------------------- * Read the user's input. Statement 100 * starts the main program loop. *-------------------------------------------------------------- 100 WRITE (*, '( A)') + 'Enter employee name (CR to QUIT) : ' READ (*, '(A)'), ENAME IF (LEN_TRIM(ENAME) .EQ. 0) GO TO 700 WRITE (*, '( A)'), 'Enter employee job : ' READ (*, '(A)'), JOB WRITE (*, '( A)') 'Enter employee salary: ' READ (*, '(I6)'), SAL 300 WRITE (*, '( A)') 'Enter employee dept : ' READ (*, '(I6)'), DEPTNO *-------------------------------------------------------------- * Check for a valid department number by * executing the SELECT statement. *-------------------------------------------------------------- CALL OEXEC(CURS(1,2)) IF (CURS(1,2).NE.0) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF *-------------------------------------------------------------- * Fetch the rows - DEPTNO is a primary key, so a max of * one row will be fetched. * If the return code is 1403 no such department exists. *-------------------------------------------------------------- CALL OFETCH(CURS(1,2)) IF (CURS(1,2).EQ.0) GO TO 500 IF (CURS(7,2).NE.1403) THEN CALL ERRRPT(LDA(1), CURS(1,2)) GO TO 700 END IF WRITE (*, '(1X, A)') 'No such department number' GO TO 300 *-------------------------------------------------------------- * Increment EMPNO by 10. * Execute the insert statement. *-------------------------------------------------------------- 500 EMPNO = EMPNO + 10 CALL OEXEC(CURS(1,1)) IF (CURS(1,1).EQ.0) GO TO 600 *-------------------------------------------------------------- * If the call returns code 1 (duplicate value in index), * generate the next possible employee number. *-------------------------------------------------------------- IF (CURS(7,1).NE.1) THEN CALL ERRRPT(LDA(1), CURS(1,1)) GO TO 700 END IF EMPNO=EMPNO+10 GO TO 500 600 WRITE (*, 610) ENAME, DNAME, EMPNO 610 FORMAT(/, 1X, A10, ' added to the ', A14, + ' department as employee# ', I4, /) *-------------------------------------------------------------- * The row has been added - commit this transaction. *-------------------------------------------------------------- CALL OCOM(LDA(1)) IF (LDA(1).NE.0) THEN CALL ERRRPT(LDA(1), LDA(1)) GO TO 700 END IF GO TO 100 *-------------------------------------------------------------- * Either a fatal error has occurred or the user typed * <CR> for the employee name. * Close the cursors, disconnect, and end the program. *-------------------------------------------------------------- 700 CONTINUE CALL OCLOSE(CURS(1,1)) IF (CURS(1,1).NE.0) CALL ERRRPT(LDA(1), CURS(1,1)) CALL OCLOSE(CURS(1,2)) IF (CURS(1,2).NE.0) CALL ERRRPT(LDA(1), CURS(1,2)) CALL OLOGOF(LDA(1)) IF (LDA(1).NE.0) CALL ERRRPT(LDA(1), LDA(1)) 900 STOP END *-------------------------------------------------------------- * ERRRPT prints the cursor number, the error code, and the * OCI function code. * * CURS is a cursor. N is the cursor number. *-------------------------------------------------------------- SUBROUTINE ERRRPT(LDA, CURS) INTEGER*2 CURS(32), LDA(32) CHARACTER*160 ERRMSG IF (CURS(6) .GT. 0) THEN WRITE (*, '(1X, A, I3)') 'ORACLE error processing OCI + function ', CURS(6) END IF CALL OERHMS(LDA(1), CURS(7), ERRMSG, 160) WRITE (*, '(1X, A)') ERRMSG RETURN END INTEGER FUNCTION LEN_TRIM(STRING) CHARACTER*(*) STRING INTEGER NEXT DO 10 NEXT = LEN(STRING), 1, -1 IF (STRING(NEXT : NEXT) .NE. ' ') THEN LEN_TRIM = NEXT RETURN ENDIF 10 CONTINUE LEN_TRIM = 0 RETURN END
* FDEMO2.FOR * * A dynamic SQL OCI example program. Processes * SQL statements entered interactively by the user. * * There is a 132-character limit on the length of * the SQL statements. It is not necessary to * terminate the SQL statement with a semicolon. * * To end the demo, type 'exit' or 'EXIT' at the * prompt. PROGRAM FDEMO2 IMPLICIT INTEGER*4 (A-Z) * Data structures * Logon and cursor areas INTEGER*2 CDA(32), LDA(32), HDA(256) * Bind values CHARACTER*20 BVARV(8) INTEGER NBV * Output values CHARACTER*10 DVARC(8) INTEGER DVARI(8) REAL*4 DVARF(8) INTEGER*2 DBTYPE(8), RLEN(8), RCODE(8) INTEGER*2 INDP(8) INTEGER NOV * Column names for SELECT CHARACTER*10 COLNAM(8) * SQL statement buffer and logon info CHARACTER*80 SQLSTM, UID, PWD, PROMPT INTEGER UIDL, PWDL, SQLL, NOBLOK UID = 'SCOTT' PWD = 'TIGER' UIDL = LEN_TRIM(UID) PWDL = LEN_TRIM(PWD) NOBLOK = 0 * Connect to ORACLE in non-blocking mode. * HDA must be initialized to all zeros before call to OLOG. DATA HDA/256*0/ CALL OLOG(LDA, HDA, UID, UIDL, PWD, PWDL, 0, -1, NOBLOK) IF (LDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) GO TO 999 ENDIF WRITE (*, '(1X, A, A)') 'Connected to ORACLE as user ', UID * Open a cursor. CALL OOPEN(CDA, LDA, UID, 0, -1, PWD, 0) IF (LDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) GO TO 900 ENDIF * Beginning of the main program loop. * Get and process SQL statements. PROMPT = 'Enter SQL statement (132 char max) + or EXIT to quit >' 100 WRITE (*, '(/, A)') PROMPT READ '(A)', SQLSTM SQLL = LEN_TRIM(SQLSTM) IF (SQLL .EQ. 0) GO TO 100 I = INDEX(SQLSTM, ';') IF (I .GT. 0) THEN SQLL = I - 1 ENDIF IF ((SQLSTM(1:4) .EQ. 'exit') .OR. + (SQLSTM(1:4) .EQ. 'EXIT')) GO TO 900 * Parse the statement. CALL OPARSE(CDA, SQLSTM, SQLL, 0, 2) IF (CDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) GO TO 100 ENDIF * If there are bind values, obtain them from user. CALL GETBNV(LDA, CDA, SQLSTM, BVARV, NBV) IF (NBV .LT. 0) GO TO 100 * Define the output variables. If the statement is not a * query, NOV returns as 0. If there were errors defining * the output variables, NOV returns as -1. CALL DEFINE(LDA, CDA, COLNAM, DBTYPE, DVARC, DVARI, + DVARF, INDP, RLEN, RCODE, NOV) IF (NOV .LT. 0) GO TO 100 * Execute the statement. CALL OEXN(CDA, 1, 0) IF (CDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) GO TO 100 ENDIF * Fetch rows and display output if the statement was a query. CALL FETCHN(LDA, CDA, COLNAM, NOV, DBTYPE, DVARC, + DVARI, DVARF, INDP, RV) IF (RV .LT. 0) GO TO 100 * Loop back to statement 100 to process * another SQL statement. GO TO 100 * End of main program loop. Here on exit or fatal error. 900 CALL OCLOSE(CDA) CALL OLOGOF(LDA) * End of program. Come here if connect fails. 999 END * Begin subprograms. SUBROUTINE GETBNV(LDA, CDA, STMT, BVARV, N) IMPLICIT INTEGER*4 (A-Z) INTEGER*2 LDA(32), CDA(32) CHARACTER*(*) STMT CHARACTER*(*) BVARV(8) * Arrays for bind variable info. INTEGER BVARI(8), BVARL(8) * Scan the SQL statement for placeholders (:ph). * Note that a placeholder must be terminated with * a space, a comma, or a close parentheses. * Two arrays are maintained: an array of starting * indices in the string (BVARI), and an array of * corresponding lengths (BVARL). POS = 1 DO 300 K = 1, 8 ! maximum of 8 per statement I = INDEX(STMT(POS:), ':') IF (I .EQ. 0) GO TO 400 POS = I + POS - 1 BVARI(K) = POS DO 100 J = POS, LEN(STMT) IF (STMT(J:J) .EQ. ' ' + .OR. STMT(J:J) .EQ. ',' + .OR. STMT(J:J) .EQ. ')') THEN BVARL(K) = J - POS GO TO 200 ENDIF 100 CONTINUE 200 POS = POS + 1 ! index past the ':' 300 CONTINUE 400 N = K - 1 ! N is the number of BVs DO 500 K = 1, N CALL OBNDRV(CDA, STMT(BVARI(K) :), BVARL(K), + BVARV(K), 20, 1,-1,0,0,-1,-1) IF (CDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) N = -1 RETURN ENDIF WRITE (*, '( A, A, A)') 'Enter value for ', + STMT(BVARI(K)+1:BVARI(K)+BVARL(K)-1), ' --> ' READ '(A)', BVARV(K) 500 CONTINUE RETURN END * Define output variables for queries. * Returns the number of select-list items (N) * and the names of the select-list items (COLNAM). * A maximum of 8 select-list items is permitted. * (Note that this program does not check if there * are more, but a production-quality program * must do this.) SUBROUTINE DEFINE(LDA, CDA, COLNAM, DBTYPE, DVARC, + DVARI, DVARF, INDP, RLEN, RCODE, RV) IMPLICIT INTEGER*4 (A-Z) INTEGER*2 LDA(32), CDA(32), DBTYPE(8) INTEGER*2 RLEN(8), RCODE(8), INDP(8) CHARACTER*(*) DVARC(8), COLNAM(8) INTEGER DVARI(8), RV REAL*4 DVARF(8) INTEGER DBSIZE(8), COLNML(8), DSIZE(8) INTEGER*2 PREC(8), SCALE(8), NOK(8) * If not a query (SQL function code .ne. 4), return. IF (CDA(2) .NE. 4) THEN RV = 0 RETURN ENDIF * Describe the select-list (up to 8 items max), * and define an output variable for each item, with the * external (hence, FORTRAN) type depending on the * internal ORACLE type, and its attributes. DO 100 N = 1, 8 COLNML(N) = 10 ! COL length must be set on the call CALL ODESCR(CDA, N, DBSIZE(N), DBTYPE(N), + COLNAM(N), COLNML(N), DSIZE(N), + PREC(N), SCALE(N), NOK(N)) * If the return code from ODESCR is 1007, then you have * reached the end of the select list. IF (CDA(7) .EQ. 1007) THEN GO TO 200 * Otherwise, if the return code is non-zero, an * error occurred. Exit the subroutine, signalling * an error. ELSE IF (CDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) RV = -1 ! Error on return RETURN ENDIF * Check the datatype of the described item. If it's a * NUMBER, check if the SCALE is 0. If so, define the * output variable as INTEGER (3). If it's NUMBER with SCALE != 0, * define the output variable as REAL (4). Otherwise, * it's assumed to be a DATE, LONG, CHAR, or VARCHAR2, * so define the output as 1 (VARCHAR2). IF (DBTYPE(N) .EQ. 2) THEN IF (SCALE(N) .EQ. 0) THEN DBTYPE(N) = 3 ELSE DBTYPE(N) = 4 ENDIF ELSE DBTYPE(N) = 1 ENDIF * Define the output variable. Do not define RLEN if * the external datatype is 1. IF (DBTYPE(N) .EQ. 3) THEN CALL ODEFIN(CDA, N, DVARI(N), 4, 3, 0, INDP(N), + FMT, 0, 0, RLEN(N), RCODE(N)) ELSE IF (DBTYPE(N) .EQ. 4) THEN CALL ODEFIN(CDA, N, DVARF(N), 4, 4, 0, INDP(N), + FMT, 0, 0, RLEN(N), RCODE(N)) ELSE CALL ODEFIN(CDA, N, DVARC(N), 10, 1, 0, INDP(N), + FMT, 0, 0, %VAL(-1), RCODE(N)) ENDIF IF (CDA(7) .NE. 0) THEN CALL ERRRPT(LDA, CDA) RV = -1 RETURN ENDIF 100 CONTINUE 200 RV = N - 1 ! Decrement to get correct count RETURN END * FETCHN uses OFETCH to fetch the rows that satisfy * the query, and displays the output. The data is * fetched 1 row at a time. SUBROUTINE FETCHN(LDA, CDA, NAMES, NOV, DBTYPE, DVARC, + DVARI, DVARF, INDP, RV) IMPLICIT INTEGER*4 (A-Z) INTEGER*2 LDA(32), CDA(32), DBTYPE(8), INDP(8) CHARACTER*(*) NAMES(8), DVARC(8) INTEGER DVARI(8), NOV, RV REAL*4 DVARF(8) IF (CDA(2) .NE. 4) THEN ! not a query RV = 0 RETURN ENDIF DO 50 COL = 1, NOV IF (DBTYPE(COL) .EQ. 1) THEN WRITE (*, 900) NAMES(COL), ' ' 900 FORMAT ('+', A10, A1, $) ELSE WRITE (*, 902) NAMES(COL), ' ' 902 FORMAT ('+', A8, A1, $) ENDIF 50 CONTINUE WRITE (*, '(1X, A, /)') '------------------------------ +-----------------------------------------------' DO 200 NROWS = 1, 10000 CALL OFETCH(CDA) IF (CDA(7) .EQ. 1403) GO TO 300 IF (CDA(7) .NE. 0 .AND. CDA(7) .NE. 1406) THEN CALL ERRRPT(LDA, CDA) RV = -1 RETURN ENDIF DO 100 COL = 1, NOV IF (INDP(COL) .LT. 0 .AND. DBTYPE(COL) .NE. 1) THEN WRITE (*, 903), ' ' 903 FORMAT ('+', A9, $) ELSE IF (INDP(COL) .LT. 0 .AND. DBTYPE(COL) .EQ. 1) THEN WRITE (*, 905), ' ' 905 FORMAT ('+', A11, $) ELSE IF (DBTYPE(COL) .EQ. 3) THEN WRITE (*, 904) DVARI(COL), ' ' 904 FORMAT ('+', I6, A3, $) ELSE IF (DBTYPE(COL) .EQ. 4) THEN WRITE (*, 906) DVARF(COL), ' ' 906 FORMAT ('+', F8.2, A1, $) ELSE WRITE (*, 908) DVARC(COL), ' ' 908 FORMAT ('+', A10, A1, $) ENDIF ENDIF 100 CONTINUE WRITE (*, '(1X)') 200 CONTINUE 300 NROWS = NROWS - 1 WRITE (*, '(/, 1X, I3, A)') NROWS, ' rows returned' RETURN END SUBROUTINE ERRRPT(LDA, CDA) INTEGER*2 LDA(32), CDA(32) CHARACTER*132 MSG MSG = ' ' IF (LDA(7) .NE. 0) THEN CDA(7) = LDA(7) CDA(6) = 0 ENDIF IF (CDA(6) .NE. 0) THEN WRITE (*, '(1X, A, I3)') 'Error processing OCI function', + CDA(6) ENDIF CALL OERHMS (LDA, CDA(7), MSG, 132) WRITE (*, '(1X, A)') MSG RETURN END INTEGER FUNCTION LEN_TRIM(STRING) CHARACTER*(*) STRING INTEGER NEXT DO 10 NEXT = LEN(STRING), 1, -1 IF (STRING(NEXT : NEXT) .NE. ' ') THEN LEN_TRIM = NEXT RETURN ENDIF 10 CONTINUE LEN_TRIM = 0 RETURN END
* FDEMO3.FOR * OCI FORTRAN Sample Program 3 * * Demonstrates using the OFLNG routine to retrieve * part of a LONG RAW column * * This example "plays" a digitized voice message * by repeatedly extracting 64 kB chunks of the message * from the row in the table, and sending them to a * converter buffer (for example, a Digital-to-Analog * Converter (DAC) FIFO buffer). * * The hardware-specific DAC routine is merely simulated * in this example. PROGRAM FDEMO3 IMPLICIT INTEGER(A-Z) * Connect and Cursor Data Structures INTEGER*2 CDA(32) INTEGER*2 LDA(32) INTEGER*2 HDA(256) * Program Variables CHARACTER*132 SQLSTM CHARACTER*20 UID, PWD INTEGER MSGID, MSGLEN INTEGER*2 INDP, RLEN, RCODE INTEGER RETL BYTE DBIN(200000) CHARACTER*6 FMT INTEGER*4 NOBLOK * Connect to ORACLE in non-blocking mode. * The HDA must be initialized to all zeros before calling OLOG. UID = 'SCOTT' PWD = 'TIGER' DATA HDA/256*0/ CALL OLOG(LDA, HDA, UID, LEN_TRIM(UID), + PWD, LEN_TRIM(PWD), 0, -1, NOBLOK) IF (LDA(1) .NE. 0) THEN WRITE (*, '(1X, A)') 'Cannot connect as scott/tiger...' WRITE (*, '(1X, A)') 'Application terminating...' GOTO 999 END IF * Open the cursor. (Use UID as a dummy parameter--it * won't be looked at.) CALL OOPEN(CDA, LDA, UID, 0, 0, UID, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(CDA) GOTO 900 END IF * Drop the old table. WRITE (*, '( A)') 'OK to drop table VOICE_MAIL (Y or N)? : ' READ '(A)', FMT IF (FMT(1:1) .EQ. 'y' .OR. FMT(1:1) .EQ. 'Y') THEN GO TO 10 ELSE GO TO 900 ENDIF * Parse the DROP TABLE statement. 10 SQLSTM = 'DROP TABLE VOICE_MAIL' CALL OPARSE(CDA, SQLSTM, LEN_TRIM(SQLSTM), 0, 2) IF (CDA(7) .EQ. 0) THEN WRITE (*, '(1X, A)') 'Table VOICE_MAIL dropped.' ELSEIF (CDA(7) .EQ. 942) THEN WRITE (*, '(1X, A)') 'Table did not exist.' ELSE CALL ERRPT(LDA, CDA) GO TO 900 ENDIF * Create new table. Parse with DEFFLG set to zero, * to immediately execute the DDL statement. The LNGFLG * is set to 2 (Version 7). SQLSTM = 'CREATE TABLE VOICE_MAIL + (MSG_ID NUMBER(6), MSG_LEN NUMBER(12), MSG LONG RAW)' * Parse the statement. Do not defer the parse, so that the * DDL statement is executed immediately. CALL OPARSE(CDA, SQLSTM, LEN_TRIM(SQLSTM), 0, 2) IF (CDA(7) .EQ. 0) THEN WRITE (*, '(1X, A)') 'Created table VOICE_MAIL.' ELSE CALL ERRPT(LDA, CDA) GOTO 900 END IF * Insert some dummy data into the table. SQLSTM = 'INSERT INTO VOICE_MAIL VALUES (:1, :2, :3)' CALL OPARSE(CDA, SQLSTM, LEN_TRIM(SQLSTM), 1, 2) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF * Do the binds for the input data to set values * in the new table. INDP = 0 CALL OBNDRN(CDA, 1, MSGID, 4, 3, 0, INDP, FMT, 0, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF CALL OBNDRN(CDA, 2, MSGLEN, 4, 3, 0, INDP, FMT, 0, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF CALL OBNDRN(CDA, 3, DBIN, 200000, 24, 0, INDP, FMT, 0, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF * Fill the input buffer with some dummy data. MSGID = 100 MSGLEN = 200000 DO 100 I = 1, 200000 100 DBIN(I) = 42 * Execute the statement to INSERT the data WRITE (*, '(1X, A)') 'Inserting data into the table.' CALL OEXN(CDA, 1, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF * Do the selects. First position the cursor at the * proper row, using the MSG_ID. Then fetch the data * in 64K chunks, using OFLNG. SQLSTM = 'SELECT MSG_ID, MSG_LEN, MSG + FROM VOICE_MAIL WHERE MSG_ID = 100' CALL OPARSE(CDA, SQLSTM, LEN_TRIM(SQLSTM), 1, 2) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF * Define the output variables for the SELECT. CALL ODEFIN(CDA, 1, MSGID, 4, 3, 0, %VAL(-1), %VAL(-1), + 0, 0, %VAL(-1), %VAL(-1)) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF CALL ODEFIN(CDA, 2, MSGLEN, 4, 3, 0, %VAL(-1), %VAL(-1), + 0, 0, %VAL(-1), %VAL(-1)) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF CALL ODEFIN(CDA, 3, DBIN, 200000, 24, 0, INDP, %VAL(-1), + 0, 0, RLEN, RCODE) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF * Do the query, getting the MSG_ID to position the cursor, and * the first 100 bytes of the message. * CANCEL and EXACT are FALSE. CALL OEXFET(CDA, 1, 0, 0) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF WRITE (*, '(1X, A, I4, A)') 'Message', MSGID, +' is available.' WRITE (*, '(1X, A, I7, A)') 'The length is', MSGLEN, +' bytes.' * Play out the message, calling the DAC routine for each * 64K chunk fetched by OFLNG. OFFSET = 0 N = MSGLEN/65536 + 1 DO 200 J = 1, N IF (MSGLEN .LT. 65536) THEN LEN = MSGLEN ELSE LEN = 65536 ENDIF CALL OFLNG(CDA, 3, DBIN, LEN, 24, RETL, OFFSET) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 ENDIF CALL PLAYMSG(DBIN, LEN) MSGLEN = MSGLEN - LEN IF (MSGLEN .LT. 0) GO TO 900 200 CONTINUE 900 CALL OCLOSE(CDA) IF (CDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF CALL OLOGOF(LDA) IF (LDA(7) .NE. 0) THEN CALL ERRPT(LDA, CDA) GOTO 900 END IF 999 STOP 'End of OCIDEMO3.' END SUBROUTINE PLAYMSG(OUT, LEN) BYTE OUT(65536) INTEGER LEN WRITE (*, '(1X, A, I7, A)') 'Playing', LEN, ' bytes.' RETURN END SUBROUTINE ERRPT(LDA, CDA) INTEGER*2 LDA(32), CDA(32) CHARACTER*132 MSG MSG = ' ' IF (LDA(7) .NE. 0) THEN CDA(7) = LDA(7) CDA(6) = 0 ENDIF IF (CDA(6) .NE. 0) THEN WRITE (*, '(1X, A, I3)') 'Error processing OCI function', + CDA(6) ENDIF CALL OERHMS (LDA, CDA(7), MSG, 132) WRITE (*, '(1X, A)') MSG RETURN END INTEGER FUNCTION LEN_TRIM(STRING) CHARACTER*(*) STRING INTEGER NEXT DO 10 NEXT = LEN(STRING), 1, -1 IF (STRING(NEXT : NEXT) .NE. ' ') THEN LEN_TRIM = NEXT RETURN ENDIF 10 CONTINUE LEN_TRIM = 0 RETURN END
![]() ![]() Prev Next |
![]() Copyright © 1996 Oracle Corporation. All Rights Reserved. |
![]() Library |
![]() Product |
![]() Contents |
![]() Index |