Oracle OCI 编译

源码:tbuldr.c摘自网络

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <oci.h>
#include <oratypes.h>
#include <ocidfn.h>
#ifdef __STDC__
#include <ociapr.h>
#else
#include <ocikpr.h>
#endif
#include <ocidem.h>

#if defined(_WIN32)
#define STRNCASECMP memicmp
#else
#define STRNCASECMP strncasecmp
#endif

#define  MIN(a,b) ((a) > (b) ? (b) : (a))

/* constants */
#define MAJOR_VERSION_NUMBER       2
#define MInor_VERSION_NUMBER       21
#define MAX_SELECT_LIST_SIZE       65534
#define MAX_COLNAME_BUFFER_SIZE    65534
#define MAX_CLOB_SIZE              65534 
#define MAX_IO_BUFFER_SIZE         1048576      

/* return code */
#define SUCCESSFUL        0
#define ERROR_logoN       1
#define ERROR_PREPARE_sql 2
#define ERROR_EXECUTE_sql 3
#define ERROR_MetaDATA    4
#define ERROR_OUT_FILE    5
#define ERROR_FETCH       6
#define ERROR_OTHER       100

/*global env variables*/
static OCIEnv       *p_env  = (OCIEnv *)0;
static OCIServer    *p_srv  = (OCIServer *)0;
static OCIError     *p_err  = (OCIError *)0;
static OCISvcCtx    *p_svc  = (OCISvcCtx *)0;
static OCIStmt      *p_stmt = (OCIStmt *)0;
static OCIDescribe  *p_desc = (OCIDescribe *)0;
static OCISession   *p_sess = (OCISession *)0;

struct COLUMN
{
  /* Describe */
  ub2             colwidth;
  ub2             coltype;
  ub2             precision;
  ub2             scale;
  text            fmtstr[64]; // for fixlen output
  text            *colname;

  /*+ Fetch */
  OCIDefine       *p_define;
  ub1             *colbuf;    //output variable
  sb2             *p_indv;
  ub2             *col_retlen;
  ub2             *col_retcode;

  /*+ Point to next column */
  struct          COLUMN *next;
};

struct ParaM
{
  text query[65534];
  text field[65534];
  text record[65534];
  text enclose[65534];
  text connstr[65534];
  text fname[65534];
  text sqlfname[65534];
  text logfile[65534];
  text tabname[65534];
  text tabmode[65534];

  ub1  field_len;   // field length
  ub1  return_len;  // return length
  ub1  enclose_len; // enclose length
  ub4  buffer;      // buffer size,default 16MB
  ub2  hsize;       // hash_area_size
  ub2  ssize;       // sort_area_size
  ub2  bsize;       // db_file_multiblock_read_count
  ub1  serial;      // _serial_direct_read
  ub1  trace;       // 10046 trace level
  ub2  batch;       // batch out files
  ub1  header;      // output header line
  ub4  Feedback;    // display progress log every x rows
  
  ub4  asize;       // array size
  ub4  lsize;       // long size 

  ub1 isstDOUT;     // stdout,not file
  ub1 isForm;       // display as MysqL form format
  ub1 isFixlen;     // fixed length output format
  ub1 debug;        // debug mode,more log output
};

struct COLUMN col;
struct ParaM *param;
int    return_code = SUCCESSFUL;
int    row_totallen=0;
FILE   *fp_log = NULL;
FILE   *fp_ctl = NULL;

/* functions */
void env_init();
void env_exit();

void session_init();

sword db_logon(char *v_user,char *v_pass,char *v_host);
void  db_logout();

void decode_connstr(char *v_user,char *v_host);
void check_err(OCIError *p_err,sword status);
void print_help();

sword sql_prepare(OCIStmt *p_stmt,text *sql_statement);
sword sql_execute(OCISvcCtx *p_svc,OCIStmt *p_stmt,ub4 execount);

sword get_columns(OCIStmt *p_stmt,struct COLUMN *collist);
void  free_columns(struct COLUMN *col);

void print_Feedback(ub4 row);
void print_row(OCISvcCtx *p_svc,struct COLUMN *col);

int  get_param(int argc,char **agrv);
void sqlldr_ctlfile(struct COLUMN *collist,ub2 numcols);

int convert_option(const ub1 *src,ub1* dst,int mlen);
ub1 get_hexindex(char c);

FILE *open_file(const text *fname,text tempbuf[],int batch);

int main(int argc,char *argv[])
{
  char *p_user=malloc(32);
  char *p_pass=malloc(32);
  char *p_host=malloc(32);

  if(get_param(argc,argv)) return return_code;
  
  if(strlen(param->connstr)){
    decode_connstr(p_user,p_pass,p_host);
  }
  else{
    return_code=ERROR_OTHER;
    print_help();
  }
  
  env_init();

  if(db_logon(p_user,p_host)==1)
  {
    return_code=ERROR_logoN;
    return return_code;
  }

  session_init();

  if(sql_prepare(p_stmt,param->query)==0)
  {
    if(sql_execute(p_svc,p_stmt,0)==0)
    {
      get_columns(p_stmt,&col);
      print_row(p_svc,&col);
      free_columns(&col);
    }
  }

  db_logout();
  env_exit();

  return return_code;
}

