Programmer's Guide to the Oracle7 Server Call Interface Go to Product Documentation Library
Library
Go to books for this product
Product
Go to Contents for this book
Contents
Go to Index
Index



Go to previous file in sequence Go to next file in sequence


    gets((char *) sql_statement);
    if (*sql_statement != 'y' && *sql_statement != 'Y')
        do_exit(EXIT_SUCCESS);
    
    /* Parse, set defflg parameter for non-deferred parse
       (to execute the DDL statement immediately). */
    if (oparse(&cda, (text *) "DROP TABLE voice_mail", -1,
               FALSE, 2))
    {
        if (cda.rc == 942)
            fputs("Table did not exist.\n", stdout);
        else
            oci_error(&cda);
    }
    else
        fputs("Dropped table \"voice_mail\".\n", stdout);

    strcpy((char *) sql_statement, "CREATE TABLE voice_mail\
        (msg_id NUMBER(6), msg_len NUMBER(12), msg LONG RAW)");
    if (oparse(&cda, sql_statement, -1, FALSE, 2))
        oci_error(&cda);
    fputs("Created table \"voice_mail\".\n", stdout);

    /* Create a dummy message. */ 
    strcpy((char *) sql_statement,
           "INSERT INTO voice_mail (msg_id, msg_len, msg) \
                           VALUES (:1, :2, :3)");
    if (oparse(&cda, sql_statement, -1, FALSE, 2))
        oci_error(&cda);

    if (obndrn(&cda, 1, (ub1 *) &msg_id, 4, 3, -1,
               (sb2 *) 0, (text *) 0, 0, -1))
        oci_error(&cda);

    /* Set buffer address before binding. */
    ucp = (ub1 *) malloc(MSG_SIZE);
    if (ucp == 0)
    {
        fputs("malloc error\n", stderr);
        do_exit(EXIT_FAILURE);
    }
    if (obndrn(&cda, 2, (ub1 *) &msg_len, 4, 3, -1,
               (sb2 *) 0, (text *) 0, 0, -1))
        oci_error(&cda);

    if (obndrn(&cda, 3, ucp, MSG_SIZE, 24, -1,
               (sb2 *) 0, (text *) 0, 0, -1))
        oci_error(&cda);

    /* Set bind vars before oexn. */
    msg_id  = 100;     
    msg_len = MSG_SIZE;
    for (i = 0, ucp1 = ucp; i < MSG_SIZE; i++)
        *ucp1++ = (ub1) i % 128;

    if (oexn(&cda, 1, 0))
        oci_error(&cda);
    fputs("Data inserted in table \"voice_mail\".\n", stdout);

/*
 *  After setting up the test data, do the
 *  select and fetch the message chunks        */
    strcpy((char *) sql_statement, "select msg_id, msg_len, msg\
                  from voice_mail where msg_id = 100");
    if (oparse(&cda, sql_statement, -1, 0, 2))
        oci_error(&cda);

    if (odefin(&cda,
               1,               /* index */
               (ub1 *) &msg_id, /* output variable */
               4,               /* length */
               3,               /* datatype */
               -1,              /* scale */
               (sb2 *) 0,       /* indp */
               (text *) 0,      /* fmt */
               0,               /* fmtl */
               -1,              /* fmtt */
               (ub2 *) 0,       /* retl */
               (ub2 *) 0))      /* rcode */
        oci_error(&cda);

    if (odefin(&cda,
               2,               /* index */
               (ub1 *) &msg_len,/* output variable */
               4,               /* length */
               3,               /* datatype */
               -1,              /* scale */
               (sb2 *) 0,       /* indp */
               (text *) 0,      /* fmt */
               0,               /* fmtl */
               -1,              /* fmtt */
               (ub2 *) 0,       /* retl */
               (ub2 *) 0))      /* rcode */
        oci_error(&cda);

    if (odefin(&cda,
               3,               /* index */
               ucp,             /* output variable */
               100,             /* length */
               24,              /* LONG RAW datatype code */
               -1,              /* scale */
               &indp,           /* indp */
               (text *) 0,      /* fmt */
               0,               /* fmtl */
               -1,              /* fmtt */
               &retl,           /* retl */
               &rcode))         /* rcode */
        oci_error(&cda);

    /* Do the query, getting the msg_id and the first
       100 bytes of the message. */
    if (oexfet(&cda,
               (ub4) 1,         /* nrows */
               0,               /* cancel (FALSE) */
               0))              /* exact (FALSE) */
    {
            oci_error(&cda);
    }

    fprintf(stdout,
      "Message %d is available, length is %d.\n", msg_id, 
             msg_len);
    fprintf(stdout,
      "indp = %d, rcode = %d, retl = %d\n", indp, rcode, retl);

    /* Play the message, looping until there are
       no more data points to output. */
    for (offset = (ub4) 0; ; offset += (ub4) 0x10000)
    {
        len = msg_len < 0x10000 ? msg_len : 0x10000;
        if (oflng(&cda,
                  3,                /* position */
                  ucp,              /* buf */
                  len,              /* bufl */
                  24,               /* datatype */
                  &ret_len,         /* retl */
                  offset))          /* offset */
            oci_error(&cda);
        /* Output the message chunk. */
        play_msg(ucp, len);
        msg_len -= len;
        if (msg_len <= 0)
            break;
    }
    do_exit(EXIT_SUCCESS);
}


