René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

A simple OCI program

The following code fragment is supposed to show how a connection can be made to an Oracle database with OCI.
Obviously, it won't do anything meaningful. However, it is possible to see that the application has connected to the database using v$session.
I was able to compile and link it on Linux with gcc:
gcc -c -I$ORACLE_HOME/rdbms/demo     \
       -I$ORACLE_HOME/rdbms/public   \
       -I$ORACLE_HOME/plsql/public   \
       -I$ORACLE_HOME/network/public \
       -I$ORACLE_HOME/precomp/public oci_test.c

gcc -L$ORACLE_HOME/lib/ -L$ORACLE_HOME/rdbms/lib/ -o oci_test oci_test.o -lclntsh   `cat $ORACLE_HOME/lib/sysliblist`
With mingw, the programm can be compiled and linked like this: gcc -o first.exe -I%ORACLE_HOME%\oci\include oci_test.c %ORACLE_HOME%\bin\oci.dll
#include <oci.h>



void checkerr(OCIError* err, sword status) {
  text errbuf[512];
  ub4 buflen;
  ub4 errcode;

  switch (status) {
  case OCI_SUCCESS:
    break;
  case OCI_SUCCESS_WITH_INFO:
    printf("Error - OCI_SUCCESS_WITH_INFO\n");
    break;
  case OCI_NEED_DATA:
    printf("Error - OCI_NEED_DATA\n");
    break;
  case OCI_NO_DATA:
    printf("Error - OCI_NO_DATA\n");
    break;
  case OCI_ERROR:
    OCIErrorGet ( err, (ub4) 1, (text *) NULL, &errcode,
            errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
    printf("Error - %s\n", errbuf);
    break;
  case OCI_INVALID_HANDLE:
    printf("Error - OCI_INVALID_HANDLE\n");
    break;
  case OCI_STILL_EXECUTING:
    printf("Error - OCI_STILL_EXECUTE\n");
    break;
  case OCI_CONTINUE:
    printf("Error - OCI_CONTINUE\n");
    break;
  default:
    break;
  }
}


void parse_connect_string(
   char* connect_str,  /* in   */
   text  username[30], /* out  */
   text  password[30], /* out  */
   text  dbname  [30]  /* out  */
) {

  username[0] = 0;
  password[0] = 0;
  dbname  [0] = 0;

  char* to=username;

  while (*connect_str) {
    if (*connect_str == '/') {
      *to=0;
      to=password;
      connect_str++;
      continue;
    }
    if (*connect_str == '@') {
      *to=0;
      to=dbname;
      connect_str++;
      continue;
    }
    *to=*connect_str;
    to++;
    connect_str++;
  }
  *to=0;
}

int main(int argc, char* argv[]) {
/*  (void) OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)           0,
                       (dvoid * (*)(dvoid *, size_t))         0,
                       (dvoid * (*)(dvoid *, dvoid *, size_t))0,
                       (void (*)(dvoid *, dvoid *))           0 ); */



  /* The environment handle defines a context in which all OCI functions are
     invoked. Each environment handle contains a memory cache, which allows for
     fast memory access. All memory allocation under the environment handle is
     done from this cache. Access to the cache is serialized if multiple
     threads try to allocate memory under the same environment handle. When
     multiple threads share a single environment handle, they may block on
     access to the cache. The environment handle is passed as the parent
     parameter to the OCIHandleAlloc() call to allocate all other handle types.
     Bind and define handles are allocated implicitly.
  */
  OCIEnv*       env;

  /* The error handle is passed as a parameter to most OCI calls. The error
     handle maintains information about errors that occur during an OCI
     operation. If an error occurs in a call, the error handle can be passed to
     OCIErrorGet() to obtain additional information about the error that
     occurred. Allocating the error handle is one of the first steps in an OCI
     application because most OCI calls require an error handle as one of its
     parameters. */
  OCIError*     err;

  OCIServer*    srv;
  OCISvcCtx*    svc;
  OCISession*   ses;

  text          username[30];
  text          password[30];
  text          dbname  [30];

  sword         r;

  if (argc < 2) {
    printf("usage %s username/password[@dbname]\n");
    exit (-1);
  }

  parse_connect_string(argv[1],username, password, dbname);

  env           =       0;
  err           =       0;
  srv           =       0;
  svc           =       0;
  ses           =       0;

  r=OCIEnvCreate( &env, OCI_DEFAULT, 0, 0, 0, 0, 0, 0); 

  if (r != OCI_SUCCESS)  {
    printf("OCIEnvCreate failed!\n");
    goto clean_up;
  }

  OCIHandleAlloc(env, (dvoid**)&err, OCI_HTYPE_ERROR,   0, 0);
  OCIHandleAlloc(env, (dvoid**)&srv, OCI_HTYPE_SERVER,  0, 0);
  OCIHandleAlloc(env, (dvoid**)&svc, OCI_HTYPE_SVCCTX,  0, 0);
  OCIHandleAlloc(env, (dvoid**)&ses, OCI_HTYPE_SESSION, 0, 0);

  r=OCIServerAttach(srv, err,  dbname, strlen(dbname), (ub4) OCI_DEFAULT);
  if (r != OCI_SUCCESS) {
    checkerr(err, r);
    goto clean_up;
  }

  /* set attribute server context in the service context */
  OCIAttrSet(svc, OCI_HTYPE_SVCCTX, srv, 0, OCI_ATTR_SERVER,  err);

  OCIAttrSet(ses, OCI_HTYPE_SESSION, username, strlen(username), OCI_ATTR_USERNAME, err); 
  OCIAttrSet(ses, OCI_HTYPE_SESSION, password, strlen(password), OCI_ATTR_PASSWORD, err); 

  r=OCISessionBegin (svc, err, ses, OCI_CRED_RDBMS, OCI_DEFAULT);
  checkerr(err, r);


clean_up:

  if (env) OCIHandleFree(env, OCI_HTYPE_ENV   );
  if (err) OCIHandleFree(err, OCI_HTYPE_ERROR );
  if (srv) OCIHandleFree(srv, OCI_HTYPE_SERVER);
  if (svc) OCIHandleFree(svc, OCI_HTYPE_SVCCTX);

  OCITerminate(OCI_DEFAULT);

  return 0;
}

Links

See also adpoci.