项目需要,将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 <string>
#include <oci.h>
#include <bson.h>
#include <bcon.h>
#include <mongoc.h>
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<OCI_CONF>::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<OCI_CONF> vConf;
vector<OCI_CONF>::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 <time.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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 <colNum; i++) {
if(pOracleField[i].colName) {
delete [] pOracleField[i].colName;
pOracleField[i].colName = NULL;
}
}
delete[] pOracleField;
pOracleField = NULL;
}
if(pBuf) {
delete[] pBuf;
pBuf = NULL;
}
closeFile();
bson_destroy(&bsonDoc);
}
bool ToBson::initMongodb(const string database, const string table) {
if(database.empty() && mDatabaseName.empty()) {
errMsg = "Mongodb database is empty";
return false;
}
if(!database.empty()) {
if(!isInitDb) {
useDB(database);
} else if(database.compare(mDatabaseName)) {
if(!useDB(database))
return false;
}
} else
if(!useDB(mDatabaseName))
return false;
if(!table.empty()) {
useTable(table);
} else if(!nowTable.empty()) {
useTable(nowTable);
} else {
errMsg = "Mongodb table is empty";
return false;
}
return true;
}
bool ToBson::initParameter(const string tableName,
const string fileName,
const long maxRowNum) {
nowTable = "";
if(!tableName.empty()) {
strcpy(sTableName, tableName.c_str());
nowTable = sTableName;
} else if(bIsSetSql) {
if(!getTableName(sqlText, nowTable)) {
errMsg = "Parsing sql failure when getting the table name";
return false;
}
} else {
errMsg = "Parameter tableName and sql is empty";
return false;
}
if(!fileName.empty())
sBsonFile = fileName;
else
sBsonFile = "./" + nowTable + ".bson";
lMaxRowNum = maxRowNum;
return true;
}
void ToBson::printConf(vector<OCI_CONF>::iterator vIter) {
cout<<endl;
cout<<"Config Info:"<<endl;
cout<<"flag="<<vIter->flag<<endl;
cout<<"table="<<vIter->table<<endl;
cout<<"jfile="<<vIter->jfile<<endl;
cout<<"bfile="<<vIter->bfile<<endl;
cout<<"rownum="<<vIter->rownum<<endl;
cout<<"sql="<<vIter->sql<<endl;
cout<<"begin="<<vIter->begin<<endl;
cout<<"end="<<vIter->end<<endl;
cout<<endl;
}
string ToBson::trimNewline(char * str) {
string _str = str;
if(!_str.empty() )
{
_str.erase(_str.find_last_not_of('\r') + 1);
_str.erase(_str.find_last_not_of('\n') + 1);
}
return _str;
}
bool ToBson::run(OCI_CONF & conf) {
vConf.clear();
if(conf.flag == 1 || conf.flag == 6) {
if(conf.tns.empty() ||
conf.user.empty() ||
conf.passwd.empty()) {
errMsg = "Parameter of tns or user or passed is empty";
return false;
}
strcpy(sTnsName, conf.tns.c_str());
strcpy(sUserName, conf.user.c_str());
strcpy(sPassWord, conf.passwd.c_str());
isOracle = true;
if(conf.flag == 6) {
if(conf.mongodb.empty() ||
conf.mongouri.empty()) {
errMsg = "Parameter of muri or mdb is empty";
return false;
}
mDatabaseName = conf.mongodb;
mTableName = conf.mongocollection;
mUri = conf.mongouri;
isMongodb = true;
} else
isMongodb = false;
} else
isOracle = false;
vConf.push_back(conf);
return run();
}
bool ToBson::run(string & sJsonFile) {
if(!ParseConfig(sJsonFile))
return false;
return run();
}
bool ToBson::run() {
long count = 0;
if(isOracle) {
// check environment
//export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
//Chinese: export NLS_LANG=AMERICAN_AMERICA.UTF8
if(getenv("NLS_LANG") == NULL)
{
errMsg = "Set env NLS_LANG first";
return false;
}
if(!connectOracle((text *)sTnsName, (text *)sUserName, (text *)sPassWord))
return false;
if(isMongodb)
if(!connectMongodb(mUri))
return false;
}
cout<<endl;
for (vIter=vConf.begin(); vIter!=vConf.end(); vIter++) {
if(vIter->flag == 1 ||
vIter->flag == 6) {
if(!isOracle) {
errMsg = "Can't connect oracle";
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
if((vIter->flag == 6) && !isMongodb) {
errMsg = "Can't connect mongodb";
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
if(!vIter->sql.empty())
setSql(vIter->sql);
if(!vIter->rownum)
vIter->rownum = _MAX_ROW_NUMS_;
if(!initParameter(vIter->table,vIter->bfile,vIter->rownum)) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
if(vIter->flag == 6) {
if(!initMongodb(vIter->mongodb, vIter->mongocollection)) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
isWriteMongo = true;
} else
isWriteMongo = false;
cout<<"Begin time:"<<getTime()<<endl;
if(!writeTableInfo()) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
cout<<"End time:"<<getTime()<<endl<<endl;
} else if(vIter->flag == 2) {
if(!writeBson(vIter->jfile, vIter->bfile, vIter->begin, vIter->end)) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
} else if(vIter->flag == 3) {
if(!writeJson(vIter->bfile, vIter->jfile, vIter->begin, vIter->end)) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
} else if(vIter->flag == 4) {
if(!readBson(vIter->bfile,vIter->begin,vIter->end)) {
cout<<getErrInfo()<<endl;
printConf(vIter);
continue;
}
} else if(vIter->flag == 5) {
cout<<"file "<<vIter->bfile<<" record nums="<<getBsonNum(vIter->bfile)<<endl<<endl;
}
count++;
}
cout<<endl<<"Total finish "<<count<<" config tasks"<<endl<<endl;
if(isOracle) {
if(!closeOracle())
return false;
if(isMongodb)
if(!closeMongodb())
return false;
}
return true;
}
bool ToBson::closeMongodb() {
if(mCollection)
mongoc_collection_destroy (mCollection);
if(mDatabase)
mongoc_database_destroy (mDatabase);
if(mClient)
mongoc_client_destroy (mClient);
mongoc_cleanup ();
return true;
}
string ToBson::getErrInfo() {
return errMsg;
}
bool ToBson::getTableName(char * sql, string &strOut, bool onlyTable) {
if(!sql || !strlen(sql)) {
errMsg = "sql is empty";
return false;
}
string strSql= sql;
string find_begin = "from";
size_t begin_postion;
begin_postion = strSql.find(find_begin);
if(onlyTable) {
string find_end = "where";
size_t end_postion = strSql.find(find_end);
if (end_postion != string::npos)
strOut = strSql.substr(begin_postion+5, end_postion-begin_postion-6);
else
strOut = strSql.substr(begin_postion+5);
} else {
if (begin_postion != string::npos)
strOut = strSql.substr(begin_postion+5);
else
return false;
}
return true;
}
string ToBson::getTime() {
char year[5] = {0};
char month[3] = {0};
char day[3] = {0};
char hour[3] = {0};
char min[3] = {0};
char second[3] = {0};
char nowTime[20] = {0};
//string cNowTime = "";
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
sprintf(year,"%d",1900 + p->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<<str<<endl;
bson_free (str);
lCount ++;
}
bson_reader_destroy (reader);
return true;
}
bool ToBson::setSql(string sSql) {
bIsSetSql = false;
if(sSql.empty()) {
errMsg = "sql is empty in setSql()";
return false;
}
sprintf(sqlText, "%s" , sSql.c_str());
bIsSetSql = true;
return true;
}
ub2 ToBson::getDefineType(ub2 iType) {
ub2 type;
switch(iType) {
case SQLT_AFC:
case SQLT_VCS:
case SQLT_CHR:
case SQLT_UIN:
case SQLT_INT:
case SQLT_FLT:
case SQLT_NUM:
case SQLT_RDD:
type = SQLT_STR;
break;
case SQLT_DAT:
type = SQLT_ODT;
break;
// case SQLT_FLT:
// case SQLT_NUM:
// type = SQLT_VNU;
// break;
default:
type = iType;
break;
}
return type;
}
int ToBson::getOffset(int col) {
if(col <= 0 )
return 0;
int offset = 0;
int i = 0;
for(i = col -1; i >= 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<<"["<<nowTable<<"]Total row nums="<<rowNum<<endl;
lNowRow = atol(rowNum);
if(!lNowRow)
return true;
if(lNowRow < lMaxRowNum)
lMaxRowNum = lNowRow;
if(!checkErr(stOciEnv.errhp, OCIStmtPrepare(stOciEnv.smthp, stOciEnv.errhp, (text *)sqlText, (ub4)strlen((const char *) sqlText), 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;
OCIAttrGet((dvoid*)stOciEnv.smthp, OCI_HTYPE_STMT, (dvoid*)&colNum, (ub4 *)0, OCI_ATTR_PARAM_COUNT, stOciEnv.errhp);
pOracleField = new OracleField[colNum];
if(!pOracleField) {
errMsg = "Allocation field list memory failure";
return false;
}
int i = 0;
iRowLen = 0;
for (i=0; i< colNum; i++) {
para_status = OCIParamGet(stOciEnv.smthp, OCI_HTYPE_STMT, stOciEnv.errhp, (void **) &stOciEnv.paramhp, (ub4)i+1);
OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid**)&colName, &pOracleField[i].colNameLen, OCI_ATTR_NAME, stOciEnv.errhp);
pOracleField[i].colName = new char[pOracleField->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"<<endl;
if(strcmp(tmpStr, "00000000000000"))
BSON_APPEND_UTF8(&bsonDoc, pOracleField[i].colName, tmpStr);
tmpStr[0] = '\0';
break;
case SQLT_FLT:
case SQLT_NUM:
if(strlen(pBufPoint)) {
if(pOracleField[i].colScale != 0)
BSON_APPEND_DOUBLE(&bsonDoc, pOracleField[i].colName, atof(pBufPoint));
else
BSON_APPEND_INT64(&bsonDoc, pOracleField[i].colName, atoll(pBufPoint));
}
break;
case SQLT_UIN:
case SQLT_INT:
if(strlen(pBufPoint))
BSON_APPEND_INT64(&bsonDoc, pOracleField[i].colName, atoll(pBufPoint));
break;
case SQLT_BLOB:
case SQLT_BIN:
cout<<"type nosupper"<<endl;
errMsg = "type nosupper";
break;
default:
cout<<"other type nosupper"<<endl;
errMsg = "other type nosupper";
break;
}
pBufPoint[0] = '\0';
}
if(isWriteMongo) {
mongoc_bulk_operation_insert(bulk, &bsonDoc);
} else {
if(!writeBson(&bsonDoc,fp))
return false;
}
}
if(isWriteMongo) {
if (!mongoc_bulk_operation_execute(bulk, NULL, &bson_error)) {
errMsg = bson_error.message;
mongoc_bulk_operation_destroy(bulk);
return false;
}
mongoc_bulk_operation_destroy(bulk);
}
lNowRow = lNowRow + rrows;
// When rrows is less than lMaxRowNum, also return OCI_NO_DATA
if(status == OCI_NO_DATA)
break;
}
closeFile();
if(pOracleField) {
for(int i = 0; i <colNum; i++) {
if(pOracleField[i].colName) {
delete [] pOracleField[i].colName;
pOracleField[i].colName = NULL;
}
}
delete[] pOracleField;
pOracleField = NULL;
}
if(pBuf) {
delete[] pBuf;
pBuf = NULL;
}
cout <<"["<<nowTable<<"]Rows has been processed="<<lNowRow<<endl;
return true;
}
bool ToBson::checkErr(OCIError *pErr, sword lSattus) {
sb4 iErrCode = 0;
switch (lSattus) {
case OCI_SUCCESS:
strcpy(sErr, "OCI_SUCCESS");
break;
case OCI_SUCCESS_WITH_INFO:
strcpy(sErr, "OCI_SUCCESS_WITH_INFO");
break;
case OCI_NO_DATA:
strcpy(sErr, "OCI_NO_DATA");
break;
case OCI_ERROR:
OCIErrorGet((dvoid *) pErr, (ub4) 1, (text *) NULL, &iErrCode, (text *) sErr, (ub4) sizeof(sErr), (ub4) OCI_HTYPE_ERROR);
break;
case OCI_NEED_DATA:
strcpy(sErr, "OCI_NEED_DATA");
break;
case OCI_INVALID_HANDLE:
strcpy(sErr, "OCI_INVALID_HANDLE");
break;
case OCI_STILL_EXECUTING:
strcpy(sErr, "OCI_STILL_EXECUTING");
break;
case OCI_CONTINUE:
strcpy(sErr, "OCI_CONTINUE");
break;
default:
break;
}
if(OCI_SUCCESS != lSattus && OCI_SUCCESS_WITH_INFO != lSattus) {
errMsg = sErr;
return false;
}
return true;
}
bool ToBson::closeOracle() {
if(stOciEnv.smthp) {
if(!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.smthp, OCI_HTYPE_STMT)))
return false;
stOciEnv.smthp = NULL;
}
if(stOciEnv.svchp && stOciEnv.errhp && stOciEnv.usrhp) {
if(!checkErr(stOciEnv.errhp,OCISessionEnd(stOciEnv.svchp, stOciEnv.errhp, stOciEnv.usrhp, OCI_DEFAULT)))
return false;
}
if (stOciEnv.usrhp) {
if(!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.usrhp, OCI_HTYPE_SESSION)))
return false;
stOciEnv.usrhp = NULL;
}
if (stOciEnv.srvhp && stOciEnv.errhp) {
if (!checkErr(stOciEnv.errhp, OCIServerDetach(stOciEnv.srvhp, stOciEnv.errhp, OCI_DEFAULT)))
return false;
}
if (stOciEnv.srvhp) {
if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.srvhp, OCI_HTYPE_SERVER)))
return false;
stOciEnv.srvhp = NULL;
}
if(stOciEnv.svchp) {
if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.svchp, OCI_HTYPE_SVCCTX)))
return false;
stOciEnv.svchp = NULL;
}
if (stOciEnv.errhp) {
if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.errhp, OCI_HTYPE_ERROR)))
return false;
stOciEnv.errhp = NULL;
}
if (stOciEnv.envhp) {
if (!checkErr(stOciEnv.errhp,OCIHandleFree(stOciEnv.envhp, OCI_HTYPE_ENV)))
return false;
stOciEnv.envhp = NULL;
}
return true;
}
}
using namespace std;
using namespace BM35;
int main(int argc, char *argv[])
{
string confFile;
string strYN;
string rowNum;
string bFile;
string jFile;
string table;
string end;
string start;
string sql;
string tns;
string user;
string passwd;
string mDb;
string mUri;
string mCollection;
OCI_CONF conf;
conf.init();
for (int c; (c = getopt(argc, argv, "f:hHr:b:j:t:e:s:q:p:u:n:d:c:i:")) != EOF;) {
switch (c) {
case 'f':
confFile = optarg;
break;
case 'r':
rowNum = optarg;
break;
case 'i':
mUri = optarg;
break;
case 'd':
mDb = optarg;
break;
case 'c':
mCollection = optarg;
break;
case 'p':
passwd = optarg;
break;
case 'u':
user = optarg;
break;
case 'n':
tns = optarg;
break;
case 'b':
bFile = optarg;
break;
case 'j':
jFile = optarg;
break;
case 'q':
sql = optarg;
break;
case 't':
table = optarg;
break;
case 'e':
end = optarg;
break;
case 's':
start = optarg;
break;
case '?':
case 'h':
case 'H':
cout<<"Usage: ToBson \n";
cout<<" -f confFile [default ./ToBson.json]\n";
cout<<" or 1,2,3,4,5 6[1ORACLETOBSON 2JSONTOBSON 3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB]\n";
cout<<" -r rownum \n";
cout<<" -p passwd \n";
cout<<" -u user \n";
cout<<" -n tns \n";
cout<<" -b bfile \n";
cout<<" -j jfile \n";
cout<<" -q sql \n";
cout<<" -s start \n";
cout<<" -e end \n";
cout<<" -t table \n";
cout<<" -i uri \n";
cout<<" -d mongoDb \n";
cout<<" -c collection \n";
cout<<" -h printf help\n";
cout<<" example:ToBson -f ./ToBson.json \n";
cout<<" ToBson -f 4 -b ./test9.bson\n";
cout<<" ToBson -f 1 -u comm -p comm -n SiC -t test9\n";
cout<<" ToBson -f 6 -u comm -p comm -n SiC -t test9 -d mongodb -i mongodb://192.168.1.123:20000/\n";
cout<<" more detail reference file ToBson.json \n";
exit(-1);
break;
default:
break;
}
}
ToBson toBson;
if(confFile.empty()) {
cout<<"Using ./ToBson.json file to run(y/n):"<<endl;
cin>>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.getErrInfo()<<endl;
return -1;
}
return 0;
}
if(!toBson.run(confFile)){
cout<<toBson.getErrInfo()<<endl;
return -1;
}
return 0;
}
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}