dvoid
play_msg(buf, len)
ub1 *buf;
sword len;
{
    fprintf(stdout, "\"playing\" %d bytes.\n", len);
}


dvoid
oci_error(cda)
Cda_Def *cda;
{
    text msg[200];
    sword n;
    fputs("\n-- ORACLE ERROR --\n", stderr);
    n = oerhms(&lda, (sb2) cda->rc, msg, 200);
    fprintf(stderr, "%.*s", n, msg);
    fprintf(stderr, "Processing OCI function %s\n",
            oci_func_tab[(int) cda->fc]);
    do_exit(EXIT_FAILURE);
}


dvoid
do_exit(rv)
sword rv;
{
    fputs("Exiting...\n", stdout);
    if (oclose(&cda))
    {
        fputs("Error closing cursor.\n", stderr);
        rv = EXIT_FAILURE;
    }
    if (ologof(&lda))
    {
        fputs("Error logging off.\n", stderr);
        rv = EXIT_FAILURE;
    }
    exit(rv);
}


cdemo4.c

/* cdemo4.c
 *
 *  Demonstrates doing a FETCH from a cursor
 *  into PL/SQL tables.  The tables are bound to C
 *  arrays using the obndra routine.
 *  The fully-commented script to create the stored procedure
 *  is in the demo program file calldemo.sql.
 *
 *  Execute this script using SQL*DBA or SQL*Plus
 *  to store the package before executing this program.
 *
 * The script is:
 * create or replace package calldemo as
 * 
 *   type char_array is table of varchar2(20) index by 
 *         binary_integer;
 *   type num_array is table of float index by binary_integer;
 * 
 *   procedure get_employees(
 *     dept_number in     integer,   -- which department to query
 *     batch_size  in     integer,   -- how many rows at a time
 *     found       in out integer,   -- n of rows actually 
 *                                      returned
 *     done_fetch  out    integer,   -- all done flag
 *     emp_name    out    char_array,-- arrays of employee names,
 *     job         out    char_array,--                   jobs,
 *     sal         out    num_array);--                   salaries
 * 
 * end;
 * /
 * 
 * create or replace package body calldemo as
 * 
 *   cursor get_emp(
 *     dept_number in     integer) is
 *       select ename, job, sal from emp
 *       where deptno = dept_number;
 * 
 * -- Procedure get_employees fetches a batch of employee
 * -- rows (batch size is determined by the client/caller
 * -- of this procedure).  Procedure may be called from
 * -- other stored procedures or client application
 * -- programs.  The procedure opens the cursor if it is
 * -- not already open, fetches a batch of rows, and
 * -- returns the number of rows actually retrieved.  At
 * -- end of fetch, the procedure closes the cursor.
 * 
 *   procedure get_employees(
 *     dept_number in     integer,
 *     batch_size  in     integer,
 *     found       in out integer,
 *     done_fetch  out    integer,
 *     emp_name    out    char_array,
 *     job         out    char_array,
 *     sal         out    num_array) is
 *     
 *    begin
 *      if NOT get_emp%ISOPEN then     -- open the cursor if it is
 *        open get_emp(dept_number);   -- not already open
 *      end if;
 * 
 * -- Fetch up to "batch_size" rows into PL/SQL table,
 * -- tallying rows found as they are retrieved.  When end
 * -- of fetch is encountered, close the cursor and exit
 * -- the loop, returning only the last set of rows found.
 * 
 *     done_fetch := FALSE;
 *     found := 0;
 *     for i in 1..batch_size loop
 *        fetch get_emp               -- get one emp table row
 *          into emp_name(i), job(i), sal(i);
 * 
 *        if get_emp%notfound then    -- if no row was found, then
 *          close get_emp;            -- close the cursor
 *          done_fetch := TRUE;       -- indicate all done
 *          exit;                     -- exit the loop
 *        else
 *          found := found + 1;       -- else count the row and 
 *                                       continue
 *          end if;
 *     end loop;
 *    end;
 * end;
 * /
 */