/* ----------------------------------------------------------------- */
/* initialize environment,allocate handles,etc.                    */
/* ----------------------------------------------------------------- */
void env_init ()
{
  OCIEnvCreate((OCIEnv **) &p_env,OCI_THREADED|OCI_OBJECT,(dvoid *)0,(dvoid * (*)(dvoid *,size_t)) 0,dvoid *,size_t))0,(void (*)(dvoid *,dvoid *)) 0,(size_t) 0,(dvoid **) 0);

  /* error handle */
  OCIHandleAlloc ((dvoid *) p_env,(dvoid **) &p_err,OCI_HTYPE_ERROR,(dvoid **) 0);

  /* server handle */
  OCIHandleAlloc ((dvoid *) p_env,(dvoid **) &p_srv,OCI_HTYPE_SERVER,(dvoid **) 0);
  /* svcctx handle*/
  OCIHandleAlloc ((dvoid *) p_env,(dvoid **) &p_svc,OCI_HTYPE_SVCCTX,(dvoid **) 0);

  /* set attribute server context in the service context */
  OCIAttrSet ((dvoid *) p_svc,(dvoid *)p_srv,(ub4) 0,OCI_ATTR_SERVER,(OCIError *) p_err);

  /*stmt handle*/
  OCIHandleAlloc((dvoid *) p_env,(dvoid **) &p_stmt,OCI_HTYPE_STMT,(dvoid **) 0);
}

/* ----------------------------------------------------------------- */
/* attach to the server and log on                                   */
/* ----------------------------------------------------------------- */
sword db_logon (char *v_user,char *v_host)
{
  sword rc;

  OCIHandleAlloc ((dvoid *) p_env,(dvoid **)&p_sess,(ub4) OCI_HTYPE_SESSION,(dvoid **) 0);

  if (strlen(v_host)==0)
  {
    check_err(p_err,OCIServerAttach (p_srv,p_err,(text *)0,(sb4)0,OCI_DEFAULT));
  }		
  else
  {
    check_err(p_err,(text *)v_host,(sb4)strlen("v_host"),OCI_DEFAULT));
  } 

  OCIAttrSet ((dvoid *)p_sess,(ub4)OCI_HTYPE_SESSION,(dvoid *)v_user,(ub4)strlen((char *)v_user),OCI_ATTR_USERNAME,p_err);

  OCIAttrSet ((dvoid *)p_sess,(dvoid *)v_pass,(ub4)strlen((char *)v_pass),OCI_ATTR_PASSWORD,p_err);

  rc=OCISessionBegin(p_svc,p_sess,OCI_CRED_RDBMS,OCI_DEFAULT);

  if(rc)
  {
    check_err(p_err,rc);
    return 1;
  }

  OCIAttrSet ((dvoid *) p_svc,(ub4) OCI_HTYPE_SVCCTX,(dvoid *) p_sess,(ub4) OCI_ATTR_SESSION,p_err);

  if(v_user) free(v_user);
  if(v_pass) free(v_pass);
  if(v_host) free(v_host);

  return 0;
}

/*-------------------------------------------------------------------*/
/* logoff and disconnect from the server.                            */
/*-------------------------------------------------------------------*/
void db_logout()
{
  if (param->trace)
  {
    sql_prepare(p_stmt,"ALTER SESSION SET EVENTS='10046 TRACE NAME CONTEXT OFF'");
    sql_execute(p_svc,1);
  }

  OCIHandleFree ((dvoid *) p_stmt,(ub4) OCI_HTYPE_STMT);

  OCISessionEnd (p_svc,(ub4) 0);
}

/*-------------------------------------------------------------------*/
/* Free handles and exit.                                            */
/*-------------------------------------------------------------------*/
void env_exit()
{
  if (p_err)  OCIServerDetach (p_srv,(ub4) OCI_DEFAULT );
  if (p_srv)  OCIHandleFree((dvoid *) p_srv,(CONST ub4) OCI_HTYPE_SERVER);
  if (p_svc)  OCIHandleFree((dvoid *) p_svc,(CONST ub4) OCI_HTYPE_SVCCTX);
  if (p_err)  OCIHandleFree((dvoid *) p_err,(CONST ub4) OCI_HTYPE_ERROR);
  if (p_sess) OCIHandleFree((dvoid *) p_sess,(CONST ub4) OCI_HTYPE_SESSION);
  if (p_stmt) OCIHandleFree((dvoid *) p_stmt,(CONST ub4) OCI_HTYPE_STMT);

  if (fp_ctl) fclose(fp_ctl);
  if (fp_log) fclose(fp_log);

  if (param) free(param);

//  exit(return_code);
}

/* ----------------------------------------------------------------- */
/* retrieve error message and print it out.                          */
/* ----------------------------------------------------------------- */
void check_err(OCIError *p_err,sword status)
{
  text errbuf[512];
  sb4 errcode = 0;

  switch (status)
  {
  case OCI_SUCCESS:
    break;
  case OCI_SUCCESS_WITH_INFO:
    (void) printf("Error - OCI_SUCCESS_WITH_INFO\n");
    (void) OCIErrorGet ((dvoid *)p_err,(ub4) 1,(text *) NULL,&errcode,errbuf,(ub4) sizeof(errbuf),OCI_HTYPE_ERROR);
    (void) printf("        %.*s\n",512,errbuf);
    break;
  case OCI_NEED_DATA:
    (void) printf("Error - OCI_NEED_DATA\n");
    break;
  case OCI_NO_DATA:
    (void) printf("Error - OCI_NODATA\n");
    break;
  case OCI_ERROR:
    (void) OCIErrorGet ((dvoid *)p_err,OCI_HTYPE_ERROR);
    (void) printf("Error - %.*s\n",errbuf); 
    break;
  case OCI_INVALID_HANDLE:
    (void) printf("Error - OCI_INVALID_HANDLE\n");
    break;
  case OCI_STILL_EXECUTING:
    (void) printf("Error - OCI_STILL_EXECUTE\n");
    break;
  case OCI_CONTINUE:
    (void) printf("Error - OCI_CONTINUE\n");
    break;
  default:
    break;
  }
}

