oci批量提取oracle数据写入mongodb或写成bson文件

项目需要,将oracle中上亿的数据表数据提取到mongdb,通过api单条插入,效率极低。通过第三方工具data-integration导入,效率还不够高。最终只能根据需求编写程序。

最初思路是解析oracle导出的dump二进制文件,在转换为bson二进制导入mongodb,但是根据测试,效率依旧较低。发现oracle与mongodb都采用批处理,效率算数有进步,最终决定采用编写程序实现。以下是在centos测试机器1万批量测得,鉴于代码未继续优化以及主机性能不强,后续效率还待测试:

oci批量提取oracle数据写入mongodb或写成bson文件_第1张图片

在oracle导入mongodb时,通过oci批量提取数据,调用mongc driver批量写入mongddb,大幅提升效率,120万批量处理速度约21845条/s。代码还可继续优化,如使用oracle分页技术分多进程,理论提高页数倍,如有更好方式,也请分享,谢谢。以下为100万批量处理时速度记录:

oci批量提取oracle数据写入mongodb或写成bson文件_第2张图片

oci程序中批量提取函数OCIDefineArrayOfStruct只能绑定静态数据,通过malloc开辟连续空间实现静态数组即可。以下为测试代码,后续请自行改进(需具备oci、mongodb、mongodb c driver、bson知识):

ToBson.h:

/**
* @file  ToBson.h
* @brief 导出ORACLE数据表或JSON文件为SBON文件、查看BSON文件工具
* @author   wangcc3
* @date     2018-1-5
* @version  001
* @copyright Copyright (c) 2018,AsiaInfo(FzOcs)
*/
#ifndef _TO_BSON_H_
#define _TO_BSON_H_

#include 
#include 
#include 
#include 
#include 

namespace BM35 {

using namespace std;

// 地址对齐
#define ALIGNMENT 8
#define ADDRPADDING(p, a) (uintptr_t)(((uintptr_t)a - ((uintptr_t)p % (uintptr_t)a)) % (uintptr_t)a)
#define ADDRALIGN(p, a) (char *)(((uintptr_t)p + ((uintptr_t)a - 1))&~((uintptr_t)a -1))

// 默认最大行数
#define _MAX_ROW_NUMS_ 1000000

/*
typedef unsigned char  ub1;
typedef   signed char  sb1;
typedef unsigned short    ub2;
typedef   signed short    sb2;
typedef unsigned int  ub4;
typedef   signed int  sb4;
typedef         ub4      duword;
typedef         sb4      dsword;
typedef         dsword   dword;
*/

// oracle句柄结构体
typedef struct _oci_env_
{
    OCIEnv      *envhp;
    OCIError    *errhp;
    OCISvcCtx   *svchp;
    OCIServer   *srvhp;
    OCISession	*usrhp;
    OCIStmt	    *smthp;
    OCIParam    *paramhp;
} OCI_ENV;

// 字段信息
class OracleField {
public:
    char *colName;
    char *colPoint;
    int	colScale;
    int colOffset;
    ub2 colType;
    ub2 colDefineType;
    ub2 coLen;
    ub4 colNameLen;
    OCIDefine *ociDefine;
};

// 配置结构体
class OCI_CONF
{
public:
    int flag;
    long rownum;
    long long begin;
    long long end;
    string table;
    string sql;
    string bfile; //可空
    string jfile;
    string tns;
    string user;
    string passwd;
    string mongouri;
    string mongodb;
    string mongocollection;

    void init() {
        flag = 0;
        rownum = 0;
        begin = -1;
        end = -1;
        table = "";
        sql = "";
        bfile = ""; //可空
        jfile = "";
        passwd = "";
        user = "";
        tns = "";
        mongouri = "";
        mongodb = "";
        mongocollection = "";
    }
};

class ToBson
{

public:

    ToBson();
    ~ToBson();

    // 运行入口
    bool run(string & sJsonFile);

    // 运行入口
    bool run(OCI_CONF & conf);

    // 获得错误信息
    string getErrInfo();


private:

    // 运行
    bool run();

    // 输出容器配置信息
    void printConf(vector::iterator vIter);

    // 关闭BSON文件
    void closeFile();