#include <stdio.h>
#include <string.h>
#include <oratypes.h>
#include <ocidfn.h>

#ifdef __STDC__
#include <ociapr.h>
#else
#include <ocikpr.h>
#endif
#include <ocidem.h>

#define MAX_ARRAY_SIZE     5
#define NO_PARSE_DEFER     0
#define V7_LNGFLG          2
#define VC_LENGTH         20

/* Declare the data areas. */
Cda_Def cda;
Lda_Def lda;
ub1     hda[512];

/*  Declare routines in this program */
dvoid do_fetch(/*_ void _*/);
dvoid oci_error(/*_ void _*/);


main(argc, argv)
sword argc;
text **argv;
{
    text username[128];

    if (argc > 1)
        strncpy((char *) username, (char *) argv[1],
                sizeof (username) - 1);
    else
        strcpy((char *) username, "SCOTT/TIGER");
    if (olog(&lda, hda, username, -1, (text *) 0, -1,
             (text *) 0, -1, OCI_LM_DEF))
    {
        printf("Cannot connect as %s. Exiting...\n", username);
        exit(-1);
    }
    else
        printf("Connected.\n");

    /* Open the OCI cursor. */
    if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1))
    {
        printf("Cannot open cursor data area, exiting...\n");
        exit(-1);
    }
    /* Fetch and print the data. */
    do_fetch();

    /* Close the OCI cursor. */
    if (oclose(&cda))
    {
        printf("Error closing cursor!\n");
        exit(-1);
    }

    /* Disconnect from ORACLE. */
    if (ologof(&lda))
    {
        printf("Error logging off!\n");
        exit(-1);
    }
    exit(0);
}


/*  Set up an anonymous PL/SQL call to the stored
    procedure that fetches the data. */