/* ----------------------------------------------------------------- */
/* get username,password,alias from use= string                      */
/* ----------------------------------------------------------------- */
void decode_connstr(char *v_user,char *v_host)
{
  char *r1="/";
  char *r2="@";
  int  n1=0;
  int  n2=0;

  n1=strcspn(param->connstr,r1);
  n2=strcspn(param->connstr,r2);

  strncpy(v_user,param->connstr,n1);

  if( n2>n1 ){
    strncpy(v_pass,&param->connstr[n1+1],n2-n1-1);
  }

  if( strlen(param->connstr)>n2){
    strncpy(v_host,&param->connstr[n2+1],strlen(param->connstr)-n2-1);
  }
}

/* ----------------------------------------------------------------- */
/* print help information                                            */
/* ----------------------------------------------------------------- */
void print_help()
{
  printf("\n----------------------------------------------------------------------------\n");
  printf("- tbuldr: Release %d.%d (ociuldr)\n",MAJOR_VERSION_NUMBER,MInor_VERSION_NUMBER);
  printf("- First issued by Lou Fangxin (@) copyright 2004/2008,all rights reserved.\n");
  printf("- Modified by Ning Haiyuan (http://www.NinGoo.net).\n");
  printf("----------------------------------------------------------------------------\n");
  printf(" Usage: TBULDR keyword=value [,keyword=value,...]\n");
  printf(" Valid Keywords:\n");
  printf("       user     = username/password@tnsname\n");
  printf("       query    = select statement,can simply speicify a table name\n");
  printf("       sql      = sql file name\n");
  printf("       field    = seperator string between fields\n");
  printf("       record   = seperator string between records\n");
  printf("       enclose  = fields enclose string\n");
  printf("       file     = output file name,default: uldrdata.txt\n");
  printf("       head     = print row header(Yes|No,ON|OFF,1|0)\n");
  printf("       read     = set DB_FILE_MULTIBLOCK_READ_COUNT at session level\n");
  printf("       sort     = set SORT_AREA_SIZE at session level (UNIT:MB) \n");
  printf("       hash     = set HASH_AREA_SIZE at session level (UNIT:MB) \n");
  printf("       serial   = set _serial_direct_read to TRUE if 1 at session level\n");
  printf("       trace    = set event 10046 to given level at session level\n");
  printf("       table    = table name in the sqlldr control file\n");
  printf("       mode     = sqlldr option,INSERT or APPEND or REPLACE or TruncATE \n");
  printf("       log      = log file name,prefix with + to append mode\n");
  printf("       long     = maximum long field size,default 8192 max 65534\n");
  printf("       array    = array fetch size,default 50\n");
  printf("       buffer   = sqlldr READSIZE and BINDSIZE,default 16 (MB)\n");
  printf("       Feedback = display progress every x rows,default 500000\n");
  printf("       form     = display rows as form (Yes|No)\n");
  printf("       fixlen   = fix length format (Yes|No)\n");
  printf("\n");
  printf("  for field,record and enclose,use '0x' to specify hex character code\n");
  printf("  \\r=0x%02x \\n=0x%02x |=0x%0x,=0x%02x \\t=0x%02x",'\r','\n','|',','\t');
  printf("  (more: man ascii)\n\n");

  return_code=ERROR_OTHER;
}

/* ----------------------------------------------------------------- */
/* prepare a sql statement                                           */
/* ----------------------------------------------------------------- */
sword sql_prepare(OCIStmt *p_stmt,text *sql_statement)
{
  sword rc;
  rc=OCIStmtPrepare(p_stmt,(text *) sql_statement,(ub4) strlen(sql_statement),OCI_NTV_Syntax,OCI_DEFAULT);

  if (rc!=0)
  {
    check_err(p_err,rc);
    return_code=ERROR_logoN;
    return -1;
  }
  else
    return 0;
}

/* ----------------------------------------------------------------- */
/* execute a sql statement                                           */
/* ----------------------------------------------------------------- */
sword sql_execute(OCISvcCtx *p_svc,ub4 execount)
{
  sword rc;
  rc=OCIStmtExecute(p_svc,execount,NULL,OCI_DEFAULT);

  if (rc!=0)
  {
   check_err(p_err,rc);
   return -1;
  }
  return 0;
}

/* ----------------------------------------------------------------- */
/* initialize session,set date format                               */
/* ----------------------------------------------------------------- */
void session_init()
{
  text tempbuf[65534];

  sql_prepare(p_stmt,"ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
  sql_execute(p_svc,1);

  sql_prepare(p_stmt,"ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SSXFF'");
  sql_execute(p_svc,"ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SSXFF TZH:TZM'");
  sql_execute(p_svc,1);

  if(param->bsize)
  {
    memset(tempbuf,65534);
    sprintf(tempbuf,"ALTER SESSION SET DB_FILE_MULTIBLOCK_READ_COUNT=%d",param->bsize);
    sql_prepare(p_stmt,tempbuf);
    sql_execute(p_svc,1);
  }

  if(param->hsize)
  {
    memset(tempbuf,"ALTER SESSION SET HASH_AREA_SIZE=%d",param->hsize*1048576);
    sql_prepare(p_stmt,1);
  }

  if(param->ssize)
  {
    memset(tempbuf,"ALTER SESSION SET SORT_AREA_SIZE=%d",param->ssize*1048576);
    sql_prepare(p_stmt,1);

    memset(tempbuf,"ALTER SESSION SET SORT_AREA_RETAINED_SIZE=%d",1);

    sql_prepare(p_stmt,"ALTER SESSION SET \"_sort_multiblock_read_count\"=128");
    sql_execute(p_svc,1);
  }
  
  if (param->serial)
  {
    memset(tempbuf,"ALTER SESSION SET \"_serial_direct_read\"=TRUE");
    sql_prepare(p_stmt,1);
  }

  if (param->trace)
  {
    memset(tempbuf,"ALTER SESSION SET EVENTS='10046 TRACE NAME CONTEXT FOREVER,LEVEL %d'",param->trace);
    sql_prepare(p_stmt,1);
  }
}

/* ----------------------------------------------------------------- */
/* get column deFinition                                             */
/* ----------------------------------------------------------------- */
sword get_columns(OCIStmt *p_stmt,struct COLUMN *collist)
{
  OCIParam      *p_param = (OCIParam *) 0;
  ub4           col;
  ub2           numcols;       //select-list columns
  struct COLUMN *tempcol;
  struct COLUMN *nextcol;

  nextcol = collist;

  //get table describ info
  if(!param->isstDOUT) printf("\n");

  //get columns
  check_err(p_err,OCIAttrGet(p_stmt,&numcols,OCI_ATTR_ParaM_COUNT,p_err));

  /* Describe the select-list items. */
  for (col = 0; col < numcols; coL++)
  {
    tempcol = (struct COLUMN *) malloc(sizeof(struct COLUMN));
    tempcol-> p_indv        = (sb2 *)malloc(param->asize * sizeof(sb2));
    tempcol-> col_retlen  = (ub2 *)malloc(param->asize * sizeof(ub2));
    tempcol-> col_retcode = (ub2 *)malloc(param->asize * sizeof(ub2));
    tempcol-> colname     = malloc(MAX_COLNAME_BUFFER_SIZE);
    memset(tempcol-> colname,MAX_COLNAME_BUFFER_SIZE);
    memset(tempcol->p_indv,param->asize * sizeof(sb2));
    memset(tempcol->col_retlen,param->asize * sizeof(ub2));
    memset(tempcol->col_retcode,param->asize * sizeof(ub2));

    tempcol->next = NULL;
    tempcol->colbuf = NULL;
    memset(tempcol->fmtstr,64);

    /* get parameter for column col*/
    check_err(p_err,OCIParamGet(p_stmt,(void **)&p_param,col+1));
    /* get data-type of column col */
    check_err(p_err,OCIAttrGet(p_param,OCI_DTYPE_ParaM,&tempcol->coltype,OCI_ATTR_DATA_TYPE,p_err));
    check_err(p_err,&tempcol->colname,0/*&tempcol->colname_len*/,(ub4)OCI_ATTR_NAME,&tempcol->colwidth,OCI_ATTR_DATA_SIZE,&tempcol->precision,OCI_ATTR_PRECISION,&tempcol->scale,OCI_ATTR_SCALE,p_err));

    nextcol->next = tempcol;
    nextcol=tempcol;

    switch(nextcol->coltype)
    {
      case sqlT_DATE:
      case sqlT_DAT:
        nextcol->colwidth=19;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_TIMESTAMP: /* TIMESTAMP */
        nextcol->colwidth=26;
        break;
      case sqlT_TIMESTAMP_TZ: /* TIMESTAMP WITH TIMEZONE */
        nextcol->colwidth=33;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_LBI:  /* LONG RAW */
      case sqlT_BLOB:
        nextcol->colwidth=param->lsize;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_CLOB:  
        nextcol->colwidth=param->lsize;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_RDD:
        nextcol->colwidth=18;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_INT:
      case sqlT_NUM:
        if (nextcol->precision)
          nextcol->colwidth=nextcol->precision;
        else
          nextcol->colwidth=38;
//        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      case sqlT_FILE: /* BFILE */
        nextcol->colwidth=param->lsize;
 //       nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      default:
        nextcol->coltype=(param->isFixlen?sqlT_AVC:STRING_TYPE);
        break;
      }

      if (nextcol->colwidth > param->lsize || nextcol->colwidth == 0)
      {
         nextcol->colwidth = param->lsize;
      }

      if(param->enclose_len) tempcol->colwidth=tempcol->colwidth+2*param->enclose_len;

      row_totallen = row_totallen + nextcol->colwidth;
      sprintf(nextcol->fmtstr,"%%-%ds",nextcol->colwidth);

      /* add some more byte to buffer */
      nextcol->colwidth++;
      nextcol->colbuf = malloc((int)param->asize * nextcol->colwidth);
      memset(nextcol->colbuf,((int)param->asize * nextcol->colwidth));
      
      if(param->debug)
         printf("%10d bytes allocated for column %s (%d) type %d\n",nextcol->colwidth*param->asize,nextcol->colname,nextcol->colwidth-1,nextcol->coltype);

      //define output
      if (nextcol->coltype==sqlT_BLOB || nextcol->coltype==sqlT_LBI )
      {
        check_err(p_err,OCIDefineByPos(p_stmt,&nextcol->p_define,col+1,(dvoid *) nextcol->colbuf,nextcol->colwidth,sqlT_LBI,nextcol->p_indv,(ub2 *)nextcol->col_retlen,(ub2 *)nextcol->col_retcode,OCI_DEFAULT));	
      }
      else
      {
        check_err(p_err,sqlT_STR,OCI_DEFAULT));
      }	
  }
  
  sqlldr_ctlfile(collist,numcols);

  return 0;
}