    /* flag: 1ORACLETOBSON  2JSONTOBSON  3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB
     * 解析配置文件config.json:
     {"note":"遍历完所有flag=1 or 6的配置时,tns、user、passwd三个字段必须存在,字段实际生效按第一次出现配置"}
     {"note":"遍历完所有flag=6的配置时,uri、mdb二个字段必须存在,字段实际生效按第一次出现配置"}
     {"note":"flag: 1ORACLETOBSON  2JSONTOBSON  3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB"}
     {"flag":1,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST9","bfile":"./TEST9.bson","sql":"","note":"bfile,[sql/table] can empty"}
     {"flag":1,"table":"TEST10","bfile":"./TEST10.bson"}
     {"flag":2,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line json to bson file,default all"}
     {"flag":3,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line bson to json file,default all"}
     {"flag":4,"bfile":"./TEST9.bson","begin":0,"end":4,"note":"read 0-4 line bson file info,default first 10 line"}
     {"flag":5,"bfile":"./TEST9.bson","note":"get bson file line nums"}
     {"flag":6,"table":"TEST9","uri":"mongodb://192.168.1.123:20000/","mdb":"mongodb","collection":"TEST9","note":"read oracle to mongodb"}
    */
    bool ParseConfig(string sJsonFile);

    // 获得SQL表名
    bool getTableName(char * sql, string &strOut, bool onlyTable = true);

    // 端口ORACLE连接
    bool closeOracle();

    // 端口MONGODB连接
    bool closeMongodb();

    // 将JSON文件写成BSON文件
    bool writeBson(string sJsonFile, string sBsonFile, long lBegin = -1, long lEnd = -1);

    // 将BSON文件写成JSON文件
    bool writeJson(string sBsonFile, string sJsonFile, long lBegin = -1, long lEnd = -1);

    // 初始化参数
    bool initParameter(const string tableName = "",
                       const string fileName = "",
                       const long maxRowNum = _MAX_ROW_NUMS_);

    // 初始化MONGODB参数
    bool initMongodb(const string database = "",
                     const string table = "");

    // 设置SQL语句
    bool setSql(string sSql);

    // 连接ORACLE
    bool connectOracle(text *dnName,text *userName, text *passWord);

    // 连接MONGODB
    bool connectMongodb(const string &uri);

    // 打开MONGODB数据库
    bool useDB(const string &databaseName);

    // 使用MONGODB数据表
    bool useTable(const string &tableName);

    // 插入MONGODB
    bool insert(string & sJsonDoc);

    // 将表数据写成BSON文件
    bool writeTableInfo();

    // 写入BSON文件
    bool writeBson(bson_t * bsonDoc, FILE *fp);

    // 检测ORACLE错误
    bool checkErr(OCIError *pErr, sword lSattus);

    // 打开BSON文件
    bool openFile(const char * sFileName);

    // 读取BSON文件信息
    bool readBson(string sBsonFile, long lBegin = -1, long lEnd = -1);

    // 获得ORACLE定义类型
    ub2 getDefineType(ub2 iType);

    // 获得缓存列偏移量
    int getOffset(int col);

    // 获得BSON文件记录数
    long getBsonNum(string sBsonFile);

    // 获得当前系统时间
    string getTime();

    // 去除换行
    string trimNewline(char * str);


private:

    bool bIsSetSql;
    bool isOracle;
    bool isMongodb;
    bool isWriteMongo;
    bool isInitDb;
    char sTnsName[32];
    char sUserName[32];
    char sPassWord[32];
    char sTableName[32];
    char sErr[512] = {0};
    char sqlText[512];
    char rowNum[32];
    string sSqlTable;
    string sSqlRow;
    string sBsonFile;
    string errMsg;
    string nowTable;
    string mDatabaseName;
    string mTableName;
    string mUri;
    char *pBuf;
    char *pBufPoint;
    text *colName;
    FILE *fp;
    bson_t * docBson;
    mongoc_client_t      *mClient;
    mongoc_database_t    *mDatabase;
    mongoc_collection_t  *mCollection;
    mongoc_bulk_operation_t *bulk;
    OCIDefine *dfnhp;
    OracleField *pOracleField;
    int iRowLen;
    ub2 coLen;
    ub4 colNum;
    ub4 colnameLen;
    ub4 rrows;
    ub4 psz;
    sb4 para_status;
    sb4 status;
    long lMaxRowNum;
    long lBufSize;
    long long lNowRow;
    long bsonNums;
    bson_t bsonDoc;
    bson_error_t  bson_error;
    OCI_ENV stOciEnv;
    vector vConf;
    vector::iterator vIter;

};

}

#endif //_TO_BSON_H_



ToBson.cpp:

/**
* @file  ToBson.cpp
* @brief 导出ORACLE数据表或JSON文件为SBON文件、查看BSON文件工具
* @author   wangcc3
* @date     2018-1-5
* @version  001
* @copyright Copyright (c) 2018,AsiaInfo(FzOcs)
*/

#include 
#include 
#include 
#include 
#include 
#include "ToBson.h"

namespace BM35 {

ToBson::ToBson() {

    fp = NULL;
    docBson = NULL;
    errMsg = "NO ERROR";
    sSqlRow = "";
    bIsSetSql = false;
    isInitDb = false;
    mDatabaseName = "";
    mTableName = "";
    mUri = "";
    mCollection = NULL;
    mDatabase = NULL;
    mClient = NULL;
    bulk = NULL;
    pOracleField = NULL;
    pBuf = NULL;
    bson_init(&bsonDoc);
    memset(sTableName, 0, sizeof(sTableName));
    memset(sqlText, 0, sizeof(sqlText));
    memset(sTnsName, 0, sizeof(sTnsName));
    memset(sUserName, 0, sizeof(sUserName));
    memset(sPassWord, 0, sizeof(sPassWord));
}

ToBson::~ToBson() {

    if(pOracleField) {
        for(int i = 0; i ::iterator vIter) {

    cout<flag == 1 ||
                vIter->flag == 6) {
            if(!isOracle) {
                errMsg = "Can't connect oracle";
                cout<flag == 6) && !isMongodb) {
                errMsg = "Can't connect mongodb";
                cout<sql.empty())
                setSql(vIter->sql);
            if(!vIter->rownum)
                vIter->rownum = _MAX_ROW_NUMS_;
            if(!initParameter(vIter->table,vIter->bfile,vIter->rownum)) {
                cout<flag == 6) {
                if(!initMongodb(vIter->mongodb, vIter->mongocollection)) {
                    cout<flag == 2) {
            if(!writeBson(vIter->jfile, vIter->bfile, vIter->begin, vIter->end)) {
                cout<flag == 3) {
            if(!writeJson(vIter->bfile, vIter->jfile, vIter->begin, vIter->end)) {
                cout<flag == 4) {
            if(!readBson(vIter->bfile,vIter->begin,vIter->end)) {
                cout<flag == 5) {
            cout<<"file "<bfile<<" record nums="<bfile)<tm_year);

    if(p->tm_mon < 10)
        sprintf(month, "0%d", 1 + p->tm_mon);
    else
        sprintf(month, "%d", 1 + p->tm_mon);

    if(p->tm_mday < 10)
        sprintf(day, "0%d", p->tm_mday);
    else
        sprintf(day, "%d", p->tm_mday);

    if(p->tm_hour < 10)
        sprintf(hour,"0%d",p->tm_hour);
    else
        sprintf(hour,"%d",p->tm_hour);

    if(p->tm_min < 10)
        sprintf(min, "0%d", p->tm_min);
    else
        sprintf(min, "%d", p->tm_min);

    if(p->tm_sec < 10)
        sprintf(second,"0%d",p->tm_sec);
    else
        sprintf(second,"%d",p->tm_sec);

    sprintf(nowTime, "%s/%s/%s %s:%s:%s",year, month, day, hour, min, second);

    //cNowTime = cNowTime + year + month + day + hour + min + second;

    return string(nowTime);
}

bool ToBson::connectMongodb(const string &uri) {

    if(uri.empty()) {
        errMsg = "Mongodb database connect uri is empty";
        return false;
    }
    mongoc_init();
    mClient = mongoc_client_new(uri.c_str());
    if(!mClient) {
        errMsg = "Create mongodb client failed!\n";
        return false;
    }

    return true;
}

bool ToBson::useDB(const string &databaseName) {

    if(databaseName.empty()) {
        errMsg = "databaseName is empty\n";
        return false;
    }

    if(mCollection) {
        mongoc_collection_destroy(mCollection);
        mCollection = NULL;
    }

    if(mDatabase) {
        mongoc_database_destroy(mDatabase);
        mDatabase = NULL;
    }

    mDatabase = mongoc_client_get_database(mClient, databaseName.c_str());
    if(!mDatabase) {
        errMsg = "Mongodb get database failed";
        return false;
    }

    isInitDb = true;
    return true;
}

bool ToBson::insert(string & sJsonDoc) {

    docBson = bson_new_from_json ((const uint8_t*)sJsonDoc.c_str(), -1, &bson_error);

    if (!docBson) {
        errMsg = bson_error.message;
        return false;
    }

    if(!mongoc_collection_insert(mCollection,
                                 MONGOC_INSERT_NONE,
                                 docBson, NULL, &bson_error)) {
        errMsg = bson_error.message;
        return false;
    }

    bson_destroy (docBson);

    return true;
}

bool ToBson::useTable(const string &tableName) {

    if(tableName.empty()) {
        errMsg = "Mogndb tableName is empty\n";
        return false;
    }
    if(mCollection) {
        mongoc_collection_destroy(mCollection);
        mCollection = NULL;
    }

    if(mDatabaseName.empty()) {
        errMsg = "Mongodb database is null, use useDB to init database instacne";
        return false;
    }

    mCollection = mongoc_client_get_collection(mClient,
                                               mDatabaseName.c_str(),
                                               tableName.c_str());
    if(!mCollection) {
        errMsg = "Mongodb get collection failed";
        return false;
    }

    return true;
}

bool ToBson::connectOracle(text *dnName,text *userName, text *passWord) {

    OCIEnvCreate(&stOciEnv.envhp, OCI_DEFAULT, (dvoid *) 0, 0, 0, 0, (size_t) 0, (dvoid **) 0);
    OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **)&stOciEnv.errhp, OCI_HTYPE_ERROR, 0, (dvoid **) 0);
    OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **)&stOciEnv.srvhp, OCI_HTYPE_SERVER, 0, (dvoid **) 0);
    if(OCIServerAttach(stOciEnv.srvhp, stOciEnv.errhp, (text *) dnName, strlen((char *) dnName), OCI_DEFAULT) != OCI_SUCCESS) {
        errMsg = "Connection database failure";
        return false;
    }
    OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.svchp, OCI_HTYPE_SVCCTX, (size_t) 0, (dvoid **) 0);
    OCIAttrSet((dvoid *) stOciEnv.svchp, OCI_HTYPE_SVCCTX, (dvoid *) stOciEnv.srvhp, (ub4) 0, OCI_ATTR_SERVER, (OCIError *) stOciEnv.errhp);
    OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.usrhp, OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
    OCIAttrSet((dvoid *) stOciEnv.usrhp, OCI_HTYPE_SESSION, (dvoid *) userName, (ub4) strlen((char *) userName), (ub4) OCI_ATTR_USERNAME, stOciEnv.errhp);
    OCIAttrSet((dvoid *) stOciEnv.usrhp, OCI_HTYPE_SESSION, (dvoid *) passWord, (ub4) strlen((char *) passWord), (ub4) OCI_ATTR_PASSWORD, stOciEnv.errhp);
    OCIAttrSet((dvoid *) stOciEnv.svchp, OCI_HTYPE_SVCCTX, (dvoid *) stOciEnv.usrhp, (ub4) 0, OCI_ATTR_SESSION, (OCIError *) stOciEnv.errhp);
    if(OCISessionBegin(stOciEnv.svchp, stOciEnv.errhp, stOciEnv.usrhp, OCI_CRED_RDBMS, OCI_DEFAULT) != OCI_SUCCESS) {
        errMsg = "Setting up user session failure";
        return false;
    }