dvoid
do_fetch(/*_ void _*/)
{
    text *call_fetch = (text *) "\
      begin\
        calldemo.get_employees(:deptno, :t_size, :num_ret,\
                           :all_done, :e_name, :job, :sal);\
      end;";
    sword table_size = MAX_ARRAY_SIZE;
    sword i, n_ret, done_flag;
    sword dept_num;
    sb2 n_ret_indp;
    ub2 n_ret_len, n_ret_rcode;
    ub4 n_ret_cursiz = 0;

    text emp_name[MAX_ARRAY_SIZE][VC_LENGTH];
    sb2 emp_name_indp[MAX_ARRAY_SIZE];
    ub2 emp_name_len[MAX_ARRAY_SIZE];
    ub2 emp_name_rcode[MAX_ARRAY_SIZE];
    ub4 emp_name_cursiz = (ub4) MAX_ARRAY_SIZE;

    text job[MAX_ARRAY_SIZE][VC_LENGTH];
    sb2 job_indp[MAX_ARRAY_SIZE];
    ub2 job_len[MAX_ARRAY_SIZE];
    ub2 job_rcode[MAX_ARRAY_SIZE];
    ub4 job_cursiz = (ub4) MAX_ARRAY_SIZE;

    float salary[MAX_ARRAY_SIZE];
    sb2 salary_indp[MAX_ARRAY_SIZE];
    ub2 salary_len[MAX_ARRAY_SIZE];
    ub2 salary_rcode[MAX_ARRAY_SIZE];
    ub4 salary_cursiz = (ub4) MAX_ARRAY_SIZE;

    /* parse the anonymous SQL block */
    if (oparse(&cda, call_fetch, -1,
               NO_PARSE_DEFER, V7_LNGFLG))
    {
        oci_error();
        return;
    }

    /* initialize the bind arrays */
    for (i = 0; i < MAX_ARRAY_SIZE; i++)
    {
        emp_name_len[i] = VC_LENGTH;
        job_len[i] = VC_LENGTH;
        salary_len[i] = sizeof (float);
    }

    n_ret_len = sizeof (sword);

    /* bind the department number IN parameter */
    if (obndrv(&cda, (text *) ":deptno", -1, (ub1 *) &dept_num,
               (sword) sizeof (sword), INT_TYPE, -1,
               (sb2 *) 0, (text *) 0, -1, -1))
    {
        oci_error();
        return;
    }

    /* bind the table size IN parameter */
    if (obndrv(&cda, (text *) ":t_size", -1, (ub1 *) &table_size,
               (sword) sizeof (sword),
               INT_TYPE, -1, (sb2 *) 0, (text *) 0, -1, -1))
    {
        oci_error();
        return;
    }

    /* bind the fetch done OUT parameter */
    if (obndrv(&cda, (text *) ":all_done", -1, (ub1 *) &done_flag,
               (sword) sizeof (sword),
               INT_TYPE, -1, (sb2 *) 0, (text *) 0, -1, -1))
    {
        oci_error();
        return;
    }

    /* Bind the OUT n_ret using obndra. obndrv could
       have been used just as well, since no arrays
       are involved, but it is possible to use obndra
       for scalars as well. */
    if (obndra(&cda,
           (text *) ":num_ret",
           -1,
           (ub1 *) &n_ret,
           (sword) sizeof (sword),
           INT_TYPE,
           -1,
           &n_ret_indp,
           &n_ret_len,
           &n_ret_rcode,
           (ub4) 0,  /* pass as 0, not 1, when binding a scalar */
           (ub4 *) 0,   /* pass as the null pointer when scalar */
           (text *) 0,
           -1,
           -1))
    {
        oci_error();
        return;
    }
    
    /* bind the employee name array */
    if (obndra(&cda,
           (text *) ":e_name",
           -1,
           (ub1 *) emp_name,
           VC_LENGTH,
           VARCHAR2_TYPE,
           -1,
           emp_name_indp,
           emp_name_len,
           emp_name_rcode,
           (ub4) MAX_ARRAY_SIZE,
           &emp_name_cursiz,
           (text *) 0,
           -1,
           -1))
    {
        oci_error();
        return;
    }



    /* bind the job array */
    if (obndra(&cda,
           (text *) ":job",
           -1,
           (ub1 *) job,
           VC_LENGTH,
           VARCHAR2_TYPE,
           -1,
           job_indp,
           job_len,
           job_rcode,
           (ub4) MAX_ARRAY_SIZE,
           &job_cursiz,
           (text *) 0,
           -1,
           -1))
    {
        oci_error();
        return;
    }

    /* bind the salary array */
    if (obndra(&cda,
           (text *) ":sal",
           -1,
           (ub1 *) salary,
           (sword) sizeof (float),
           FLOAT_TYPE,
           -1,
           salary_indp,
           salary_len,
           salary_rcode,
           (ub4) MAX_ARRAY_SIZE,
           &salary_cursiz,
           (text *) 0,
           -1,
           -1))
    {
        oci_error();
        return;
    }

    printf("\nenter deptno: ");
    scanf("%d", &dept_num);

    for (;;)
    {
        /* execute the fetch */
        if (oexec(&cda))
        {
            oci_error();
            return;
        }

        printf("\n%d row%c returned\n",
               n_ret, n_ret == 1 ? '\0' : 's');

        if (n_ret > 0)
        {
            printf("\n%-*.*s%-*.*s%s\n",
                   VC_LENGTH, VC_LENGTH, "Employee Name",
                   VC_LENGTH, VC_LENGTH, "Job", "   Salary");
            for (i = 0; i < n_ret; i++)
            {
                printf("%.*s", emp_name_len[i], emp_name[i]);
                printf("%*c", VC_LENGTH - emp_name_len[i], ' ');
                printf("%.*s", job_len[i], job[i]);
                printf("%*c", VC_LENGTH - job_len[i], ' ');
                printf("%8.2f\n", salary[i]);
            }
        }
        if (done_flag != 0)
        {
            printf("\n");
            break;
        }
    }
    return;
}


dvoid
oci_error(/*_ void _*/)
{
    text msg[900];
    sword rv;

    rv = oerhms(&lda, cda.rc, msg, (sword) sizeof (msg));
    printf("\n\n%.*s", rv, msg);
    printf("Processing OCI function %s\n",
           oci_func_tab[(int) cda.fc]);
    return;
}


cdemo5.c

/*
 *     -- cdemo5.c --
 *
 *  An example program which demonstrates the use of
 *  Variable Cursors in an OCI program.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <oratypes.h>
#include <ocidfn.h>
#include <ocikpr.h>

 /* oparse flags */