/* ----------------------------------------------------------------- */
/* free column datastruct                                            */
/* ----------------------------------------------------------------- */
void free_columns(struct COLUMN *col)
{
   struct COLUMN *p,*temp;
   p=col->next;

   col->next = NULL;
   while(p!=NULL)
   {
     free(p->colbuf);
     free(p->p_indv);
     free(p->col_retlen);
     free(p->col_retcode);

     temp=p;
     p=temp->next;
     free(temp);
   }
}

/* ----------------------------------------------------------------- */
/* output query result                                               */
/* ----------------------------------------------------------------- */
void print_row(OCISvcCtx *p_svc,struct COLUMN *col)
{
  ub4    colcount;
  ub4    tmp_rows;
  ub4    tmp_rows_size;
  ub4    rows;
  ub4    j;
  ub4    seconds;
  sword  rc;
  sword  r;
  ub4    c;
  ub4    trows;
  struct COLUMN *p;
  struct COLUMN *cols[MAX_SELECT_LIST_SIZE];
  text   tempbuf[512];
  FILE   *fp = NULL;
  FILE   *fp_lob = NULL;
  ub1    *iobuf = NULL;

  time_t start_time,end_time;
  
  int bcount=1;
  trows=0;
  colcount=0;

  start_time=time(0);
  
  p = col->next;
  while(p != NULL)
  {
    cols[colcount] = p;
    p=p->next;
    colcount++;
  }
  
  memset(tempbuf,512);

  if(!param->isstDOUT)
  {
    if((fp = open_file(param->fname,tempbuf,bcount)) == NULL) 
    {
      fprintf((fp_log == NULL?stderr:fp_log),"ERROR -- Cannot write to file : %s\n",tempbuf);
      return_code=ERROR_OUT_FILE;
      return;
    }

    iobuf = (text *)malloc(MAX_IO_BUFFER_SIZE);
    memset(iobuf,MAX_IO_BUFFER_SIZE);
    if(setvbuf(fp,iobuf,_IOFBF,MAX_IO_BUFFER_SIZE))
      printf("Canot setup buffer for output file!\n");
  }

  if (param->header)
  {
    for(c=0;c<colcount;c++)
    {
      if (param->isFixlen)
        fprintf(fp,cols[c]->fmtstr,cols[c]->colname);
      else
      {
        fprintf((fp == NULL?stdout:fp),"%s",cols[c]->colname);
        if (c < colcount - 1) 
          fwrite(param->field,param->field_len,1,(fp == NULL?stdout:fp));
      }
    }
    if(!param->isFixlen) fwrite(param->record,param->return_len,(fp == NULL?stdout:fp));
  }

  if(param->debug) fprintf((fp_log == NULL?stderr:fp_log),"\n");
  print_Feedback(trows);
  for (;;)
  {
    rows = param->asize;
    rc=OCIStmtFetch(p_stmt,param->asize,OCI_DEFAULT);    

    if (rc !=0)
    {
      if (rc!= OCI_NO_DATA) check_err(p_err,rc);
      
      check_err(p_err,OCIAttrGet((dvoid *) p_stmt,(ub4) OCI_HTYPE_STMT,(dvoid *)&tmp_rows,(ub4 *) &tmp_rows_size,(ub4)OCI_ATTR_ROWS_FETCHED,p_err));
      rows = tmp_rows % param->asize;
    }		
    
    for(r=0;r<rows;r++)
    {
      for(c=0;c<colcount;c++)
      {
        if (param->isForm)
        {
          fprintf((fp == NULL?stdout:fp),"%-31s: ",cols[c]->colname);
        }
        if (*(cols[c]->p_indv+r) >= 0)
        {
          if (cols[c]->coltype == sqlT_LBI || cols[c]->coltype == sqlT_BLOB) //long binary type
          {  
            if(param->enclose_len) fwrite(param->enclose,param->enclose_len,(fp == NULL?stdout:fp));
            for(j=0;j < *(cols[c]->col_retlen+r); j++)
            {
               fprintf((fp == NULL?stdout:fp),"%02x",cols[c]->colbuf[r * cols[c]->colwidth + j]);
            }
            if(param->enclose_len) fwrite(param->enclose,(fp == NULL?stdout:fp));
          }
          else
          { 
            if(param->isFixlen)
              fprintf(fp,cols[c]->colbuf+(r* cols[c]->colwidth));
            else
            {
              if(param->enclose_len) fwrite(param->enclose,(fp == NULL?stdout:fp));
/*
              ub1 *p_tmp=cols[c]->colbuf+(r* cols[c]->colwidth);
              while(*p_tmp)
              {
                if(STRNCASECMP(p_tmp,param->field,param->field_len)==0) memcpy(p_tmp," ",param->field_len);
                p_tmp=p_tmp+param->field_len;
              }
*/
              fwrite(cols[c]->colbuf+(r* cols[c]->colwidth),*(cols[c]->col_retlen+r),(fp == NULL?stdout:fp));
              if(param->enclose_len) fwrite(param->enclose,(fp == NULL?stdout:fp));
            }
          }
        }
        if (param->isForm)
        {
          fprintf((fp == NULL?stdout:fp),"\n");
        }
        else
        {
          if (c < colcount - 1)
            if(!param->isFixlen) fwrite(param->field,(fp == NULL?stdout:fp));
        }  
      }
      if(!param->isFixlen) fwrite(param->record,(fp == NULL?stdout:fp));
      trows=trows+1;
      if (trows % param->Feedback  == 0)
      {
        print_Feedback(trows);
        if(param->batch && ((trows / param->Feedback) % param->batch) == 0)
        {
          if(!param->isstDOUT)
            fprintf((fp_log == NULL?stderr:fp_log),"         output file %s closed at %u rows.\n",trows);
          if(fp) fclose(fp);
          bcount++;
          memset(tempbuf,512);

          if(param->isstDOUT)
          {
            if((fp = open_file(param->fname,bcount)) == NULL) 
            {
              fprintf((fp_log == NULL?stderr:fp_log),tempbuf);
              return_code=ERROR_OUT_FILE;
              return;
            }
          }

          if (param->header)
          {
            for(c=0;c<colcount;c++)
            {
              fprintf(fp,cols[c]->colname);
              if (c < colcount - 1)
                fwrite(param->field,(fp == NULL?stdout:fp));
            }
            if(param->isFixlen) fwrite(param->record,(fp == NULL?stdout:fp));
          }
          trows = 0;
        }
      }
    }
    if (rows < param->asize) break;
  }
  if (trows % param->Feedback != 0)
    print_Feedback(trows);
  if(fp) fclose(fp);
 
  end_time=time(0);

  seconds = difftime(end_time,start_time);

  if(!param->isstDOUT)
    fprintf((fp_log == NULL?stderr:fp_log),"         output file %s closed at %u rows. Elapsed time: %d min %d sec.\n",trows,seconds/60,seconds%60);
  else
    if(fp_log) fprintf(fp_log,"         output file %s closed at %u rows. Elapsed time: %d min %d sec\n",seconds%60);
  if(fp_ctl) 
  {
    memset(tempbuf,128);
    sprintf(tempbuf,"%s_sqlldr.ctl",param->tabname);
    if(!param->isstDOUT)
      fprintf((fp_log == NULL?stderr:fp_log),"         control file is %s\n",tempbuf);
    else
      if(fp_log) fprintf(fp_log,tempbuf);
  }
  if(!param->isstDOUT) fprintf((fp_log == NULL?stderr:fp_log),"\n");
  fflush((fp_log == NULL?stderr:fp_log));

  if(iobuf) free(iobuf);
}

