朋友托我写个OCI程序

来源:互联网 发布:知乎 湖南农民考察报告 编辑:程序博客网 时间:2024/05/16 09:07

朋友托我写个OCI程序,于是到网上东拼西凑,搞了个

 

1. 平台:AIX或LINUX

2. makefile

### makefile :  My first OTLV4 For Oracle On AIX  2009-12-1 by tan

PRECOMPHOME=$$ORACLE_HOME/precomp/public
PROCINCLUDE=include=.  /
include=${ORACLE_HOME}/precomp/syshdr /
include=${ORACLE_HOME}/precomp/public /
include=${ORACLE_HOME}/rdbms/public /
include=${ORACLE_HOME}/rdbms/demo /
include=${ORACLE_HOME}/plsql/public /
include=${ORACLE_HOME}/network/public /
include=$(ORACLE_HOME)/precomp/lib/env_precomp.mk
ORALIBPATH=$(ORACLE_HOME)/lib
ORALIBS=-locci -lclntsh  -ldl -lm -lnsl

INCLUDE= -I.   -I/usr/include -I/usr/vacpp/include  -I${ORACLE_HOME}/precomp/public /
   -I${ORACLE_HOME}/rdbms/public /
   -I${ORACLE_HOME}/rdbms/demo /
   -I${ORACLE_HOME}/plsql/public
  
LIBPATH=-L/usr/vacpp/lib  -L/lib  -L$(ORALIBPATH) $(ORALIBS)  #-L/usr/lib

CC = xlC  -q64
#CC=g++ -g

CC_FLAGS =

 

PROGRAM = run

ALL : $(PROGRAM)

.SUFFIXES: .cpp .c .cc .cxx .o
.DEFAULT : all


SRCS = storedproc.cpp  myoci.cpp

OBJS = $(SRCS:.cpp=.o)
 
$(PROGRAM) : $(OBJS)
  $(CC)  $(INCLUDE) $(LIBPATH) $(OBJS) -o $(PROGRAM)  ${LIBPATH}
.cpp.o:
 $(CC) $(INCLUDE) $(CC_FLAGS)   -c $<
 
clean:
 - rm -f  ./*.o ./*.a ./$(PROGRAM)

### END---MAKEFILE

 

3.

// myoci.h:

#ifndef __MY_OCI_H__
#define __MY_OCI_H__
 
#include <oci.h>
 
#define OK 1
#define ERROR 0
 
/*--- define OCI handle struct---*/
typedef struct{
        OCIEnv           *p_env;
        OCIError         *p_err;
        OCISvcCtx        *p_svc;
        OCIStmt          *p_sql;
        OCIDefine        *p_dfn;
        OCIBind          *p_bnd;
}OCIDATA;
 
/*--- output error information  ---*/
void error_proc(dvoid *errhp, sword status);
 
/*--- create env and initialize OCI handle ---*/
void ociCreatEvnHandle(OCIDATA *data);

/*--- logon oracle database ---*/
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername);
 
/*--- prepare sql ---*/
void ociStmtPrepare(OCIDATA *data, char *strSql);
 
/*--- bind data on array from database ---*/
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type);
 
/*--- execute sql ---*/
sword  ociStmtExecute(OCIDATA *data);
 
/*--- fetch data until output finish ---*/
sword  ociStmtFetch(OCIDATA *data);

 
/*--- logoff and release handles ---*/
void ociHandleFree(OCIDATA *data);


int oci_insert(char *sql, char * out);
int oci_query(char *sql, char  *out);
void ociCreatEvnHandle(OCIDATA *data);
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type);
void ociHandleFree(OCIDATA *data);
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername);
sword  ociStmtExecute(OCIDATA *data);
sword  ociStmtFetch(OCIDATA *data);
void ociHandleFree(OCIDATA *data);

#endif // __MY_OCI_H__

 

4.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>
#include "myoci.h"