#define DEFER_PARSE 1
#define VERSION_7 2
#define NPOS 16
#define DSCLEN 240

text *username = (text *) "SCOTT";
text *password = (text *) "TIGER";

static  sword retval;
static  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];
 
static Lda_Def lda1;
static text plsql_block[] = 
      "begin \
	  OPEN :cursor1 FOR select empno, ename, job, mgr,
hiredate,sal,deptno\
               from emp where job=:job order by empno;\
      end;";

/* CLIENT CURSORS */
static Cda_Def cursor, cursor_emp;

/* Prototype */
void oracle_error();


int main ()
{
  Lda_Def *ldap = &lda1;
  ub4    empno;
  text   ename[11];
  text   job[10];
  ub4    mgr;
  text   hidate[10];
  ub4    sal;
  ub4    deptno;
  int    i;  
  text   job_kind[50];
  ub4    pos;
  
  strcpy((char *) job_kind, "ANALYST");
  fprintf(stdout,"\n\nFETCHING for job=%s\n\n",job_kind);

  /* Connect to Oracle as SCOTT/TIGER.  *
   * Exit on any error.                 */
    if (olog(ldap, hstb, username, -1, password, -1,
           (text *) 0, -1, OCI_LM_DEF))
  {  
      printf("Unable to connect as %s\n", username);
      exit(EXIT_FAILURE);
  }

  printf("Connected to Oracle as %s\n\n", username);
 
  /*
   * Open a cursor for executing the PL/SQL block.
   */
  if (oopen(&cursor, ldap, (text *) 0, -1, 0, (text *) 0, -1))
  {
     oracle_error(&cursor);
     exit(EXIT_FAILURE);
  }
 
  /* Parse the PL/SQL block. */
  
  if (oparse(&cursor, plsql_block, (sb4) -1, (sword) TRUE,
             (ub4) 2))
  {
     oracle_error(&cursor);
     exit(EXIT_FAILURE);
  }

  /*
   * Bind a variable of cursor datatype, the cursor will be opened
   * inside the PL/SQL block.
   */

  if (obndra(&cursor,(text *) ":cursor1", -1, (ub1 *) &cursor_emp,               -1, SQLT_CUR, -1, (sb2 *) 0, (ub2 *) 0, (ub2 *) 0,
             (ub4) 0, (ub4 *) 0, (text *) 0, 0, 0))
  {
     oracle_error(&cursor);
     exit(EXIT_FAILURE);
  }

  /*
   * Bind a variable of string datatype.
   */

  if (obndra(&cursor, (text *) ":job", -1, (ub1 *) job_kind, 
             -1, SQLT_STR, -1, (sb2 *) 0, (ub2 *) 0, (ub2 *) 0,
             (ub4) 0, (ub4 *) 0, (text *) 0, 0, 0))
  {
     oracle_error(&cursor);
     exit(EXIT_FAILURE);
  }

  /* 
   * Execute the PL/SQL block.
   */

   if (oexec(&cursor))
   {
      oracle_error(&cursor);
      exit(EXIT_FAILURE);
   }

  /*
   * Close the cursor on which the PL/SQL block executed.
   */

  if (oclose(&cursor))
  {
     oracle_error(&cursor);
     exit(EXIT_FAILURE);
  }



  /* 
   * Do describe on cursor initialized and returned from the 
     PL/SQL block.
   */
  for (pos = 0; pos < NPOS; pos++)
  {
     cbufl[pos] = DSCLEN;
     if (odescr(&cursor_emp, (sword) (pos+1), &dbsize[pos],
              &dbtype[pos],(sb1 *) cbuf[pos], &cbufl[pos],
              &dsize[pos], &prec[pos], &scale[pos], &nullok[pos]))
     {
        if (cursor_emp.rc == 1007)
           break;
        oracle_error(&cursor_emp);
        exit(EXIT_FAILURE);
     }
  }

  printf("Describe select-list returns:\n\n");
  printf("----------------------------------------\n");
  printf("Item\t\tMaxSize\t\tType\n");
  printf("----------------------------------------\n");

  for (i = 0; i < pos; i++)
  {
     cbuf[i][cbufl[i]] = '\0';
     printf("%s\t\t%d\t\t%d\n", cbuf[i], dbsize[i], dbtype[i]);
  }

  /* 
   * Do client defines.
   */

  if (odefin(&cursor_emp, 1, (ub1 *) &empno, (sword) sizeof(ub4), 
             SQLT_INT, -1, (sb2 *) -1, (text *) 0, (sword) 0, 
            (sword) 0, (ub2 *) 0,(ub2 *) 0))
  {
     oracle_error(&cursor_emp);
     exit(EXIT_FAILURE);
  }

   if (odefin(&cursor_emp, 2, (ub1 *) ename, (sword) 
              sizeof(ename), SQLT_STR, -1, (sb2 *) -1, (text *)0, 
              (sword) 0, (sword) 0,(ub2 *) 0, (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }
  if (odefin(&cursor_emp, 3, (ub1 *) job, (sword) sizeof(job), 
             SQLT_STR, -1, (sb2 *) -1, (text *) 0, (sword) 0, 
             (sword) 0, (ub2 *) 0, (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }

  if (odefin(&cursor_emp, 4, (ub1 *)&mgr, (sword) sizeof(ub4), 
             SQLT_INT, -1, (sb2 *) -1, (text *)0, (sword) 0, 
             (sword) 0, (ub2 *) 0, (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }

  if (odefin(&cursor_emp, 5, (ub1 *)hidate, (sword)sizeof(hidate),               SQLT_STR, -1, (sb2 *) -1, (text *) 0, (sword) 0, 
            (sword) 0, (ub2 *) 0, (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }

   if (odefin(&cursor_emp, 6, (ub1 *) &sal, (sword) sizeof(ub4), 
              SQLT_INT, -1, (sb2 *) -1, (text *) 0, (sword) 0, 
             (sword) 0, (ub2 *) 0, (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }

   if (odefin(&cursor_emp, 7, (ub1 *) &deptno, 
             (sword)sizeof(deptno), SQLT_INT, -1, (sb2 *) -1, 
             (text *) 0, (sword) 0, (sword) 0, (ub2 *) 0,
             (ub2 *) 0))
   {
      oracle_error(&cursor_emp);
      exit(EXIT_FAILURE);
   }
  printf("\nFETCH from variable cursor:\n\n");
  printf("------------------------------------------------------------\n");

  printf("empno\tename\tjob\tmgr\thiredate\tsalary\tdept\n");
  printf("------------------------------------------------------------\n");

  /* 
   * Now fetch the result set and display.
   */

  while (1)
  {
    sb4 err = 0;
    if (err = ofetch(&cursor_emp))
    {
      if (cursor_emp.rc == 1403)
         break;
      else 
      {
         oracle_error(&cursor_emp);
         exit(EXIT_FAILURE);
      }
    }
    else 
    {
      /* A row was returned; have to do the fetch. */

      fprintf(stdout, "%d\t%s\t%s\t%d\t%s\t%d\t%d\n\n",
              empno, ename, job, mgr, hidate, sal, deptno);
    }
  }

  /* 
   * Log off.
   */

  if (ologof(ldap))
  {
     oracle_error(&cursor_emp);
     exit(EXIT_FAILURE);
  }
} /* end of main */


void oracle_error(lda)
Lda_Def * lda;
{
  char msgbuf[512];
  int n=oerhms(lda, lda->rc, msgbuf, (int) sizeof(msgbuf) );
   
  printf("\n\n%.*s\n",n,msgbuf);
} 


cdemo6.cc

/*      -- cdemo6.cc --
 *  An example program which illustrates how a C++ program
 *  can use the OCI interface to access ORACLE database.
 *
 *  This program retrieves department name, given the
 *  department number.
 *  
 *  The program queries the user for data as follows:
 *   
 *  Enter department number:
 *   
 *  The program terminates if -1 is entered
 *  when the department number is requested.
 */
extern "C"
{
#include <stdio.h>
#include <oratypes.h>
#include <ociapr.h>
/* demo constants and structs */
#include <ocidem.h>
}
extern "C"
{
#include <oratypes.h>
#include <ocidfn.h>
#include <ocidem.h>
}
/* oparse flags */
#define  DEFER_PARSE        1
#define  NATIVE             1
#define  VERSION_7          2
/* Class forward declarations */
class connection;
class cursor;
/*
 * This class represents a connection to ORACLE database.
 *
 * NOTE: This connection class is just given as an example and 
 * all possible operations on a connection have not been defined.
 */
class connection
{
  friend class cursor;
  public:
    connection() 
      { state = not_connected; }
    ~connection();
    sword connect(const text *username, const text *password);
    sword disconnect();
    void display_error(FILE* file) const;
  private:
    Lda_Def lda;
    ub1 hda[HDA_SIZE];
    enum conn_state
    {
      not_connected,
      connected
    };
    conn_state state;
};
/*
 * This class represents an ORACLE cursor.
 *
 * NOTE: This cursor class is just given as an example and all
 * possible operations on a cursor have not been defined.
 */
class cursor
{
  public:
    cursor() 
      {state = not_opened; conn = (connection *)0; }
    ~cursor();
    sword open(connection *conn_param);
    sword close();
    sword parse(const text *stmt)
      { return (oparse(&cda, (text *)stmt, (sb4)-1, 
                       DEFER_PARSE, (ub4) VERSION_7)); }
    /* bind an input variable */
    sword bind_by_position(sword sqlvnum, ub1 *progvar, 
                           sword progvarlen, sword datatype, 
                           sword scale, sb2 *indicator)
      { return (obndrn(&cda, sqlvnum, progvar, progvarlen,
                datatype, scale, indicator, (text *)0, -1, -1)); }
    /* define an output variable */
    sword define_by_position(sword position, ub1 *buf, 
                sword bufl, sword datatype, sword scale,
                sb2 *indicator, ub2 *rlen, ub2 *rcode)
      { return (odefin(&cda, position, buf, bufl, datatype, 
                       scale, indicator,
                       (text *)0, -1, -1, rlen, rcode)); }
    sword describe(sword position, sb4 *dbsize, sb2 *dbtype, 
                   sb1 *cbuf, sb4 *cbufl, sb4 *dsize, sb2 *prec,
                   sb2 *scale, sb2 *nullok)
      { return (odescr(&cda, position, dbsize, dbtype, 
                       cbuf, cbufl, dsize,  prec, scale, nullok));
      }
    sword execute()
      { return (oexec(&cda)); }
    sword fetch()
      { return (ofetch(&cda)); }
    sword get_error_code() const
      { return (cda.rc); }
    void display_error( FILE* file) const;
  private:
    Cda_Def cda;
    connection *conn;
    enum cursor_state
    {
      not_opened,
      opened
    };
    cursor_state state;
};
/* Error number macros */

#define CONERR_ALRCON -1            /* already connected */ 
#define CONERR_NOTCON -2            /* not connected */ 
#define CURERR_ALROPN -3            /* cursor is already open */
#define CURERR_NOTOPN -4            /* cursor is not opened */
/* exit status upon failure */
#define  EXIT_FAILURE       1
 
const text *username = (text *) "SCOTT";
const text *password = (text *) "TIGER";
/* define SQL statements to be used in the program */
const text *seldept = (text *) "SELECT dname FROM dept WHERE deptno = :1";
void err_report(FILE *file, text *errmsg, sword func_code);
void myfflush();
/* connection destructor */
connection::~connection() 
{
  // disconnect if connection exists
  if (state == connected)
  {
    if (disconnect())
    {
      display_error(stderr);
    }
  }
}
/* connect to ORACLE */
sword connection::connect(const text *username, const text *password)
{
  sword status;
  if (state == connected)
  {
    // this object is already connected
    return (CONERR_ALRCON);
  }
  if ((status = olog(&lda, hda, (text *)username, -1
                     (text *)password, -1, (text *) 0, -1,
                     OCI_LM_DEF)) == 0)
  {
    // successful login
    state = connected;
    printf("Connected to ORACLE as %s\n", username);
  }
  return (status);
}
/* disconnect from ORACLE */
sword connection::disconnect()
{
  sword status;
  if (state == not_connected)
  {
    // this object has not been connected
    return (CONERR_NOTCON);
  }
  if ((status = ologof(&lda)) == 0)
  {
    // successful logout
    state = not_connected;
  }
  return (status);
}
/* write error message to the given file */
void connection::display_error(FILE *file) const
{
  if (lda.rc != 0)
  {
    sword n;
    text msg[512];
    n = oerhms((cda_def *)&lda, lda.rc, msg, (sword) sizeof(msg));
    err_report(file, msg, lda.fc);
  }
}
/* cursor destructor */
cursor::~cursor()
{
  if (state == opened)
  {
    if (close())
      display_error(stderr);
  }
}
/* open the cursor */
sword cursor::open(connection *conn_param)
{
  sword status;
  if (state == opened)
  {
    // this cursor has already been opened
    return (CURERR_ALROPN);
  }
  if ((status = oopen(&cda, &conn_param->lda, (text *)0, -1, -1, 
                      (text *)0, -1)) == 0)
  {
    // successfull open
    state = opened;
    conn = conn_param;
  }
  return (status);
}
/* close the cursor */
sword cursor::close()
{
  sword status;
  if (state == not_opened)
  {
    // this cursor has not been opened
    return (CURERR_NOTOPN);
  }
  if ((status = oclose(&cda)) == 0)
  {
    // successful cursor close
    state = not_opened;
    conn = (connection *)0;
  }
  return (status);
}
/* write error message to the given file */
void cursor::display_error(FILE *file) const
{
  if (cda.rc != 0)
  {
    sword n;
    text msg[512];
    n = oerhms(&conn->lda, cda.rc, msg, (sword) sizeof(msg));
    err_report(file, msg, cda.fc);
  }
}
int main()
{
    sword deptno;
    sword len, dsize;
    sb4   deptlen;
    sb2   db_type;
    sb1   name_buf[20];
    text  *dept;
/* 
 *  Connect to ORACLE and open a cursor.
 *  Exit on any error.
 */

    connection conn;
    if (conn.connect(username, password))
    {
      conn.display_error(stderr);
      return(EXIT_FAILURE);
    }
    cursor crsr;
    if (crsr.open(&conn))
    {
      crsr.display_error(stderr);
      return(EXIT_FAILURE);
    }
    /* parse the SELDEPT statement */
    if (crsr.parse(seldept))
    {
      crsr.display_error(stderr);
      return(EXIT_FAILURE);
    }
    /* bind the placeholder in the SELDEPT statement */
    if (crsr.bind_by_position(1, (ub1 *) &deptno, 
                              (sword) sizeof(deptno),
                              INT_TYPE, -1, (sb2 *) 0))
    {
      crsr.display_error(stderr);
      return(EXIT_FAILURE);
    }  
    /* describe the select-list field "dname" */
    len = sizeof (name_buf);

    if (crsr.describe(1, (sb4 *) &deptlen, &db_type,
                      name_buf, (sb4 *) &len, (sb4 *) &dsize, 
                     (sb2 *) 0, (sb2 *) 0, (sb2 *) 0))
    {
      crsr.display_error(stderr);
      return(EXIT_FAILURE);
    }
    /* allocate space for dept name now that you have length */
    dept = new text((int) deptlen + 1);
    /* define the output variable for the select-list */
    if (crsr.define_by_position(1, (ub1 *) dept, (sword)deptlen+1,
                                STRING_TYPE, -1, (sb2 *) 0, 
                               (ub2 *) 0, (ub2 *) 0))
    {
      crsr.display_error(stderr);
      delete dept;
      return(EXIT_FAILURE);
    }
    for (;;)
    {
        /* prompt for department number, */
        /* break if given number == -1 */
        printf("\nEnter department number (or -1 to EXIT): ");
        while (scanf("%d", &deptno) != 1)
        {
          myfflush();
          printf("Invalid input, please enter a number \
                 (-1 to EXIT): ");
        }
        if (deptno == -1)
        {
          printf("Exiting... ");
          break;
        }
        /* display the name of the corresponding department */
        if (crsr.execute() || crsr.fetch())
        {
          if (crsr.get_error_code() != NO_DATA_FOUND)
          {
            crsr.display_error(stderr);
            delete dept;
            return(EXIT_FAILURE);
          }
          else


          printf("\n  The department number that you entered \
                 doesn't exist.\n");
        }
        else
       {
       printf("\n  Department name = %s    \
              Department number = %d\n", 
              dept, deptno);
       }
    }
    delete dept;
    printf ("\nG'day\n");
  return 0;
}
void err_report(FILE *file, text *errmsg, sword func_code)
{
    fprintf(file, "\n-- ORACLE error--\n\n%s\n", errmsg);
    if (func_code > 0)
        fprintf(file, "Processing OCI function %s\n",
            oci_func_tab[func_code]);
}
void myfflush()
{
  eb1 buf[50];
 
  fgets((char *) buf, 50, stdin);
}




Go to previous file in sequence Go to next file in sequence
Prev Next
Oracle
Copyright © 1996 Oracle Corporation.
All Rights Reserved.
Go to Product Documentation Library
Library
Go to books for this product
Product
Go to Contents for this book
Contents
Go to Index
Index