/* ----------------------------------------------------------------- */
/* get field and record char if it is hex code                       */
/* ----------------------------------------------------------------- */
int convert_option(const ub1 *src,int mlen)
{
  int i,len,pos;
  ub1 c,c1,c2;

  i=pos=0;
  len = strlen(src);
 
/*  if(STRNCASECMP(src,"0x",2)) 
  {
    memcpy(dst,src,MIN(mlen,len));
    return MIN(mlen,len);
  }  
*/ 
  while(i<MIN(mlen,len))
  {
    if ( *(src+i) == '0')
    {
      if (i < len - 1)
      {
         c = *(src+i + 1);
         switch(c)
         {
           case 'x':
           case 'X':
             if (i < len - 3)
             {
               c1 = get_hexindex(*(src+i + 2));
               c2 = get_hexindex(*(src+i + 3));
               *(dst + pos) = (ub1)((c1 << 4) + c2);
               i=i+2;
             }
             else if (i < len - 2)
             {
               c1 = *(src+i + 2);
               *(dst + pos) = c1;
               i=i+1;
             }
               break;
            default:
               *(dst + pos) = c;
               break;
         }
         i = i + 2;
      }
      else
      {
        i ++;
      }
    }
    else
    {
      *(dst + pos) = *(src+i);
      i ++;
    }
    pos ++;
  }
  *(dst+pos) = '\0';

  return pos;
}