    if(!checkErr(stOciEnv.errhp, OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.smthp, OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0 )))
        return false;
    return true;
}

bool ToBson::openFile(const char * sFileName) {

    if(!sFileName) {
        errMsg = "File is null";
        return false;
    }

    if((fp=fopen(sFileName,"w+"))==NULL) {
        errMsg = "Fail to open file";
        return false;
    }
    return true;
}

void ToBson::closeFile() {

    if(fp) {
        fclose(fp);
        fp = NULL;
    }
}

bool ToBson::ParseConfig(string sJsonFile) {

    if(sJsonFile.empty()) {
        errMsg = "Config file path is empty";
        return false;
    }
    vConf.clear();
    OCI_CONF tmpConf;
    tmpConf.init();
    string key;
    uint32_t len=0;
    bson_json_reader_t *reader;
    bson_error_t error;
    bson_t doc = BSON_INITIALIZER;
    int b;
    bson_iter_t iter;
    char errInfo[256] = { 0 };

    if (!(reader = bson_json_reader_new_from_file (sJsonFile.c_str(), &error))) {
        sprintf(errInfo, "Fail to open the json config file:%s", error.message);
        errMsg = errInfo;
        return false;
    }

    while ((b = bson_json_reader_read (reader, &doc, &error))) {
        if (b < 0) {
            //continue;
            sprintf(errInfo, "Parsing json file failure:%s", error.message);
            errMsg = errInfo;
            return false;
        }

        if (bson_iter_init(&iter, &doc)) {
            while(bson_iter_next(&iter)) {
                key = bson_iter_key(&iter);
                if(BSON_ITER_HOLDS_UTF8(&iter)) {
                    if(!key.compare("tns")) {
                        if(!strlen(sTnsName))
                            strcpy(sTnsName, bson_iter_utf8(&iter,&len));
                    } else if(!key.compare("user")) {
                        if(!strlen(sUserName))
                            strcpy(sUserName, bson_iter_utf8(&iter,&len));
                    } else if(!key.compare("passwd")) {
                        if(!strlen(sPassWord))
                            strcpy(sPassWord, bson_iter_utf8(&iter,&len));
                    } else if(!key.compare("table")) {
                        tmpConf.table = bson_iter_utf8(&iter,&len);
                    } else if(!key.compare("sql")) {
                        tmpConf.sql = bson_iter_utf8(&iter,&len);
                    } else if(!key.compare("bfile")) {
                        tmpConf.bfile = bson_iter_utf8(&iter,&len);
                    } else if(!key.compare("jfile")) {
                        tmpConf.jfile = bson_iter_utf8(&iter,&len);
                    } else if(!key.compare("uri")) {
                        if(mUri.empty())
                            mUri = bson_iter_utf8(&iter,&len);
                    } else if(!key.compare("mdb")) {
                        tmpConf.mongodb = bson_iter_utf8(&iter,&len);
                        if(mDatabaseName.empty())
                            mDatabaseName = tmpConf.mongodb;
                    } else if(!key.compare("collection")) {
                        tmpConf.mongocollection = bson_iter_utf8(&iter,&len);
                    } else
                        continue;
                } else if(BSON_ITER_HOLDS_INT64(&iter)) {
                    if(!key.compare("flag")) {
                        tmpConf.flag = bson_iter_int64(&iter);
                    } else if(!key.compare("rownum")) {
                        tmpConf.rownum = bson_iter_int64(&iter);
                    } else if(!key.compare("begin")) {
                        tmpConf.begin = bson_iter_int64(&iter);
                    } else if(!key.compare("end")) {
                        tmpConf.end = bson_iter_int64(&iter);
                    } else
                        continue;
                } else if(BSON_ITER_HOLDS_INT32(&iter)) {
                    if(!key.compare("flag")) {
                        tmpConf.flag = bson_iter_int32(&iter);
                    } else if(!key.compare("rownum")) {
                        tmpConf.rownum = bson_iter_int32(&iter);
                    } else if(!key.compare("begin")) {
                        tmpConf.begin = bson_iter_int32(&iter);
                    } else if(!key.compare("end")) {
                        tmpConf.end = bson_iter_int32(&iter);
                    } else
                        continue;
                } else {
                    errMsg = "Conf file data type error";
                }
            }
            if(tmpConf.flag == 1 ||
                    tmpConf.flag == 2 ||
                    tmpConf.flag == 3 ||
                    tmpConf.flag == 4 ||
                    tmpConf.flag == 5 ||
                    tmpConf.flag == 6) {
                vConf.push_back(tmpConf);
                tmpConf.init();
            }

        } else {
            errMsg = "init bson iter error!";
            return false;
            //continue;
        }
        bson_reinit (&doc);
    }

    bson_json_reader_destroy (reader);
    bson_destroy (&doc);

    if(vConf.empty()) {
        errMsg = "Conf vector are empty, initialization failed";
        return false;
    }

    if(strlen(sTnsName) &&
            strlen(sUserName) &&
            strlen(sPassWord))
        isOracle = true;
    else
        isOracle = false;

    if(mUri.empty() ||
            mDatabaseName.empty())
        isMongodb = false;
    else
        isMongodb = true;

    return true;
}