CONST char *DB_USER     = "CRMCN_DEMO"; 
CONST char *DB_PASSWORD = "CRMCN_DEMO";
CONST char *DB_DBNAME   = "DEVDB150";

static OCIEnv           *p_env;
static OCIError         *p_err;
static OCISvcCtx        *p_svc;
static OCIStmt          *p_sql;
static OCIDefine        *p_dfn    = (OCIDefine *) 0;
static OCIBind          *p_bnd    = (OCIBind *) 0;

 

     

int oci_insert(char *sql, char * out)
{
   int             p_bvi;
   char            *p_sli;
   char            *p_sli1;
   int             rc;
   char            errbuf[100];
   int             errcode;

   /* Initialize OCI evironment*/
   rc = OCIEnvCreate((OCIEnv **) &p_env,OCI_DEFAULT,(dvoid *)0,
          (dvoid * (*)(dvoid *, size_t)) 0,
          (dvoid * (*)(dvoid *, dvoid *, size_t))0,
          (void (*)(dvoid *, dvoid *)) 0,     
          (size_t) 0, (dvoid **) 0);
 
   /* Initialize handles */
   rc = OCIHandleAlloc( (dvoid *) p_env, (dvoid **) &p_err, OCI_HTYPE_ERROR,
           (size_t) 0, (dvoid **) 0);
   rc = OCIHandleAlloc( (dvoid *) p_env, (dvoid **) &p_svc, OCI_HTYPE_SVCCTX,
           (size_t) 0, (dvoid **) 0);

   /* Connect to database server */
  

   rc = OCILogon(p_env, p_err, &p_svc,
                    (CONST OraText *)DB_USER,     (ub4)strlen((const char *)DB_USER),
                    (CONST OraText *)DB_PASSWORD, (ub4)strlen((const char *)DB_PASSWORD),
                    (CONST OraText *)DB_DBNAME,   (ub4)strlen((const char *)DB_DBNAME)  );

   if (rc != 0) {
      OCIErrorGet((dvoid *)p_err, (ub4) 1, (text *) NULL, &errcode, (OraText *)errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
      printf("Error - %.*s/n", 512, errbuf);
      exit(8);
   }
   else
   {
    printf("Connect to orcl successful! /n");
   }

   /* Allocate and prepare SQL statement */
   rc = OCIHandleAlloc((dvoid *) p_env, (dvoid **) &p_sql,
           OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);

   rc = OCIStmtPrepare(p_sql, p_err, (CONST OraText *)sql,
           (ub4) strlen(sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);


   /* Execute the SQL statment */

   rc = OCIStmtExecute(p_svc, p_sql, p_err, (ub4) 1, (ub4) 0,
           (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);
 

   if(rc != OCI_SUCCESS && rc != OCI_SUCCESS_WITH_INFO){
        printf("insert error!/n");
        OCIErrorGet((dvoid *)p_err, (ub4) 1, (text *) NULL, &errcode, (OraText *)errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
        sprintf(out,"insert error message: %s",errbuf);
        return 0;
        }
   else
        printf("insert success!/n");
        sprintf(out,"insert success!/n");

   rc = OCILogoff(p_svc, p_err);                           /* Disconnect */
   rc = OCIHandleFree((dvoid *) p_sql, OCI_HTYPE_STMT);    /* Free handles */
   rc = OCIHandleFree((dvoid *) p_svc, OCI_HTYPE_SVCCTX);
   rc = OCIHandleFree((dvoid *) p_err, OCI_HTYPE_ERROR);

   return 1;
}


int oci_query(char *sql, char  *out){ 
/*--- initialize ---*/  
        OCIDATA  data;
       
        const int NUM=30;
       
        char USER[31];  
        char PASS_WORD[31];  
        char SERVERNAME[31];

  
        char out1[NUM];//output num 1 column   
        char out2[NUM];//output num 2 column   
        char out3[NUM];//output num 3 column   
        char out4[NUM];
        char temp[100];
        sword  re;//return param   
  
        strcpy(USER,"scott");  
        strcpy(PASS_WORD,"tiger");  
        strcpy(SERVERNAME,"orcl");  
  
/*--- get data from oracle database ---*/  
        ociCreatEvnHandle(&data);//initialize handle   
        ociLogon(&data, USER, PASS_WORD, SERVERNAME);//logon database   
        ociStmtPrepare(&data, sql);//prepare sql   
  
/*--- bind data from database ---*/  
        ociDefineByPos(&data, 1, out1, SQLT_CHR);//bind mum 1 column   
        ociDefineByPos(&data, 2, out2, SQLT_CHR);//bind num 2 column   
        ociDefineByPos(&data, 3, out3, SQLT_CHR);//bind num 3 column   
        ociDefineByPos(&data, 4, out4, SQLT_CHR);//bind num 3 column
  
/*--- initialize output array---*/  
        memset(out1,0,NUM);  
        memset(out2,0,NUM);  
        memset(out3,0,NUM);
        memset(out4,0,NUM);  
  
/*--- execute sql ---*/  
        re = ociStmtExecute(&data);  
  
/*--- output data from database ---*/  
        while(re != OCI_NO_DATA){  
        //      printf("%s/n", out1);   
                sprintf(temp,"%s %s %s %s/n", out1, out2, out3,out4);
                strcat(out,temp);
                memset(temp,0,100);  
                re = ociStmtFetch(&data);  
        }  
  
/*--- logout and release handles ---*/  
        ociHandleFree(&data);  
       
        return 1;
}

 

/*--- output error information  ---*/
void error_proc(dvoid *errhp, sword status)
{
        text errbuf[512];
        sb4 errcode;
        switch (status)
        {
        case OCI_SUCCESS:
//                      printf("OCI_SUCCESS/n");
                        break;
        case OCI_SUCCESS_WITH_INFO:
                        printf("OCI error: OCI_SUCCESS_WITH_INFO/n");
                        break;
        case OCI_NEED_DATA:
                        printf("OCI error: OCI_NEED_DATA/n");
                        break;
        case OCI_NO_DATA:
                        printf("OCI error: OCI_NO_DATA/n");
                        break;
        case OCI_ERROR:
                        (void)OCIErrorGet((dvoid *)errhp,(ub4)1,NULL,&errcode,
                                errbuf,(ub4)sizeof(errbuf),OCI_HTYPE_ERROR);
                        printf("....%d/n.....%s/n",errcode,errbuf);
                        break;
        case OCI_INVALID_HANDLE:
                        printf("OCI error: OCI_INVALID_HANDLE/n");
                        break;
        case OCI_STILL_EXECUTING:
                        printf("OCI error: OCI_STILL_EXECUTING/n");
                        break;
        default:
                        break;
        }
}
 
/*--- create env and initialize OCI handle ---*/
void ociCreatEvnHandle(OCIDATA *data){
        sword re;
        //......
        re = OCIEnvCreate(&(data->p_env),OCI_DEFAULT,(dvoid *)0,
          0,0,0,0,(dvoid **)0);
        //......
        re = OCIHandleAlloc((dvoid *)data->p_env, (dvoid **)&(data->p_err),
          OCI_HTYPE_ERROR,0,(dvoid **)0);
        if(re != 0)
                printf("creation fail!");
        error_proc(data->p_err, OCIHandleAlloc((dvoid *)data->p_env,
                 (dvoid **)&(data->p_svc),  OCI_HTYPE_SVCCTX, 0, 0));
}
/*--- logon oracle database ---*/
void ociLogon(OCIDATA *data, char *user, char *pwd, char *servername){
        sword status;
        status = OCILogon(data->p_env, data->p_err,  &(data->p_svc),
                (CONST OraText *)user,
                (ub4) strlen((char *)user),
                (CONST OraText *)pwd,
                (ub4)strlen((char *)pwd),
                (CONST OraText *)servername,
                (ub4)strlen((char *)servername));
        if (status==OCI_SUCCESS)
                printf("connection success!/n");
        else {
                printf("....connect fail!/n");
                printf("-----ORA_search,ERROR in OCILogon-----/n");
                error_proc(data->p_err,status);
        }
}
 
/*--- prepare sql ---*/
void ociStmtPrepare(OCIDATA *data, char *strSql){
        error_proc(data->p_err, OCIHandleAlloc((dvoid *)data->p_env,
                (dvoid **)&(data->p_sql),  OCI_HTYPE_STMT, 0, 0));
        error_proc(data->p_err, OCIStmtPrepare(data->p_sql, data->p_err, (CONST OraText *)strSql,
           (ub4) strlen((char *)strSql), (ub4) OCI_NTV_SYNTAX,
                (ub4) OCI_DEFAULT));
}
 
/*--- bind data on array from database ---*/
void ociDefineByPos(OCIDATA *data, int pos, char *out, ub2 type){
        error_proc(data->p_err, OCIDefineByPos(data->p_sql, &(data->p_dfn),
                data->p_err, pos, (dvoid *) out, (sword)20,
                 type, (dvoid *) 0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT));
 
}
 
/*--- execute sql ---*/
sword  ociStmtExecute(OCIDATA *data){
        sword status;
        if ((status=OCIStmtExecute(data->p_svc, data->p_sql,
                data->p_err, (ub4) 0, (ub4) 0,(CONST OCISnapshot *) NULL,
                (OCISnapshot *) NULL, OCI_DEFAULT))
                && status != OCI_SUCCESS_WITH_INFO)
        {       //.....
                error_proc(data->p_err,status);
                printf("-----ORA_search,ERROR in OCIStmtExecute-----/n");
                return ERROR;
        }
        return status;
}
 
/*--- fetch data until output finish ---*/
sword  ociStmtFetch(OCIDATA *data){
        sword re;
        re = OCIStmtFetch(data->p_sql, data->p_err, 1, 0, 0);
        return re;
}
 
/*--- logoff and release handles ---*/
void ociHandleFree(OCIDATA *data){
        OCILogoff(data->p_svc, data->p_err);
        OCIHandleFree(data->p_sql, OCI_HTYPE_STMT);    // Free handles
        OCIHandleFree(data->p_svc, OCI_HTYPE_SVCCTX);
        OCIHandleFree(data->p_err, OCI_HTYPE_ERROR);
}

5.   

-- storedproc.cpp 
/*****
####################  使用OCI编写多线程的ORACLE应用软件 ###############
OCI的OCIThread软件包提供了一些线程化函数,主要有三种类型。实际使用情况见后面的编程实例。
⑴初始化和结束函数
在调用其他函数之前必须调用OCIThreadProcessInit()函数,执行OCIThread软件包的初始化工作,然后再调用OCIThreadInit()函数,初始化OCIThread上下文,供其他OCIThread函数使用。调用OCIThreadTerm()函数,结束OCIThread接口层的处理,释放OCIThread上下文内存。
⑵线程管理函数
类型为OCIThreadHandle的线程句柄用于表示线程的内部数据结构。在使用之前,应该用OCIThreadHndInit()来分配和初始化,用完后应调用OCIThreadHndDestroy()来释放内存。用OCIThreadCreate()函数创建新线程。用OCIThreadId类型变量来标识一个线程。使用OCIThreadIdInit()来分配和初始化线程ID,而用OCIThreadIdDestroy()来释放线程ID的结构。用OCIThreadClose()函数关闭线程。OCIThreadJoin()函数允许调用者线程与其他线程连接,当要想连接的线程正在运行时,阻塞调用该函数的线程。直到指定的线程运行结束,这个调用者线程才被唤醒,方能继续执行下去。
⑶互斥锁管理函数
在应用程序中用类型OCIThreadMutex的变量来表示互斥锁。互斥锁在使用之前必须用OCIThreadMutexInit()初始化,用完后要用OCIThreadMutexDestroy()释放内存结构。一个线程可用OCIThreadMutexAcquire()来掌握一把互斥锁,任何时候至多只能有一个线程掌握这把互斥锁,掌握这把互斥锁的线程能够用OCIThreadMutexRelease()来释放它。当一个线程掌握这把互斥锁后,其它线程若想再掌握这把互斥锁,就会被阻塞。直到掌握这把锁的线程释放它,被阻塞的线程之一才能得到它,获得互斥锁的线程才能继续执行下去。


下面用一个实例来讲述多线程方式ORACLE应用程序的编写和多线程的运行机制,仍以显示地震三维数据体为例。
将从数据库中读数据当作一个线程,
数据解压,三维图象处理和显示当作另一个线程,
在进程中给出二个数据缓冲区,使这二个线程轮流交叉使用这二个缓冲区。并用二把互斥锁来协调这二个线程对缓冲区的使用。
为能清楚而简单地说明线程和互斥锁的使用,这里仅给出程序的主要代码段。

 

*****/


#include "myoci.h"
#include <oci.h>
#include <string.h>
#include <stdio.h>

 

struct thrs_data {
   OCIThreadMutex *mutex1;// 缓冲区1互斥锁
   int buffer1[10240];    // 缓冲区1
   OCIThreadMutex *mutex2;// 缓冲区2互斥锁
   int buffer2[10240];    // 缓冲区2
   int flag;              // 数据处理结束标志
   int start_read;        // 开始读数据标志
   int start_disp;        // 开始显示数据标志
};
 
const int BUF_SIZE = 1024;

OCIEnv    *envhp;///OCI环境句柄
OCIError  *errhp;///OCI错误记录句柄


void read_fun(dvoid *arg);
void disp_fun(dvoid *arg);
int test_many_thread(void);

 

 

 

 

int main(int argc, char* argv[])
{
    // test_many_thread();
   
    char recvbuf[BUF_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf) );
    char sendbuf[BUF_SIZE];
    memset(sendbuf, 0, sizeof(sendbuf) );
   
    strcpy(recvbuf, "INSERT INTO T VALUES (1,2,3,4) ");

    oci_insert(recvbuf,  sendbuf);

    printf("sendbuf :  %s", sendbuf);
   
    return 0;   
}

int test_many_thread(void)
{
   
    OCIThreadId *tId1,*tId2;               //线程ID句柄
    OCIThreadHandle *tHnd1,*tHnd2;         //线程句柄
    struct thrs_data op_data;              //定义数据
   
    // OCI初始化(线程安全性)和分配句柄:
    OCIEnvCreate((OCIEnv **) &envhp,OCI_THREADED,(dvoid *)0,
     (dvoid* (*)(dvoid*,size_t))0,(dvoid* (*)(dvoid*,dvoid*,size_t))0,
     (void (*)(dvoid *, dvoid *)) 0, (size_t) 0,(dvoid **) 0 );
    
    
    OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,
      OCI_HTYPE_ERROR,(size_t)0, (dvoid **)0);
     
     
    // 线程软件包和线程初始化:
    OCIThreadProcessInit();
    OCIThreadInit(envhp,errhp);
   
   
    // 初始化线程ID和线程句柄:
    OCIThreadIdInit(envhp,errhp,&tId1);
    OCIThreadHndInit(envhp,errhp,&tHnd1);
    OCIThreadIdInit(envhp,errhp,&tId2);
    OCIThreadHndInit(envhp,errhp,&tHnd2);
   
   
    // 分配和初始化互斥锁:
    OCIThreadMutexInit(envhp,errhp,&(op_data.mutex1));
    OCIThreadMutexInit(envhp,errhp,&(op_data.mutex2));
    
    
    // 创建新的线程,执行线程函数调用:
    op_data.start_read=0;
    op_data.start_disp=0;
    OCIThreadCreate(envhp,errhp,read_fun,(dvoid *)&op_data,  tId1,tHnd1);
    OCIThreadCreate(envhp,errhp,disp_fun,(dvoid *)&op_data,  tId2,tHnd2);
   
   
    // 参数read_fun和disp_fun是二个线程函数,op_data是送给线程函数的变量。
    // 等待线程执行完成并关闭线程句柄:
    OCIThreadJoin(envhp,errhp,tHnd1);
    OCIThreadClose(envhp,errhp,tHnd1);
    OCIThreadJoin(envhp,errhp,tHnd2);
    OCIThreadClose(envhp,errhp,tHnd2);
   
   
    // 释放互斥锁内存:
    OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex1));
    OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex2));
   
   
    // 释放线程ID和线程句柄:
    OCIThreadIdDestroy(envhp,errhp,&tId1);
    OCIThreadHndDestroy(envhp,errhp,&tHnd1);
    OCIThreadIdDestroy(envhp,errhp,&tId2);
    OCIThreadHndDestroy(envhp,errhp,&tHnd2);
   
   
    // 释放线程上下文:
    OCIThreadTerm(envhp,errhp);
   
   
    // 释放所有分配的句柄。
    OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR);
    OCIHandleFree((dvoid *)envhp, OCI_HTYPE_ENV);
 
}