ub1  get_hexindex(char c)
{
  if ( c >='0' && c <='9') return c - '0';
  if ( c >='a' && c <='f') return 10 + c - 'a';
  if ( c >='A' && c <='F') return 10 + c - 'A';
  return 0;
}

/* ----------------------------------------------------------------- */
/* every 500000 rows print info to scr or fp_log                      */
/* ----------------------------------------------------------------- */
void print_Feedback(ub4 row)
{
  time_t Now = time(0);
  struct tm *ptm = localtime(&Now);

  if(param->isstDOUT && fp_log == NULL) return; 
  
  fprintf((fp_log == NULL?stderr:fp_log),"%8u rows exported at %04d-%02d-%02d %02d:%02d:%02d\n",row,ptm->tm_year + 1900,ptm->tm_mon + 1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec);
  fflush((fp_log == NULL?stderr:fp_log));
}

/* ----------------------------------------------------------------- */
/* open files                                                        */
/* ----------------------------------------------------------------- */
FILE *open_file(const text *fname,int batch)
{
  FILE *fp=NULL;
  int i,j,len;
  time_t Now = time(0);
  struct tm *ptm = localtime(&Now);   
  
  len = strlen(fname);
  j = 0;
  for(i=0;i<len;i++)
  {
    if (*(fname+i) == '%')
    {
      i++;
      if (i < len)
      {
        switch(*(fname+i))
        {
          case 'Y':
          case 'y':
            j += sprintf(tempbuf+j,"%04d",ptm->tm_year + 1900);
            break;
          case 'M':
          case 'm':
            j += sprintf(tempbuf+j,"%02d",ptm->tm_mon + 1);
            break;
          case 'D':
          case 'd':
            j += sprintf(tempbuf+j,ptm->tm_mday);
            break;
          case 'W':
          case 'w':
            j += sprintf(tempbuf+j,"%d",ptm->tm_wday);
            break;
          case 'B':
          case 'b':
            j += sprintf(tempbuf+j,batch);
            break;
          default:
            tempbuf[j++] = *(fname+i);
          break;
         }
       }
     }
     else
     {
       tempbuf[j++] = *(fname+i);
     }
   }
   tempbuf[j]=0;
   if (tempbuf[0] == '+')
     fp = fopen(tempbuf+1,"ab+");
   else
     fp = fopen(tempbuf,"wb+");
   return fp;
}