bool ToBson::writeJson(string sBsonFile, string sJsonFile, long lBegin, long lEnd) {

    if(sBsonFile.empty()) {
        errMsg = "The parameter sBsonFile is empty";
        return false;
    }

    if(sJsonFile.empty()) {
        errMsg = "The parameter sJsonFile is empty";
        return false;
    }

    FILE *jsonfp;
    char errInfo[256] = { 0 };
    bson_reader_t *reader;
    const bson_t *b;
    bson_error_t error;
    long lCount = 0;

    if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) {
        sprintf(errInfo, "Fail to open the bson file:%s", error.message);
        errMsg = errInfo;
        return false;
    }

    if((jsonfp=fopen(sJsonFile.c_str(),"w+"))==NULL) {
        errMsg = "Fail to open the bson file";
        return false;
    }

    while((b = bson_reader_read (reader, NULL))) {

        if(lEnd >= 0) {
            if(lCount >= lEnd)
                break;
        }

        if(lBegin > lCount) {
            lCount ++;
            continue;
        }

        fprintf(jsonfp, "%s\n", bson_as_json (b, NULL));
        lCount ++;
    }
    fclose(jsonfp);
    bson_reader_destroy (reader);
    return true;
}

bool ToBson::writeBson(string sJsonFile, string sBsonFile, long lBegin,long lEnd) {

    //参数 /ccw/test.json   /ccw/test.bson
    if(sJsonFile.empty() || sBsonFile.empty()) {
        errMsg = "Parameter jsonfile or bsonfile is empty";
        return false;
    }

    FILE *bsonfp;
    bson_json_reader_t *reader;
    bson_error_t error;
    bson_t doc = BSON_INITIALIZER;
    int b;
    char errInfo[256] = { 0 };
    long lCount = 0;

    if((bsonfp=fopen(sBsonFile.c_str(),"w+"))==NULL) {
        errMsg = "Fail to open the bson file";
        return false;
    }

    if (!(reader = bson_json_reader_new_from_file (sJsonFile.c_str(), &error))) {
        sprintf(errInfo, "Fail to open the json file:%s", error.message);
        errMsg = errInfo;
        return false;
    }

    while ((b = bson_json_reader_read (reader, &doc, &error))) {
        if (b < 0) {
            sprintf(errInfo, "Parsing json file failure:%s", error.message);
            errMsg = errInfo;
            return false;
        }

        if(lEnd >= 0) {
            if(lCount >= lEnd)
                break;
        }

        if(lBegin > lCount) {
            lCount ++;
            continue;
        }

        if (fwrite (bson_get_data(&doc), 1, doc.len, bsonfp) != doc.len) {
            errMsg = "Write file failure";
            return false;
        }

        lCount ++;
        bson_reinit (&doc);
    }

    bson_json_reader_destroy (reader);
    bson_destroy (&doc);
    fclose(bsonfp);
    return true;
}

