WinOCI & Cursor Variables...
Date: 1996/09/06
Message-ID: <32307CA7.3A14_at_comdisco.com>
After a bit of a reprieve I am back to trying to make cursor variables work under windows.
Can someone please look at the following and tell me what I am missing. Code executes through the parse but the cursor variable does not appear to be set up properly by the stored procedure resulting in a GPF on the odescr call.
Here is the stored package...
CREATE OR REPLACE PACKAGE EmployeePkg AS
TYPE EmpRec IS RECORD (
empno emp.empno%TYPE, ename emp.ename%TYPE, job emp.job%TYPE, mgr emp.mgr%TYPE, hiredate emp.hiredate%TYPE, sal emp.sal%TYPE, deptno emp.deptno%TYPE);
TYPE EmpCursor IS REF CURSOR RETURN EmpRec; PROCEDURE GetEmployees(p_Cursor IN OUT EmpCursor, p_jobtitle VARCHAR2); END EmployeePkg;
/
CREATE OR REPLACE PACKAGE BODY EmployeePkg AS PROCEDURE GetEmployees (p_Cursor IN OUT EmpCursor, p_jobtitle VARCHAR2) IS BEGIN
OPEN p_Cursor FOR SELECT empno, ename, job, mgr, hiredate, sal, deptno FROM EMP WHERE Job = p_JobTitle;
END GetEmployees;
END EmployeePkg;
And now for the source code...
/*
- winoci.c
*
- Example OCI Application for Windows V3.0.
*
- by D. Colello -- Desktop Products Division.
*
- Copyright 1991, Oracle Corporation.
*
- Modified -
- cchui 10/25/94 - replace calls to osql3 with oparse - bug 229431
- cchui 10/25/94 - replace call to olon with orlon - bug 229431
- dcriswel 12/03/93 - Port to v7
- Colello 07/09/91 - Created from winsam.pc
*/
#include <windows.h> #include "winoci.h" #include <string.h> #include "ociapr.h" #include "ocidem.h" #include "ocidfn.h"
/* oparse flags */
#define DEFER_PARSE 1
#define VERSION_7 2
#define NPOS 16
#define DSCLEN 240
text sJobKind[50] = "ANALYST";
static sword retval;
static ub4 hstb[HDA_SIZE/sizeof(ub4)]; /*ub1 hstb[512];*/
static text errorb[4095];
static text cbuf[NPOS][DSCLEN];
static sb4 cbufl[NPOS];
static sb4 dbsize[NPOS];
static sb4 dsize[NPOS];
static sb2 dbtype[NPOS];
static sb2 prec[NPOS];
static sb2 scale[NPOS];
static sb2 nullok[NPOS];
/********************************************************************/ /* Oracle Declaration Section */ /********************************************************************/ /* Cursor and LDA for communicating with ORACLE */ struct cda_def lda; /* lda area */ #define LDA (struct cda_def far *)&lda static struct cda_def sel_curs; /* cursor for SELECT */ #define SEL_CURS (struct cda_def far *)&sel_curs struct cda_def dml_curs; /* cursor for DML...insert,update,delete */ #define DML_CURS (struct cda_def far *)&dml_curs struct cda_def sel_curs_var; /* cursor for SELECT */#define SEL_CURS_VAR (struct cda_def far *)&sel_curs_var
/* Input host variables for logging into ORACLE. */ char userid[ MAX_USERID + 1 ]; /*used at CONNECT time*/ char password[ MAX_PASSWORD + 1 ]; /*used at CONNECT time*/ char connect[ MAX_CONNECT + 1 ]; /*used at CONNECT time*/ /* Input/Output host variables for EMP table. */ char emp_empno[ 5 ]; /*used for EMP table*/ char emp_ename[ 11 ]; /*used for EMP table*/ char emp_job[ 10 ]; /*used for EMP table*/ char emp_mgr[ 5 ]; /*used for EMP table*/ char emp_hiredate[ 10 ]; /*used for EMP table*/ char emp_sal[ 9 ]; /*used for EMP table*/ char emp_comm[ 9 ]; /*used for EMP table*/char emp_deptno[ 3 ]; /*used for EMP table*/
/* Null field indicators for table EMP. */
short ind_emp_empno; /*used for EMP table*/ short ind_emp_ename; /*used for EMP table*/ short ind_emp_job; /*used for EMP table*/ short ind_emp_mgr; /*used for EMP table*/ short ind_emp_hiredate; /*used for EMP table*/ short ind_emp_sal; /*used for EMP table*/ short ind_emp_comm; /*used for EMP table*/ short ind_emp_deptno; /*used for EMP table*/
/* Structure to keep info on current session */ struct oracle_session session;
char hda[256];
/********************************************************************/ /* Windows Declaration Section */ /********************************************************************/
static HANDLE hInst;
FARPROC lpprocAbout;
/********************************************************************/ /* OCI and Windows Code. */ /********************************************************************/ /*
*EmployeesDlg
*/
BOOL FAR PASCAL EmployeesDlg(hDlg, message, wParam, lParam) HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
/* SQL statement used to get info from database */ /* char far *empsel="SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, \
DEPTNO FROM EMP FOR UPDATE OF EMPNO, ENAME, JOB, MGR, \ HIREDATE, SAL, COMM, DEPTNO"; */ char far *empsel= "begin \ EmployeePkg.GetEmployees(:cCursor, :sJob);\ end;"; /*****************************************************************/ /* You need the "FOR UPDATE OF" clause so that you can use */ /* the "rowid" field with UPDATE and DELETE statements. This also*/ /* applies to a PRO*C 'WHERE CURRENT OF' clause. This field will */ /* be valid for other statements to use if and only if you */ /* use the "FOR UPDATE OF" clause with the SELECT since this */ /* locks the ROWID until the next COMMIT [see SQL manuals]. */ /*****************************************************************/
/* SQL statement to delete currently fetched emp record */ char far *delete="DELETE FROM EMP WHERE ROWID = :row_id";
/* SQL statement to update currently fetched emp record */ char far *update="UPDATE EMP SET EMPNO=:empno, ENAME=:ename, JOB=:job, \
MGR=:mgr, HIREDATE=:hiredate, SAL=:sal, COMM=:comm, \ DEPTNO=:deptno WHERE ROWID = :row_id";
/* SQL statement to insert an emp record */ char far *insert="INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM, \
DEPTNO) VALUES (:empno,:ename,:job,:mgr,:hiredate,:sal, \ :comm,:deptno)";
ub4 pos;
switch (message) {
case WM_COMMAND :
switch (wParam) {
case ID_EMPLOYEES_EXIT : EndDialog(hDlg, 1); break; case ID_EMPLOYEES_SELECT : /* check to see if we have an open, parsed, defined cursor */ /* if so, all we need to do below is re-execute the query in order to get a new active set. Otherwise, open, parse, and define output buffers for the query */ if (session.opened == FALSE) { /* open a cursor for the select from emp */ if (oopen(SEL_CURS_VAR, LDA, (char far *)0, -1, -1, (char far *)0, -1)) { ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ /* parse cursor */ // if (osql3(SEL_CURS_VAR, (char far *)empsel, -1)) { if (oparse(SEL_CURS_VAR, (char far *)empsel, -1, (sword) TRUE, (ub4)2)) { ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ if (obndra(SEL_CURS_VAR, (text *)":cCursor", -1, (ub1 *)&sel_curs, -1, SQLT_CUR, -1, (sb2 *)0,(ub2 *)0, (ub2 *)0, (ub4) 0, (ub4 *)0, (text *)0,0,0)){ ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ if (obndra(SEL_CURS_VAR, (text *)":sJob", -1, (ub1 *)sJobKind, -1, SQLT_STR, -1, (sb2 *)0,(ub2 *)0, (ub2 *)0, (ub4) 0, (ub4 *)0, (text *)0,0,0)){ ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ /* execute the query to get a new active set */ if (oexec(SEL_CURS_VAR)) { ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ if(oclose(SEL_CURS_VAR)){ ProcessOracleErrorCode(hDlg, SEL_CURS_VAR); break; } /*if*/ for (pos=0;pos<NPOS;pos++){ cbufl[pos]=DSCLEN; if(odescr(SEL_CURS, (sword)(pos+1), &dbsize[pos],&dbtype[pos], (sb1 *)cbufl[pos], &cbufl[pos], &dsize[pos], &prec[pos], &scale[pos], &nullok[pos])){ if (sel_curs.rc == 1007) break; ProcessOracleErrorCode(hDlg, SEL_CURS); break; } } /* define output buffers for the all fields in the select list of our query */ if (odefin(SEL_CURS, 1, (char far *)emp_empno, sizeof(emp_empno), NULLTERM, -1, (short far *)&ind_emp_empno, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 2, (char far *)emp_ename, sizeof(emp_ename), NULLTERM, -1, (short far *)&ind_emp_ename, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 3, (char far *)emp_job, sizeof(emp_job), NULLTERM, -1, (short far *)&ind_emp_job, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 4, (char far *)emp_mgr, sizeof(emp_mgr), NULLTERM, -1, (short far *)&ind_emp_mgr, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 5, (char far *)emp_hiredate, sizeof(emp_hiredate), NULLTERM, -1, (short far *)&ind_emp_hiredate, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 6, (char far *)emp_sal, sizeof(emp_sal), NULLTERM, -1, (short far *)&ind_emp_sal, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 7, (char far *)emp_comm, sizeof(emp_comm), NULLTERM, -1, (short far *)&ind_emp_comm, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ if (odefin(SEL_CURS, 8, (char far *)emp_deptno, sizeof(emp_deptno), NULLTERM, -1, (short far *)&ind_emp_deptno, (char far *)0, -1, -1, (short far *)0, (short far *)0)) { ProcessOracleErrorCode(hDlg, SEL_CURS); break; } /*if*/ } /*if*/ session.opened = TRUE; session.nomore = FALSE; case ID_EMPLOYEES_FETCH :
// More code but it is the same as in the WinOCI sample... Received on Fri Sep 06 1996 - 00:00:00 CEST