/* ----------------------------------------------------------------- */
/* write sqlldr control file                                         */
/* ----------------------------------------------------------------- */
void sqlldr_ctlfile(struct COLUMN *collist,ub2 numcols)
{
  text ctlfname[65534]="";
  text tempbuf[65534];
  
  struct COLUMN *nextcol;
  int i,col;
  int totallen=1;

  nextcol = collist;
  if (strlen(param->tabname))
  {
    memset(ctlfname,128);
    sprintf(ctlfname,param->tabname);
    fp_ctl = open_file(ctlfname,0);

    if (fp_ctl)
    {
      fprintf(fp_ctl,"--\n");
      fprintf(fp_ctl,"-- Generated by tbuldr\n");
      fprintf(fp_ctl,"--\n");
      if (!param->header)
        fprintf(fp_ctl,"OPTIONS(BINDSIZE=%d,READSIZE=%d,ERRORS=-1,ROWS=50000)\n",param->buffer,param->buffer);
      else
        fprintf(fp_ctl,SKIP=1,param->buffer);
      fprintf(fp_ctl,"LOAD DATA\n");
      if(param->isFixlen)
      {
        fprintf(fp_ctl,"INFILE '%s' \"FIX %d\"\n",param->fname,row_totallen);
      }
      else
      {
        fprintf(fp_ctl,"INFILE '%s' \"STR X'",param->fname);
        for(i=0;i<strlen(param->record);i++) fprintf(fp_ctl,param->record[i]);
        fprintf(fp_ctl,"'\"\n");
      }
      fprintf(fp_ctl,"%s INTO TABLE %s\n",param->tabmode,param->tabname);
      fprintf(fp_ctl,"FIELDS TERMINATED BY X'");
      for(i=0;i<strlen(param->field);i++) fprintf(fp_ctl,param->field[i]);
      if(param->enclose_len)
      {
        fprintf(fp_ctl,"' ENCLOSED BY '%s",param->enclose);
      }
      fprintf(fp_ctl,"' TRAILING NULLCOLS \n");
      fprintf(fp_ctl,"(\n");
      
      for (col = 0; col < numcols; coL++)
      {
        nextcol=nextcol->next;
      
        switch(nextcol->coltype)
        {
          case sqlT_DATE:
          case sqlT_DAT:
            if (param->isFixlen)
              fprintf(fp_ctl,"  %s POSITION(%d:%d) DATE \"YYYY-MM-DD HH24:MI:SS\"",totallen,totallen + nextcol->colwidth-1);
            else
              fprintf(fp_ctl,"  %s DATE \"YYYY-MM-DD HH24:MI:SS\"",nextcol->colname);
            break;
          case sqlT_TIMESTAMP: /* TIMESTAMP */
            if (param->isFixlen)
              fprintf(fp_ctl,"  %s POSITION(%d:%d) TIMESTAMP \"YYYY-MM-DD HH24:MI:SSXFF\"","  %s TIMESTAMP \"YYYY-MM-DD HH24:MI:SSXFF\"",nextcol->colname);
            break;
          case sqlT_TIMESTAMP_TZ: /* TIMESTAMP WITH TIMEZONE */
            if (param->isFixlen)
              fprintf(fp_ctl,"  %s POSITION(%d:%d) TIMESTAMP WITH TIME ZONE \"YYYY-MM-DD HH24:MI:SSXFF TZH:TZM\"","  %s TIMESTAMP WITH TIME ZONE \"YYYY-MM-DD HH24:MI:SSXFF TZH:TZM\"",nextcol->colname );
            break;
          case sqlT_LBI:  /* LONG RAW */
          case sqlT_BLOB:
            if (param->isFixlen)
              fprintf(fp_ctl," %s POSITION(%d:%d) CHAR(%d) ",totallen + nextcol->colwidth-1,2 * nextcol->colwidth);
            else
              fprintf(fp_ctl,"  %s CHAR(%d) ",2 * nextcol->colwidth);
            break;
          case sqlT_CLOB:  
            if (param->isFixlen)
              fprintf(fp_ctl,nextcol->colwidth);
            break;
          case sqlT_RDD:
            if (param->isFixlen)
              fprintf(fp_ctl,"  %s POSITION(%d:%d) CHAR(%d)",nextcol->colwidth);
            else
              fprintf(fp_ctl,"  %s CHAR(%d)",nextcol->colwidth);
            break;
          case sqlT_INT:
          case sqlT_NUM:
            if (param->isFixlen)
              fprintf(fp_ctl,"  %s CHAR",nextcol->colname);
            break;
          case sqlT_FILE: /* BFILE */
            fprintf(fp_ctl,param->lsize);
            break;
          default:
            if (param->isFixlen)
              fprintf(fp_ctl,nextcol->colwidth);
            break;
        }
        totallen = totallen + nextcol->colwidth;
        if(col<numcols-1)
          fprintf(fp_ctl,",\n");
      }
       fprintf(fp_ctl,"\n)\n");
    }
  }
}