bool ToBson::writeBson(bson_t * bsonDoc, FILE *fp) {

    if(!fp) {
        errMsg = "File pointers are not initialized";
        return false;
    }

    if (fwrite(bson_get_data(bsonDoc), 1, bsonDoc->len, fp) != bsonDoc->len) {
        errMsg = "Invocation of fwrite() error, write file failure";
        return false;
    }

    return true;
}

long ToBson::getBsonNum(string sBsonFile) {

    if(sBsonFile.empty()) {
        errMsg = "Parameter sBsonFile is empty";
        return -1;
    }
    char errInfo[256] = { 0 };
    bson_reader_t *reader;
    bson_error_t error;
    long lCount = 0;
    if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) {
        sprintf(errInfo, "Fail to open the bson file:%s", error.message);
        errMsg = errInfo;
        return -1;
    }

    while(bson_reader_read (reader, NULL)) {
        lCount ++;
    }

    bson_reader_destroy (reader);
    return lCount;
}

bool ToBson::readBson(string sBsonFile,long lBegin,long lEnd) {

    if(sBsonFile.empty()) {
        errMsg = "The parameter sBsonFile is empty";
        return false;
    }
    char errInfo[256] = { 0 };
    bson_reader_t *reader;
    const bson_t *b;
    bson_error_t error;
    char *str;
    long lCount = 0;
    if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) {
        sprintf(errInfo, "Fail to open the bson file:%s", error.message);
        errMsg = errInfo;
        return false;
    }

    while((b = bson_reader_read (reader, NULL))) {

        if((lBegin < 0) && (lEnd < 0)) {
            if(lCount >= 10)
                break;
        }

        if(lEnd >= 0) {
            if(lCount >= lEnd)
                break;
        }

        if(lBegin > lCount) {
            lCount ++;
            continue;
        }

        str = bson_as_json (b, NULL);
        cout<= 0; i--) {
        offset += (pOracleField[i].coLen + ALIGNMENT -1 + 1);
    }
    return offset;
}

