ORACLE_SQL导出CSV

/*
主要功能说明:
1.通过配置文件export_sql.conf中的内容,将ORACLE数据库的数据导出为CSV文件的格式。
2.通过配置文件export_conf.conf,可以设定程序的单进程和多进程模式。
3.通过配置文件export_conf.conf,可以指定每次导出的行数。
4.通过配置文件export_conf.conf,可以指定导出数据的文件夹位置。
5.通过配置文件export_conf.conf,可以指定日期数据的日期的格式。
6.详情见下文的Readme.txt文件。
*/
/*export_sql.h*/
#ifndef __EXPORT_H__
#define __EXPORT_H__


#define __MY_WIN32_FLAG__
#include "myinclude.h"

#include "myoci.h"
#include "mymethod.h"
#include "mylib.h"
//#include "myproc.h"

#ifdef __MY_WIN32_FLAG__
#define PATH_SYSCONF ".\\conf\\export_conf.conf"
#define PATH_DATADIR ".\\datafile"
#define PATH_FILENAME "%s\\%s.csv"
#define PATH_LOGDIR ".\\log"
#define PATH_LOG ".\\log\\operlog.log"
#define F_OK 0
#define W_OK 2
#define MKDIR(x) mkdir((x))
#define SYSTEM(x) system((x))
#else
#define PATH_SYSCONF "./conf/export_conf.conf"
#define PATH_DATADIR "./datafile"
#define PATH_FILENAME "%s/%s.csv"
#define PATH_LOGDIR "./log"
#define PATH_LOG "./log/operlog.log"
#define MKDIR(x) mkdir((x),0666)
#endif

#define DEF_LINEBUF 1000
#define DEF_PROCESSMODE 0
#define DEF_PROCESSNUM 4
#define DEF_FILENAMELEN 1000
#define DEF_REPLACE_NEWLINE 0
#define DEF_DBCONNMODE "NORMAL"

typedef struct key_value{
char *key;
char *value;
}key_value;

typedef struct conf_info{
int filename_len;
char *chrset;
char *usr;
char *pwd;
char *ora;
char *datafile_path;
char *date_format;
unsigned fetch_buf;
unsigned replace_newline;
char *database_connmode;
unsigned process_mode;
unsigned process_num;
}conf_info;

#define ERR_NODEF_DBCONN -1
#define ERRMSG_NODEF_DBCONN "未知的数据库连接模式\n"
#define ERR_FILEPATH_BUF -2
#define ERRMSG_FILEPATH_BUF "文件路径缓冲不足\n"
#define ERR_CREATEOPEN_DATAFILE -3
#define ERRMSG_CREATEOPEN_DATAFILE "数据文件打开(创建)失败\n"
#define ERRMSG_CREATE_DATAFILE_1 "数据文件%s打开(创建)失败\n"
#define ERR_CMD_ARG -4
#define ERRMSG_CMD_ARG "命令行模式下参数错误\n"
#define ERR_NOTFOUND_SYSCONF -5
#define ERRMSG_NOTFOUND_SYSCONF "配置文件export_conf.conf没有找到\n"
#define ERR_SYSCONF_FORMAT -6
#define ERRMSG_SYSCONF_FORMAT "配置文件export_conf.conf格式有误\n"
#define ERR_NOTFOUND_SQLCONF -7
#define ERRMSG_NOTFOUND_SQLCONF "配置文件export_sql.conf没有找到\n"
#define ERR_SQLCONF_FORMAT -8
#define ERRMSG_SQLCONF_FORMAT "配置文件export_sql.conf格式有误\n"
#define ERR_OTHER -9
#define ERRMSG_OTHER "未知错误,可能是系统中断引起\n"
#define ERR_OS_VERSION -10
#define ERRMSG_OS_VERSION "

操作系统版本不确定,请重新编译程序\n"
#define ERR_CREATE_LOGDIR -11
#define ERRMSG_CREATE_LOGDIR "创建日志文件夹失败\n"
#define ERR_LOGDIR_WRPERMISSION -12
#define ERRMSG_LOGDIR_WRPERMISSION "日志文件夹没有写权限\n"
#define ERR_CREATEOPEN_LOGFILE -13
#define ERRMSG_CREATEOPEN_LOGFILE "创建或打开日志文件失败\n"
#define ERR_MULTIPROCESS_PARMATER -14
#define ERRMSG_MULTIPROCESS_PARMATER "多进程模式下,进程数量不能为0\n"

#define CMD_ARGFORMAT "usage %s [data_file] [sql_statement]\n"

