项目需要,将oracle中上亿的数据表数据提取到mongdb,通过api单条插入,效率极低。通过第三方工具data-integration导入,效率还不够高。最终只能根据需求编写程序。
最初思路是解析oracle导出的dump二进制文件,在转换为bson二进制导入mongodb,但是根据测试,效率依旧较低。发现oracle与mongodb都采用批处理,效率算数有进步,最终决定采用编写程序实现。以下是在centos测试机器1万批量测得,鉴于代码未继续优化以及主机性能不强,后续效率还待测试:
在oracle导入mongodb时,通过oci批量提取数据,调用mongc driver批量写入mongddb,大幅提升效率,120万批量处理速度约21845条/s。代码还可继续优化,如使用oracle分页技术分多进程,理论提高页数倍,如有更好方式,也请分享,谢谢。以下为100万批量处理时速度记录:
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<table<jfile<bfile<rownum<sql<begin<end<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}