bool ToBson::writeTableInfo() {

    if(!bIsSetSql && !strlen(sTableName)) {
        errMsg = "TableName or sql statement is not set!";
        return false;
    }

    if(!bIsSetSql) {
        sSqlRow.clear();
        sprintf(sqlText, "select * from %s" ,sTableName);
        sSqlRow = sSqlRow + "select count(*) from " + sTableName;
    } else {
        if(!getTableName(sqlText, sSqlTable, false)) {
            errMsg = "Parsing sql failure when getting the table name";
            return false;
        }
        sSqlRow = "select count(*) from " + sSqlTable;
    }

    if(!checkErr(stOciEnv.errhp, OCIStmtPrepare(stOciEnv.smthp, stOciEnv.errhp, (text *)sSqlRow.c_str(), (ub4)sSqlRow.length(), OCI_NTV_SYNTAX, OCI_DEFAULT)))
        return false;

    if(!checkErr(stOciEnv.errhp, OCIStmtExecute(stOciEnv.svchp, stOciEnv.smthp, stOciEnv.errhp, 0, 0, NULL, NULL, OCI_DEFAULT)))
        return false;

    para_status = OCIDefineByPos(stOciEnv.smthp, &dfnhp, stOciEnv.errhp, 1, (dvoid*)rowNum, sizeof(rowNum) + 1, SQLT_STR, 0, 0, 0, OCI_DEFAULT);
    if (para_status != OCI_SUCCESS) {
        checkErr(stOciEnv.errhp,para_status);
        return false;
    }

    para_status = OCIStmtFetch(stOciEnv.smthp, stOciEnv.errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
    if (para_status == OCI_NO_DATA) {
        errMsg = "Get rowNum error";
        return false;
    }

    cout<<"["<colNameLen+1];
        if(!pOracleField[i].colName) {
            errMsg = "Allocation field name memory failure";
            return false;
        }
        strncpy(pOracleField[i].colName, (char*)colName, pOracleField[i].colNameLen);
        pOracleField[i].colName[pOracleField[i].colNameLen] = '\0';
        OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid *)&pOracleField[i].colScale, 0, OCI_ATTR_SCALE, stOciEnv.errhp);
        OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid*)&pOracleField[i].colType, 0, OCI_ATTR_DATA_TYPE, stOciEnv.errhp);
        OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid*)&pOracleField[i].coLen, 0, OCI_ATTR_DATA_SIZE, stOciEnv.errhp);

        if(pOracleField[i].colType == SQLT_LNG ||
                pOracleField[i].colType == SQLT_LBI ||
                pOracleField[i].colType == SQLT_LVC ||
                pOracleField[i].colType == SQLT_LVB ||
                pOracleField[i].colType == SQLT_CLOB ||
                pOracleField[i].colType == SQLT_BLOB) {
            errMsg = "Type unsupport";
            return false;
        }

        pOracleField[i].colDefineType = getDefineType(pOracleField[i].colType);
        pOracleField[i].colOffset = getOffset(i);
        iRowLen = iRowLen + pOracleField[i].coLen + (ALIGNMENT -1) + 1;
    }
    iRowLen = iRowLen + ((ALIGNMENT - (iRowLen % ALIGNMENT)) % ALIGNMENT);
    lBufSize = iRowLen * lMaxRowNum;
    pBuf = new char[lBufSize];
    if(pBuf == NULL) {
        errMsg = "Allocation buf memory failure";
        return false;
    }
    memset(pBuf, 0, lBufSize);

    for(i=0; i< colNum; i++) {
        pBufPoint = pBuf + pOracleField[i].colOffset;
        pOracleField[i].colPoint = ADDRALIGN(pBufPoint,ALIGNMENT);

        para_status = OCIDefineByPos(stOciEnv.smthp, &pOracleField[i].ociDefine, stOciEnv.errhp, i+1, (dvoid*)pOracleField[i].colPoint, (sb4)(pOracleField[i].coLen + 1), pOracleField[i].colDefineType, 0, 0, 0, OCI_DEFAULT);
        if(!checkErr(stOciEnv.errhp, para_status))
            return false;

        para_status=OCIDefineArrayOfStruct(pOracleField[i].ociDefine, stOciEnv.errhp, (ub4)iRowLen, 0, (ub4)0, 0);
        if(!checkErr(stOciEnv.errhp, para_status))
            return false;
    }

    if(!isWriteMongo) {
        if(!openFile(sBsonFile.c_str()))
            return false;
    }

    lNowRow = 0;
    char tmpStr[32] = {0};
    ub4 buf_size = 32;
    psz = sizeof(ub4);
    long j = 0;

    while(true) {

        status = OCIStmtFetch(stOciEnv.smthp, stOciEnv.errhp, lMaxRowNum, OCI_FETCH_NEXT, OCI_DEFAULT);

        if(!checkErr(stOciEnv.errhp, OCIAttrGet((dvoid *)stOciEnv.smthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&rrows, (ub4 *)&psz, (ub4)OCI_ATTR_ROWS_FETCHED, stOciEnv.errhp))) {
            errMsg = "Rows fetched of OCIAttrGet() failed";
            return false;
        }

        if(!rrows)
            break;

        if(isWriteMongo) {
            bulk = mongoc_collection_create_bulk_operation(mCollection, true, NULL);
            if(!bulk) {
                errMsg = "Create bulk failed";
                return false;
            }
        }

        for(j = 0; j < rrows; j++) {
            bson_reinit(&bsonDoc);
            for(i = 0; i < colNum; i++) {
                pBufPoint = pOracleField[i].colPoint + j*iRowLen;
                //printf("value=%x\n",pBufPoint);
                switch(pOracleField[i].colType) {
                case SQLT_AFC:
                case SQLT_VCS:
                case SQLT_CHR:
                case SQLT_RDD:
                    BSON_APPEND_UTF8(&bsonDoc, pOracleField[i].colName, pBufPoint);
                    break;
                case SQLT_DAT:
                    para_status = OCIDateToText(stOciEnv.errhp,
                                                (OCIDate*)pBufPoint,
                                                (oratext*)"yyyymmddhh24miss",
                                                strlen("yyyymmddhh24miss"),
                                                (oratext*)"American",
                                                strlen("American"),
                                                &buf_size,
                                                (oratext*)tmpStr);
                    if(!checkErr(stOciEnv.errhp, para_status))
                        cout<<"Use Func OCIDateToText() failed"<>strYN;
        if(!strYN.compare("Y") ||
                !strYN.compare("y"))
            confFile = "./ToBson.json";
        else
            return 0;
    } else if(!confFile.compare("1") ||
              !confFile.compare("2") ||
              !confFile.compare("3") ||
              !confFile.compare("4") ||
              !confFile.compare("5") ||
              !confFile.compare("6")) {
        conf.flag = atoi(confFile.c_str());
        if(!rowNum.empty())
            conf.rownum = atol(rowNum.c_str());
        if(!end.empty())
            conf.end = atoll(end.c_str());
        if(!start.empty())
            conf.begin = atoll(start.c_str());
        conf.bfile = bFile;
        conf.jfile = jFile;
        conf.table = table;
        conf.sql = sql;
        conf.tns = tns;
        conf.user = user;
        conf.passwd = passwd;
        conf.mongouri = mUri;
        conf.mongocollection = mCollection;
        conf.mongodb = mDb;

        if(!toBson.run(conf)){
            cout<



 ToBson.json:

{"note":"遍历完所有flag=1 or 6的配置时,tns、user、passwd三个字段必须存在,字段实际生效按第一次出现配置"}
{"note":"遍历完所有flag=6的配置时,uri、mdb二个字段必须存在,字段实际生效按第一次出现配置"}
{"note":"flag: 1ORACLETOBSON  2JSONTOBSON  3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB"}
{"flag":1,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST9","bfile":"./TEST9.bson","sql":"","note":"bfile,[sql/table] can empty"}
{"flag":1,"table":"TEST10","bfile":"./TEST10.bson"}
{"flag":2,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line json to bson file,default all"}
{"flag":3,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line bson to json file,default all"}
{"flag":4,"bfile":"./TEST9.bson","begin":0,"end":4,"note":"read 0-4 line bson file info,default first 10 line"}
{"flag":5,"bfile":"./TEST9.bson","note":"get bson file line nums"}
{"flag":6,"table":"TEST9","uri":"mongodb://192.168.1.123:20000/","mdb":"mongodb","collection":"TEST9","note":"read oracle to mongodb"}

ToBson.json_bak:

{"flag":6,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST","uri":"mongodb://192.168.1.127:27017/","mdb":"mongodb","rownum":1200000}




你可能感兴趣的:(C++,oc,mongdo,bson,mongdb,c,driver,oracle批量提取数据)