#define ERR_CSV_CONVERT "CSV文件字段格式转换有误\n"
#define ERR_EXP_LINEBUF "缓冲行数不能为0\n"
#define ERR_EXP_PROCESSMODE "未知的线程模式,使用默认的单线程模式运行程序\n"
#define ERR_EXP_DBCONNMODE "未知的连接模式,已使用默认的普通连接模式"
#define ERR_EXP_DATADIR_WRPERMISSION "给出的文件夹没有写的权限\n"
#define ERR_EXP_CREATE_DATADIR "创建文件夹失败\n"
#define ERR_EXP_NODEF_KEY "一个未知的配置项目\n"
#define ERR_EXP_NODEF_KEYVALUE "配置项目格式错误\n"
#define ERR_EXP_CONN "\n连接失败:%s\n"
#define ERR_EXP_GETHANDLE "\n不能初始化句柄\n"
#define ERR_EXP_SET_DATEFORMAT "\n日期字符串可能有误,请检查\n"
#define ERR_EXP_DATEFORMAT "\n日期字符串错误,已使用默认客户端日期字符串\n"

#define LOG_FORMAT_STRING_1(w,x,y,z) fprintf(stderr,"\n**Exporting data(database-source:%s@%s,file_name:%s)**\n\
*Start Export:%s\n",(w),(x),(y),(z))
#define LOG_FORMAT_STRING_2(w,x,y,z) fprintf(stderr,"\n**Exporting data(database-source:%s@%s,file_name:%s)**\n",(w),(x),(y));\
fprintf(stderr,"*Start Export:%s\n",(z))
#define LOG_FORMAT_STRING_3(a,b,c,d,e) fprintf(stderr,"\n**Exporting data(database-source:%s@%s,file_name:%s)**\n\
*End Export:%s\n*Export Total:%d\n",\
(a),(b),(c),(d),(e));
#define LOG_FORMAT_STRING_4(a,b) fprintf(stderr,"\n*End Export:%s\n",a);\
fprintf(stderr,"*Export Total:%d\n",b);

extern void printpid(void *f_data);
extern void printcolname(int f_fdes,OCIOraFieldSet *f_fieldset);
extern void printdata(int f_fdes,OCIOraFieldSet *f_fieldset);
extern int read_sql(FILE *in_stream,s_link *keyvalue_link);
extern int read_conf(FILE *in_stream);
extern int db_oper(conf_info *f_info,const char *f_sql,const char *f_fname);
extern int create_log(void);
extern void childprocess_recode(int f_recode);
extern int multi_process(char **argv);
extern int single_process(void);
extern int create_datadir(void);
extern void createprocess_result(int f_pid);


#define MSG_CUREXP "文件名:%s\n导出的SQL语句:%s\n"
#define MSG_CREATEPROCESS "创建子进程失败\n"
#define MSG_MAINTAINPROCESS "不能维护子进程队列\n"
#define MSG_CURPROCESS "当前子进程:"
#define MSG_CHILDRECODE "发生错误:等待的子进

程ID无效,或子进程没有返回值\n"

#define MSG_CREATEPROC1 "发生错误:参数的长度超过了1024字节\n"
#define MSG_CREATEPROC2 "发生错误:参数无效\n"
#define MSG_CREATEPROC3 "发生错误:在指定路径中未找到程序\n"
#define MSG_CREATEPROC4 "发生错误:在指定文件不可执行\n"
#define MSG_CREATEPROC5 "发生错误:没有足够的内存运行子进程\n"
#define MSG_CREATEPROC6 "发生错误:其他未知错误\n"
#endif


/*sql_export.c*/
#include "export_sql.h"