// 下面是二个线程函数主要代码段:

void read_fun(dvoid* arg)
{//  读数据进缓冲区函数
       
     struct thrs_data *op_data;
     int n=0;
     op_data=(struct thrs_data *)arg;
    
    
     for(int k=0;k<5;k++)
     {    //在实际应用中,此处可为for(;;) ,让退出循环的
          //条件由要读的实际数据确定,这里用5次循环,是为
          //了能够运行给出的框架程序。
          OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1);//获得互斥锁
          op_data->start_read=1;//告诉显示线程,读线程已使用缓冲区
          printf("read data into buffer1 .../n");
         
          //在实际应用中,此处应调用“读数据进缓冲区1”的函数。
          OCIThreadMutexRelease(envhp,errhp,op_data->mutex1);//释放互斥锁
          //在实际应用中,此处可为:当所有数据都读完时,使op_data->flag=1;并退出循环体
          OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);
          printf("read data into buffer2 .../n");
         
          //在实际应用中,此处应调用“读数据进缓冲区2”的函数。
          if(n==0) while(op_data->start_disp==0);//循环第一次结束时要等待显示线程启
           
          n=1;                                   //动并使用缓冲区
          OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);
         
          if(k==2) {          // 这里的代码段,是为了能演示框架程序;
            op_data->flag=2;  // 在实际应用中,此处可为:
            break;            // 当所有数据都读完时,使op_data->flag=2;
          }                   // 并退出循环体
     }
}
 

void disp_fun(dvoid* arg)
{   //处理和显示数据函数
    struct thrs_data *op_data;
    op_data=(struct thrs_data *)arg;
   
  
    for(;;)
    {
         while(op_data->start_read==0);//开始时保证读数据线程先使用缓冲区
        
         OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1);
         op_data->start_disp=1; //告诉读数据线程,显示线程已开始使用缓冲区
         printf(" display buffer1 .../n");
        
         //在实际应用中,此处应调用“使用缓冲区1中数据,解压,图象处理和显示”的函数。
         OCIThreadMutexRelease(envhp,errhp,op_data->mutex1);
         if(op_data->flag==1) break; //退出循环体,返回
           
         OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);
         printf(" display buffer2 .../n");
         //在实际应用中,此处应调用“使用缓冲区2中数据,解压,图象处理和显示”的函数。
         OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);
         if(op_data->flag==2) break;//退出循环体,返回
    }
}

 

------------end------------

原创粉丝点击