WinOCI & Cursor Variables...

From: Roderick Prince <rrprince_at_comdisco.com>
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

Original text of this message