extern conf_info v_confinfo;
/*打印当前运行的进程*/
void printpid(void *f_data){
fprintf(stderr,"| %d",*(int*)f_data);
}
/*写入列名信息*/
void printcolname(int f_fdes,OCIOraFieldSet *f_fieldset){
unsigned i,v_cols;
char *v_colname;

if(!f_fieldset||(v_cols=OCIGetColumns4FieldSet(f_fieldset))==0){
return;
}

for(i=0;iif((v_colname=OCIGetFieldName4FieldSet(f_fieldset,i))!=NULL){
buf_write(f_fdes,"\"",0);
buf_write(f_fdes,v_colname,0);
buf_write(f_fdes,"\"",0);
if(i==v_cols-1)
buf_write(f_fdes,"\n",0);
else
buf_write(f_fdes,",",0);
}
}
}
/*写入列值信息*/
void printdata(int f_fdes,OCIOraFieldSet *f_fieldset){

unsigned i,j,v_cols,v_rows;

char *v_data;

if(!f_fieldset||
(v_cols=OCIGetColumns4FieldSet(f_fieldset))==0||
(v_rows=OCIGetFetchRows4FieldSet(f_fieldset))==0){
return;
}
for(i=0;ifor(j=0;jv_data=OCIGetFieldVal4Field(OCIGetFieldbyIndex4FieldSet(f_fieldset,j),i);
if(STRLEN(v_data)){
char *v_data1,*v_data2;
v_data1=v_data2=NULL;
if(v_confinfo.replace_newline){
if(strchr(v_data,'\n')){
if((v_data1=replacestr(v_data,"\n",""))==NULL){
fprintf(stderr,ERR_CSV_CONVERT);
return;
}
}
}

if(strchr(v_data,'\"')){
v_data=v_data1?v_data1:v_data;
if((v_data2=replacestr(v_data,"\"","\"\""))==NULL){
fprintf(stderr,ERR_CSV_CONVERT);
return;
}
}

if(v_data2)
v_data=v_data2;
else if(v_data1)
v_data=v_data1;
else
v_data=v_data;

buf_write(f_fdes,"\"",0);
buf_write(f_fdes,v_data,0);
buf_write(f_fdes,"\"",0);

FREE(v_data1);
FREE(v_data2);
}
else
buf_write(f_fdes,"\"\"",0);
if(j==v_cols-1)
buf_write(f_fdes,"\n",0);
else
buf_write(f_fdes,",",0);
}
}
//buf_write(f_fdes,"",1);
}
/*将文件中的SQL语句读入链表*/
int read_sql(FILE *in_stream,s_link *keyvalue_link){
int valid_flage=1;
char *buf_line,*buf_str=NULL;
char *key_pos;
key_value *v_keyvalue;
if(!in_stream||!keyvalue_link)
return FALSE;
while(buf_line=read_line(in_stream,NULL,NULL)){
if(buf_line[0]=='#'){
free(buf_line);
continue;
}
if(buf_line[strlen(buf_line)-1]==';'){
buf_line[strlen(buf_line)-1]='\0';
if(!buf_str){
buf_str=(char*)malloc(sizeof(char)*(strlen(buf_line)+1)

);
strcpy(buf_str,buf_line);
}
else{
buf_str=(char*)realloc((void*)buf_str,sizeof(char)*(strlen(buf_str)+strlen(buf_line)+1));
strcat(buf_str,buf_line);
}
if(key_pos=strchr(buf_str,'=')){
*key_pos='\0';
v_keyvalue=(key_value*)malloc(sizeof(key_value));
v_keyvalue->key=newstr(buf_str);
v_keyvalue->value=newstr(key_pos+1);
s_addnode(keyvalue_link,(void*)v_keyvalue);
FREE(buf_line);
FREE(buf_str);
continue;
}
FREE(buf_line);
FREE(buf_str);
return FALSE;
}
else{
if(!buf_str){
buf_str=(char*)malloc(sizeof(char)*(strlen(buf_line)+1));
strcpy(buf_str,buf_line);
}
else{
buf_str=(char*)realloc((void*)buf_str,sizeof(char)*(strlen(buf_str)+strlen(buf_line)+1));
strcat(buf_str,buf_line);
}
free(buf_line);
}
}
return TRUE;
}
/*将文件中的配置信息读入结构*/
int read_conf(FILE *in_stream){
int valid_flage=1;
char *buf_line,*buf_str=NULL;
char *key_pos;
if(!in_stream)
return FALSE;
while(buf_line=read_line(in_stream,NULL,NULL)){
if(buf_line[0]=='#'){
free(buf_line);
continue;
}
if(buf_line[strlen(buf_line)-1]==';'){
buf_line[strlen(buf_line)-1]='\0';
if(!buf_str){
buf_str=(char*)malloc(sizeof(char)*(strlen(buf_line)+1));
strcpy(buf_str,buf_line);
}
else{
buf_str=(char*)realloc((void*)buf_str,sizeof(char)*(strlen(buf_str)+strlen(buf_line)+1));
strcat(buf_str,buf_line);
}
if(key_pos=strchr(buf_str,'=')){
*key_pos='\0';
if(strcmp(upperstr(buf_str),"FILENAME_LEN")==0){
sscanf(key_pos+1,"%du",&v_confinfo.filename_len);
if(v_confinfo.filename_len<1000)
v_confinfo.filename_len=1000;
}
else if(strcmp(upperstr(buf_str),"FETCH_BUFLINE")==0){
if(sscanf(key_pos+1,"%du",&v_confinfo.fetch_buf)==0){
fprintf(stderr,ERR_EXP_LINEBUF);
return FALSE;
}
}
else if(strcmp(upperstr(buf_str),"PROCESS_NUM")==0){
sscanf(key_pos+1,"%du",&v_confinfo.process_num);
}
else if(strcmp(buf_str,"PROCESS_MODE")==0){
if(strcmp(upperstr(key_pos+1),"MULTI")==0)
v_confinfo.process_mode=1;
else if(strcmp(upperstr(key_pos+1),"SINGLE")==0)
v_confinfo.process_mode=0;
else
fprintf(stderr,ERR_EXP_PROCESSMODE);
}
else if(strcmp(buf_str,"CHARSET")==0){
v_confinfo.chrset=upperstr(newstr(key_pos+1));
}
else if(strcmp(buf_str,"USER")==0){
v_https://www.360docs.net/doc/e08409986.html,r=newstr(key_pos+1);
if((v_confinfo.ora=strchr(v_https://www.360docs.net/doc/e08409986.html,r,'@'))!=NULL){
char *v_pos;
v_pos=v_confinfo.ora;
v_pos++;
v_confinfo.ora=newstr(v_pos);
*(v_pos-1)='\0';
}
}
else if(strcmp(buf_str,"PASSWORD")==0){
v_confinfo.pwd=newstr(key_pos+1);
}
else if(strcmp(buf_str,"DATE_FORMAT")==0){
v_confinfo.date_format=newstr(key_pos+1);
}
else if(strcmp(buf_str,"REPLACE_NEWLINE")==0){
if(strcmp(u

pperstr(key_pos+1),"TRUE")==0)
v_confinfo.replace_newline=1;
}
/*else if(strcmp(buf_str,"DATABASE_CONNMODE")==0){
if(strcmp(upperstr(key_pos+1),"NORMAL")==0)
v_confinfo.database_connmode=newstr(key_pos+1);
else if(strcmp(upperstr(key_pos+1),"SYSDBA")==0)
v_confinfo.database_connmode=newstr(key_pos+1);
else if(strcmp(upperstr(key_pos+1),"SYSOPER")==0)
v_confinfo.database_connmode=newstr(key_pos+1);
else
fprintf(stderr,ERR_EXP_DBCONNMODE);
}*/
else if(strcmp(buf_str,"DATAFILE_PATH")==0){
v_confinfo.datafile_path=newstr(key_pos+1);
}
else{
fprintf(stderr,ERR_EXP_NODEF_KEY);
}
FREE(buf_line);
FREE(buf_str);
continue;
}
else{
fprintf(stderr,ERR_EXP_NODEF_KEYVALUE);
FREE(buf_line);
FREE(buf_str);
return FALSE;
}
}
else{
if(!buf_str){
buf_str=(char*)malloc(sizeof(char)*(strlen(buf_line)+1));
strcpy(buf_str,buf_line);
}
else{
buf_str=(char*)realloc((void*)buf_str,sizeof(char)*(strlen(buf_str)+strlen(buf_line)+1));
strcat(buf_str,buf_line);
}
FREE(buf_line);
}
}
return TRUE;
}
/*操作数据库导出数据*/
int db_oper(conf_info *f_info,const char *f_sql,const char *f_fname){
//ora_handle v_orah;
OCIHandle v_ocih;
OCICda v_ocic;
OCIOraFieldSet v_fieldset;
char v_dfsql[1024]={'\0'};
char *file_name;
char time_buf[21]={'\0'};
int fd,i=0;

//ora_init(&v_orah);
//if(strcmp(f_info->database_connmode,"NORMAL")==0){
// if(ora_connect_normal(&v_orah,f_info->usr,f_info->pwd,f_info->ora,NULL)!=0){
// fprintf(stderr,ERR_EXP_CONN,v_orah.sql_error._error);
// return FALSE;
// }
//}
//else if(strcmp(f_info->database_connmode,"SYSDBA")==0){
// if(ora_connect_sysdba(&v_orah,f_info->usr,f_info->pwd,f_info->ora,NULL)!=0){
// fprintf(stderr,ERR_EXP_CONN,v_orah.sql_error._error);
// return FALSE;
// }
//}
//else if(strcmp(f_info->database_connmode,"SYSOPER")==0){
// if(ora_connect_sysoper(&v_orah,f_info->usr,f_info->pwd,f_info->ora,NULL)!=0){
// fprintf(stderr,ERR_EXP_CONN,v_orah.sql_error._error);
// return FALSE;
// }
//}
//else{
// fprintf(stderr,ERRMSG_NODEF_DBCONN);
// return ERR_NODEF_DBCONN;
//}
OCIInitHandle(&v_ocih);

if(!OCIConnORA(&v_ocih,f_info->usr,f_info->pwd,f_info->ora)){
OCIPrintOraErr(&v_ocih._error);
fprintf(stderr,ERR_EXP_CONN);
return FALSE;
}

//if(OCIGetHandle4PROC(&v_ocih)==NULL){
// OCIPrintOraErr(&v_ocih._error);
// fprintf(stderr,ERR_EXP_GETHANDLE);
// return FALSE;
//}
///*设置信息*/
//v_ocih._usr=newstr(f_info->usr);
//v_ocih._pwd=newstr(f_info->pwd);
//v_ocih._ora=newstr(f_info->ora);
if(sprintf(v_dfsql,"alter session set nls_date_format='%s'",f_info->date_format)>1023){
fprintf(stderr,ERR_EXP_SET_DATEFORMAT);
}
else
if(OCIExecSQL(&v_ocih,v_dfsql)<=0){
fprintf(stderr,ERR_EXP_DATEFORMAT);
}
file_name=(char*)mal

loc(sizeof(char)*(f_info->filename_len+1));
memset((void*)file_name,0,sizeof(char)*(f_info->filename_len+1));


getstrftime(time_buf,21,"%Y-%m-%d %I:%M:%S");
if(f_info->process_mode){
LOG_FORMAT_STRING_1(f_info->usr,f_info->ora,f_fname,time_buf);
}
else{
LOG_FORMAT_STRING_2(f_info->usr,f_info->ora,f_fname,time_buf);
}
/*查询*/
OCIOpenCDAParseSQL(&v_ocih,&v_ocic,f_sql,OCI_DELAYPARSE);
if(!OCIGetOraFieldSet(&v_ocic,f_info->fetch_buf,&v_fieldset)||!OCIExecCDA(&v_ocic)){
OCIPrintOraErr(&v_ocic._error);
OCICloseCDA(&v_ocic);
OCICloseORA(&v_ocih);
FREE(file_name);
return FALSE;
}
/*提取数据*/
else{
int v_rows;

if(sprintf(file_name,PATH_FILENAME,v_confinfo.datafile_path,f_fname)>v_confinfo.filename_len){
fprintf(stderr,ERRMSG_FILEPATH_BUF);
return ERR_FILEPATH_BUF;
}
if((fd=open(file_name,O_WRONLY|O_CREAT|O_TRUNC,0666))==-1){
OCICloseORA(&v_ocih);
fprintf(stderr,ERRMSG_CREATE_DATAFILE_1,file_name);
return ERR_CREATEOPEN_DATAFILE;
}
/*写入列名*/
printcolname(fd,&v_fieldset);
while((v_rows=OCIFetch2OraFieldSet(&v_ocic,f_info->fetch_buf,&v_fieldset))>0){
if(!f_info->process_mode){
printf("<");
fflush(stdout);
}
/*写入数据*/
printdata(fd,&v_fieldset);
i+=v_rows;
if(v_rowsfetch_buf)
break;
}
if(OCIIsOraErr(&v_ocic._error)){
OCIPrintOraErr(&v_ocic._error);
}
}
buf_write(fd,NULL,1);
close(fd);
OCIDestroyOraFieldSet(&v_fieldset);
OCICloseCDA(&v_ocic);
getstrftime(time_buf,21,"%Y-%m-%d %I:%M:%S");

if(f_info->process_mode){
LOG_FORMAT_STRING_3(f_info->usr,f_info->ora,f_fname,time_buf,i);
}
else{
LOG_FORMAT_STRING_4(time_buf,i);
}
//printf("\n**Exporting data(database-source:%s,file_name:%s)**\n",usr,fname);
OCICloseORA(&v_ocih);
//ora_close(&v_orah);
FREE(file_name);
return getpid();
}

int create_log(void){
int v_fdlog;
if(access(PATH_LOG,F_OK)==-1){
if(MKDIR(PATH_LOGDIR)==-1){
perror(ERRMSG_CREATE_LOGDIR);
exit(ERR_CREATE_LOGDIR);
}
}
else{
if(access(PATH_LOGDIR,W_OK)==-1){
perror(ERRMSG_LOGDIR_WRPERMISSION);
exit(ERR_LOGDIR_WRPERMISSION);
}
}
if((v_fdlog=open(PATH_LOG,O_CREAT|O_WRONLY|O_APPEND,0666))==-1){
perror(ERRMSG_CREATEOPEN_LOGFILE);
exit(ERR_CREATEOPEN_LOGFILE);
}
return v_fdlog;
}

int single_process(void){
FILE *v_sqlflptr;
s_link *tmpkeyvalue_link,*keyvalue_link;
keyvalue_link=init_slink(NULL);
if(!(v_sqlflptr=fopen("export_sql.conf","r"))){
fprintf(stderr,ERRMSG_NOTFOUND_SQLCONF);
//return ERR_NOTFOUND_SQLCONF;
return FALSE;
}
if(read_sql(v_sqlflptr,keyvalue_link)==-1){
fprintf(stderr,ERRMSG_SQLCONF_FORMAT);
//return ERR_SQLCONF_FORMAT;
return FALSE;
}
fclose(v_sqlflptr);
tmpkeyvalue_link=keyvalue_link;
while(tmpkeyvalue_link->_next_snode){
char *sql,*filename;
sql=((key_value*)tmpkeyvalue_link->_data)->value;
filename=((key_value*)tmpkey

value_link->_data)->key;
if(db_oper(&v_confinfo,sql,filename)<=0)
break;
FREE(filename);
FREE(sql);
tmpkeyvalue_link=tmpkeyvalue_link->_next_snode;
}
s_destroylink(&keyvalue_link);
return TRUE;
}

/*解析子进程退出码*/
void childprocess_recode(int f_recode){
if(f_recode<0){
switch(f_recode){
case ERR_OS_VERSION:
fprintf(stderr,ERRMSG_OS_VERSION);
break;
case ERR_CREATE_LOGDIR:
fprintf(stderr,ERRMSG_CREATE_LOGDIR);
break;
case ERR_LOGDIR_WRPERMISSION:
fprintf(stderr,ERRMSG_LOGDIR_WRPERMISSION);
break;
case ERR_CREATEOPEN_LOGFILE:
fprintf(stderr,ERRMSG_CREATEOPEN_LOGFILE);
break;
case ERR_NODEF_DBCONN:
fprintf(stderr,ERRMSG_NODEF_DBCONN);
break;
case ERR_FILEPATH_BUF:
fprintf(stderr,ERRMSG_FILEPATH_BUF);
break;
case ERR_CREATEOPEN_DATAFILE:
fprintf(stderr,ERRMSG_CREATEOPEN_DATAFILE);
break;
case ERR_CMD_ARG:
fprintf(stderr,ERRMSG_CMD_ARG);
break;
case ERR_NOTFOUND_SYSCONF:
fprintf(stderr,ERRMSG_NOTFOUND_SYSCONF);
break;
case ERR_SYSCONF_FORMAT:
fprintf(stderr,ERRMSG_SYSCONF_FORMAT);
break;
case ERR_OTHER:
default:
fprintf(stderr,ERRMSG_OTHER);
}
}
}

void createprocess_result(int f_pid){
switch(f_pid){
case E2BIG:
fprintf(stderr,MSG_CREATEPROC1);
break;
case EINVAL:
fprintf(stderr,MSG_CREATEPROC2);
break;
case ENOENT:
fprintf(stderr,MSG_CREATEPROC3);
break;
case ENOEXEC:
fprintf(stderr,MSG_CREATEPROC4);
break;
case ENOMEM:
fprintf(stderr,MSG_CREATEPROC5);
#ifdef SYSTEM
SYSTEM("pause");
#endif
exit(-1);
break;
case -1:
fprintf(stderr,MSG_CREATEPROC6);
}
}

int multi_process(char **argv){
#ifdef __MY_WIN32_FLAG__
int *v_pid;
#elif defined(__MY_LINUX_FLAG__)
pid_t *v_pid;
#else
{fprintf(stderr,ERRMSG_OS_VERSION);}
exit(ERR_OS_VERSION);
#endif
s_link *v_pidlink;
FILE *v_sqlflptr;
s_link *tmpkeyvalue_link,*keyvalue_link;
char *file_name,*sql;
char *v_file_name,*v_sql;


keyvalue_link=init_slink(NULL);
v_pidlink=init_slink(NULL);
if(!(v_sqlflptr=fopen("export_sql.conf","r"))){
fprintf(stderr,ERRMSG_NOTFOUND_SYSCONF);
return ERR_NOTFOUND_SYSCONF;
}
if(read_sql(v_sqlflptr,keyvalue_link)==-1){
fprintf(stderr,ERRMSG_SYSCONF_FORMAT);
return ERR_SYSCONF_FORMAT;
}
fclose(v_sqlflptr);
tmpkeyvalue_link=keyvalue_link;
while(1){
/*创建一定数量的进程*/
if(tmpkeyvalue_link->_next_snode&&v_pidlink->_total
file_name=((key_value*)tmpkeyvalue_link->_data)->key;
v_file_name=(char*)malloc(sizeof(char)*(STRLEN(file_name)+3));

strncpy(v_file_name,file_name,STRLEN(file_name)+3);

sql=((key_value*)tmpkeyvalue_link->_data)->value;
v_sql=(char*)malloc(sizeof(char)*(STRLEN(sql)+3));

strncpy(v_sql,sql,STRLEN(sql)+3);

fprintf(stderr,MSG_CUREXP,file_name,sql);

sprintf(v_file_name,"\"%s\"",file_name);
sprintf(v_sql,

"\"%s\"",sql);
#ifdef __MY_WIN32_FLAG__
v_pid=(int*)malloc(sizeof(int));
*v_pid=_spawnl(_P_NOWAIT,argv[0],argv[0],v_file_name,v_sql,NULL);
#elif defined(__MY_LINUX_FLAG__)
v_pid=(int*)malloc(sizeof(pid_t));
if((*v_pid=fork())==-1){
fprintf(stderr,MSG_CREATEPROCESS);
exit(-1);
}
else if(*v_pid==0){
execl(argv[0],argv[0],file_name,sql,NULL);
exit(-1);
}
#else
fprintf(stderr,ERRMSG_OS_VERSION);
exit(ERR_OS_VERSION);
#endif
if(s_addnode(v_pidlink,(void*)v_pid)==NULL){
fprintf(stderr,MSG_MAINTAINPROCESS);
#ifdef SYSTEM
SYSTEM("pause");
#endif
exit(-1);
}
fprintf(stderr,MSG_CURPROCESS);
s_travlink(v_pidlink,printpid);
fprintf(stderr,"\n");
FREE(v_file_name);
FREE(v_sql);
FREE(file_name);
FREE(sql);
tmpkeyvalue_link=tmpkeyvalue_link->_next_snode;
}
/*等待子进程结束*/
else{
if(v_pidlink->_total>0){
int child_status;
#ifdef __MY_WIN32_FLAG__
int v_pid;
s_link *v_tmppidlink;
v_tmppidlink=v_pidlink;
while(1){
if(v_tmppidlink->_next_snode){
if((v_pid=_cwait(&child_status,*(int*)v_tmppidlink->_data,_WAIT_CHILD))==ECHILD||v_pid==-1){
fprintf(stderr,MSG_CHILDRECODE);
fprintf(stderr,MSG_MAINTAINPROCESS);
#ifdef SYSTEM
SYSTEM("pause");
#endif
exit(-1);
}
childprocess_recode(child_status);
if(s_delfirstmatch(&v_pidlink,&v_pid,sizeof(int))!=1){
fprintf(stderr,MSG_MAINTAINPROCESS);
#ifdef SYSTEM
SYSTEM("pause");
#endif
exit(-1);
}
if(v_pidlink->_total){
fprintf(stderr,MSG_CURPROCESS);
s_travlink(v_pidlink,printpid);
fprintf(stderr,"\n");
}
break;
}
else
v_tmppidlink=v_pidlink;
v_tmppidlink=v_tmppidlink->_next_snode;
}
#elif defined(__MY_LINUX_FLAG__)
pid_t v_pid;
while((v_pid=waitpid(-1,&child_status,WNOHANG))>0&&v_pidlink->_total>0){
if(WIFEXITED(child_status)){
int v_recode;
v_recode=WEXITSTATUS(child_status);
childprocess_recode(v_recode);
}
else
childprocess_recode(ERR_OTHER);
if(s_delfirstmatch(&v_pidlink,&v_pid,sizeof(pid_t))!=1){
fprintf(stderr,MSG_MAINTAINPROCESS);
exit(-1);
}
if(v_pidlink->_total){
fprintf(stderr,MSG_CURPROCESS);
s_travlink(v_pidlink,printpid);
fprintf(stderr,"\n");
}
}
#else
fprintf(stderr,ERRMSG_OS_VERSION);
exit(ERR_OS_VERSION);
#endif
}

if(!tmpkeyvalue_link->_next_snode&&v_pidlink->_total==0)
break;
}


}
s_destroylink(&keyvalue_link);
s_destroylink(&v_pidlink);
return TRUE;
}

int create_datadir(void){
if(access(v_confinfo.datafile_path,F_OK)!=-1){
if(access(v_confinfo.datafile_path,W_OK)==-1){
fprintf(stderr,ERR_EXP_DATADIR_WRPERMISSION);
return FALSE;
}
}
else{
if(MKDIR(v_confinfo.datafile_path)==-1){


fprintf(stderr,ERR_EXP_CREATE_DATADIR);
return FALSE;
}
}
#ifdef __MY_WIN32_FLAG__
if(v_confinfo.datafile_path[strlen(v_confinfo.datafile_path)-1]=='\\')
#elif defined(__MY_LINUX_FLAG__)
if(v_confinfo.datafile_path[strlen(v_confinfo.datafile_path)-1]=='/')
#endif
v_confinfo.datafile_path[strlen(v_confinfo.datafile_path)-1]='\0';
return TRUE;
}


/*app_main.c*/
#include "export_sql.h"

conf_info v_confinfo={
DEF_FILENAMELEN,
NULL,
NULL,
NULL,
NULL,
PATH_DATADIR,
NULL,
DEF_LINEBUF,
DEF_REPLACE_NEWLINE,
DEF_DBCONNMODE,
DEF_PROCESSMODE,
DEF_PROCESSNUM
};

int main(int argc,char **argv)
{
int v_fdlog;
FILE *v_confflptr;

/*读配置文件*/

if(!(v_confflptr=fopen(PATH_SYSCONF,"r"))){
fprintf(stderr,ERRMSG_NOTFOUND_SYSCONF);
#ifdef SYSTEM
SYSTEM("pause");
#endif
return ERR_NOTFOUND_SYSCONF;
}

if(!read_conf(v_confflptr)||!STRLEN(v_https://www.360docs.net/doc/e08409986.html,r)||!STRLEN(v_confinfo.pwd)){
fprintf(stderr,ERRMSG_SYSCONF_FORMAT);
#ifdef SYSTEM
SYSTEM("pause");
#endif
return ERR_SYSCONF_FORMAT;
}
/*建立目录*/
create_datadir();
fclose(v_confflptr);

/*非命令行模式*/
if(argc==1){
/*单进程模式*/
if(!v_confinfo.process_mode){
single_process();
#ifdef SYSTEM
system("pause");
#endif
}
/*多进程模式*/
else{
if(!v_confinfo.process_num){
fprintf(stderr,ERRMSG_MULTIPROCESS_PARMATER);
return ERR_MULTIPROCESS_PARMATER;
}
else
multi_process(argv);
#ifdef SYSTEM
system("pause");
#endif
}
}
/*命令行模式*/
else{
v_fdlog=create_log();
dup2(v_fdlog,2);
if(argc==3)
return db_oper(&v_confinfo,argv[2],argv[1]);
else{
fprintf(stderr,CMD_ARGFORMAT,argv[0]);
return ERR_CMD_ARG;
}
}
return 0;
}


/*export_sql.conf配置文件*/
##格式:导出文件名=SQL语句;##
##由于是简单判断SQL语句的有效性,所以每条语句的起始行必须为一新行,而不能跟着上一条SQL语句##
TMP_0116_CZ1=select * from TMP_0116_CZ1;
TMP_0116_CZ11=select * from TMP_0116_CZ11;
/*export_conf.conf配置文件*/
##文件名长度控制##
filename_len=40;
##多进程模式,注意在WINDOWS下,现阶段每个SQL语句不能超过1K字节的长度,LINUX下没有限制,默认为单进程模式##
process_mode=multi;
##进程数量,默认为4个,在process_mode=multi下有效##
process_num=4;
##是否替换掉换行符#
REPLACE_NEWLINE=TRUE;
##每次提取的行数,不能超过32521这个常量值,如果此值过大的同时,数据库字段的长度也过大,则程序会引内存不足而直接退出##
fetch_bufline=2000;
##本地字符编码到指定编码转换##
charset=UTF-8;
##用户名与ORCL服务名##
user=jsbdp@jsyw;
##密码##
password=js_bdp_2;
##数据文件输出路径,如果为空,输出数据则在安装程序下面###
#DATAFILE_PATH=F:\export_data;
##数据文件的日期时间格式##
date_format=yyyy-mm-dd hh24:mi:ss;



/*Readme.txt*/
说明:
1.每个配置项都是键值的关系,并以';'结束,且必须在一行的末尾。例如:filename_len=40;
2.windows下的版本请不要安装在默认安装目录下,即C:\Program Files\。否则多进程模式会报错,
还没有找到问题的原因。
3.在导出大表,即字段很多,且每个字段的长度很长时,请不要使用多进程模式,并严格控制fetch_bufline参数的大小,
否则程序会因为内存分配达到上限,而停止运行。典型实例是在整表导出表t1_enterprise_industry_feild时,
如果fetch_bufline设置为5000时,此进程将消耗1.4GB的内存空间。
4.如果字段为CLOB、RAW时,字段的内容不能操作4069字节,否则会被截断。
且暂时只实现对NUMBER、CHAR、VARCHAR、DATE、TIMESTAMP、CLOB、RAW的字段类型的导出。
5.LINUX控制台下的输出信息是原本是GBK编码模式的。如果要更改,请在编译时,将export_sql.h头文件用iconv命令转码。
例如:iconv -f GBK -t UTF8 export_sql.h > tmpexport_sql.h;\rm -f export_sql.h;\mv tmpexport_sql.h export_sql.h
6.LINUX下export_conf.conf配置文件最好使用UTF8编码。
7.在LINUX下编译之前,请修改install.sh脚本中的关于ORACLE环境变量,然后运行./install.sh进行编译。并确保系统安装了gcc编译器,
如果系统有其他c的编译器,请修改Makefile文件中的$(CC)的值,例如,如果是cc编译器,则修改为$(CC) = cc。
8.在linux下运行前,请设置关于ORACLE的环境变量,示例如下:
export ORACLE_HOME="/opt/oracle/product/10.2.0"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
export PATH=$PATH:$ORACLE_HOME/bin
export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

可以制作一个运行脚本:
#!/bin/sh
export ORACLE_HOME="/opt/oracle/product/10.2.0"
export LD_LIBRARY_PATH="$ORACLE_HOME/lib"
export PATH=$PATH:$ORACLE_HOME/bin
export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"

./oci_export

9.LINUX平台下,单线程模式下CTRL+Z挂起进程暂时没有解决。CTRL+C或CTRL+\可以被捕获信号,都是停止进程。
10.程序还有命令行模式,用法如下:
$>程序名 导出数据文件 "导出SQL语句"
程序的其他参数(用户,密码,TNS名)使用配置文件export_conf.conf中的参数。
11.配置文件conf/export_conf.conf文件的说明如下,忽略大小写:
##文件名长度控制,主要是考虑到路径名很长的情况,一般没什么用,可以忽略
filename_len=40;
##多进程模式,注意在WINDOWS下,现阶段每个SQL语句不能超过1K字节的长度,
#LINUX下没有限制,程序默认为单进程模式single,多进程模式为multi
process_mode=multi;
##进程数量,程序默认为4个,在process_mode=multi下有效
process_num=4;
##是否替换掉换行符,程序默认为FALSE,即不替换,如果要替换则设置为TRUE#
REPLACE_NEWL

INE=TRUE;
##每次提取的行数,程序默认为1000行。此值不能超过32521这个常量值,如果此值过大的同时,
#数据库字段的长度也过大,则程序会引内存不足而直接退出
fetch_bufline=2000;
##本地字符编码到指定编码转换,暂时没有实现,如果在LINUX下面,可以使用iconv命令转码数据文件
charset=UTF-8;
##用户名与ORCL服务名
user=jsbdp@jsyw;
##密码##
password=js_bdp_2;
##数据文件输出路径,如果为空,输出数据则在程序安装目录的datafile文件夹下面
#DATAFILE_PATH=F:\export_data;
##数据文件的日期时间格式##
date_format=yyyy-mm-dd hh24:mi:ss;

相关主题
相关文档
最新文档