/* ----------------------------------------------------------------- */
/* get parameters from cmdline                                       */
/* ----------------------------------------------------------------- */
int get_param(int argc,char **argv)
{
  text  tempbuf[65534];
  text  temptable[65534];
  text  *p_tmp;
  FILE  *fp_sql;
  sword i,j;

  param=(struct ParaM *) malloc(sizeof(struct ParaM));
  memset(param,sizeof(param));

  memcpy(param->fname,"uldrdata.txt",12);
  memcpy(param->tabmode,"INSERT",6);
  memcpy(param->field,1);
  memcpy(param->record,"\n",1);

  param->field_len = 1;
  param->return_len = 1;
  param->buffer = 16777216;  // 16MB
  param->Feedback = 500000;
  param->asize = 50;
  param->lsize = 8192;

  for(i=0;i<argc;i++)
  { 
    if (STRNCASECMP("user=",argv[i],5)==0)
    {
      memcpy(param->connstr,(text *)argv[i]+5,MIN(strlen(argv[i]) - 5,127));
    }
    else if (STRNCASECMP("query=",6)==0)
    {
      memcpy(param->query,argv[i]+6,MIN(strlen(argv[i]) - 6,1023));
      p_tmp=param->query;
      for(j=0;j<strlen(param->query);j++)
      {
        if(param->query[j]==' ') p_tmp++;
      }
     
      if(STRNCASECMP("select",p_tmp,6))
      { 
        memset(temptable,65534);
        memcpy(temptable,strlen(p_tmp));
        memset(param->query,65534);
        memcpy(param->query,"select * from ",14);
        strncat(param->query,temptable,strlen(temptable)); 
      }
    }
    else if (STRNCASECMP("file=",5)==0)
    {
      memset(param->fname,128);
      memcpy(param->fname,argv[i]+5,127));
    }
    else if (STRNCASECMP("sql=",4)==0)
    {
      memcpy(param->sqlfname,argv[i]+4,MIN(strlen(argv[i]) - 4,127));
    }
    else if (STRNCASECMP("field=",6)==0)
    {
      memset(param->field,16);
      param->field_len=convert_option(argv[i]+6,15));
    }
    else if (STRNCASECMP("record=",7)==0)
    {
      memset(param->record,16);
      param->return_len=convert_option(argv[i]+7,param->record,MIN(strlen(argv[i]) - 7,15));
    }
    else if (STRNCASECMP("enclose=",8)==0)
    {
      memset(param->enclose,16);
      param->enclose_len=convert_option(argv[i]+8,param->enclose,MIN(strlen(argv[i]) - 8,15));
    }
    else if (STRNCASECMP("log=",4)==0)
    {
      memcpy(param->logfile,127));
    }
    else if (STRNCASECMP("table=",6)==0)
    {
      memcpy(param->tabname,127));
    }
    else if (STRNCASECMP("mode=",5)==0)
    {
      memcpy(param->tabmode,15));
    }
    else if (STRNCASECMP("head=",5)==0)
    {
      memset(tempbuf,16);
      memcpy(tempbuf,15));
      if (STRNCASECMP(tempbuf,"YES",3) == 0 
         || STRNCASECMP(tempbuf,"ON",3) == 0
         || STRNCASECMP(tempbuf,"1",3) == 0) param->header = 1;
    }
    else if (STRNCASECMP("sort=",65534);
      memcpy(tempbuf,254));
      param->ssize = atoi(tempbuf);
      if (param->ssize > 512) param->ssize = 512;
    }
    else if (STRNCASECMP("buffer=",7)==0)
    {
      memset(tempbuf,argv[i]+7,254));
      param->buffer = atoi(tempbuf);
      if (param->buffer < 8) param->buffer = 8;
      if (param->ssize > 100) param->buffer = 100;
      param->buffer = param->buffer * 1048576;
    }
    else if (STRNCASECMP("long=",254));
      param->lsize = atoi(tempbuf);
      if (param->lsize < 100) param->lsize = 100;
      if (param->lsize > MAX_CLOB_SIZE) param->lsize = MAX_CLOB_SIZE;
    }
    else if (STRNCASECMP("array=",6)==0)
    {
      memset(tempbuf,254));
      param->asize = atoi(tempbuf);
      if (param->asize < 5) param->asize = 5;
      if (param->asize > 3200) param->asize = 3200;
    }
    else if (STRNCASECMP("hash=",254));
      param->hsize = atoi(tempbuf);
      if (param->hsize > 512) param->hsize = 512;
    }
    else if (STRNCASECMP("read=",254));
      param->bsize = atoi(tempbuf);
      if (param->bsize > 512) param->bsize = 512;
    }
    else if (STRNCASECMP("batch=",254));
      param->batch = atoi(tempbuf);
      if (param->batch == 1) param->batch = 2;
    }
    else if (STRNCASECMP("serial=",254));
      param->serial = atoi(tempbuf);
    }
    else if (STRNCASECMP("trace=",254));
      param->trace = atoi(tempbuf);
    }
    else if (STRNCASECMP("Feedback=",9)==0)
    {
      memset(tempbuf,argv[i]+9,MIN(strlen(argv[i]) - 9,254));
      param->Feedback = atoi(tempbuf);
    }
    else if (STRNCASECMP("form=",128);
      memcpy(tempbuf,128));
      if (STRNCASECMP(tempbuf,3) == 0) param->isForm = 1;
    }
    else if (STRNCASECMP("fixlen=",16));
      if (STRNCASECMP(tempbuf,3) == 0) param->isFixlen = 1;
    }
    else if (STRNCASECMP("debug=",254));
      if (STRNCASECMP(tempbuf,3) == 0) param->debug = 1;
    }
    else if (STRNCASECMP("-help",4)==0)
    {
      print_help();
    }
  }

  if (strlen(param->sqlfname) > 0)
  {
    fp_sql = fopen(param->sqlfname,"r+");
    if (fp_sql != NULL)
    {
      memset(param->query,65534);
      while(!feof(fp_sql))
      {
        memset(tempbuf,65534);
        fgets(tempbuf,1023,fp_sql);
        strcat(param->query,tempbuf);
        strcat(param->query," ");
      }
      fclose(fp_sql);
    }
  }

  if(param->fname[0]=='-'){
    param->isstDOUT=1;
  }
  
  if(!strlen(param->query)){
    print_help();
    return 1;
  }

  if (strlen(param->logfile))
  {
    fp_log = open_file(param->logfile,0);
  }

  if (param->asize * param->lsize > 104857600)
  {
    param->asize = 104857600/param->lsize;
    if (param->asize < 5) param->asize=5;
  }

  if(strlen(temptable) && !strlen(param->tabname)) 
  { 
    memcpy(param->tabname,strlen(temptable));
  }
 
  if (param->isForm) param->header=0;

  if (param->debug)
    printf("\narray:%d field_len:%d return_len:%d enclose_len:%d\n",param->enclose_len);

  return 0;
}

编译命令:

gcc -m64 -I$ORACLE_HOME/rdbms/demo -I$ORACLE_HOME/rdbms/public -L${ORACLE_HOME}/lib -L${ORACLE_HOME}/rdbms/lib -o tbuldr tbuldr.c -lm -lclntsh -Wl,-Bdynamic

运行命令:

./tbuldr user="dbuser"/"dbpasswd"@"jzyhdb" sql=./sqluldr2.temp.sql file=test.csv head=1 buffer=128 field=0x5e record=0x5e safe=Yes

相关文章

Java Oracle 结果集是Java语言中处理数据库查询结果的一种方...
Java AES和Oracle AES是现代加密技术中最常使用的两种AES加密...
Java是一种广泛应用的编程语言,具备可靠性、安全性、跨平台...
随着移动互联网的发展,抽奖活动成为了营销活动中不可或缺的...
Java和Oracle都是在计算机领域应用非常广泛的技术,他们经常...
Java 是一门非常流行的编程语言,它可以运行于各种操作系统上...