tbuldr
NinGoo's blog

使用zlib输出gzip格式的文件

zlib是一个比较通用的压缩库,通过在程序中引入zlib,可以方便的对数据进行压缩。今天花了点时间研究了一下,在tbuldr中实现了直接将数据库中的数据导出为gzip文件的功能。

下载zlib源代码,对于Linux,可以编译成静态库,然后将zlib.h,libz.a(如有必要,再加上zonf.h)和程序代码放置到同一个目录,编译的时候包含libz.a即可。

#./configure
#make
#make install

如果要编译成动态库,则只需要第一步改成./configure -s即可。

废话少说,下面是一段演示代码,非常简单:

#include <stdio.h>
#include "zlib.h"

int main()
{
  char *data = "this is a gzip test from NinGoo.net";
  gzFile *fp=NULL;
  fp=gzopen("test_out.gz","wb");
  gzwrite(fp,data,strlen(data));
  gzclose(fp);
}

编译:

gcc -o test test.c libz.a

执行:

$./test
$gzip -d test_out.gz
$more test_out
this is a gzip test from NinGoo.net

tbuldr中,只需要在file参数指定的文件名后面加上.gz,就会自动输出为gzip格式的文件。至此,tbuldr已基本实现了sqluldr2的全部功能,性能测试结果也不相上下了。

另外,zlib也可以在内存中对数据进行压缩和解压缩,参考:
http://hispider.googlecode.com/svn/trunk/devel/hispider/src/utils/zstream.c

学习oci编程,从ociuldr开始

Update:发现原来在linux上写的代码,到windows上编译会有些错误,主要是编译器对变量声明的位置容忍度不一样,已经修正了代码。另外对输出的日志做了一点增强,打印了导出的总时间,省得人工计算了。并将源代码,windows32位版本,linux32位版,及linux64版本一并打包提供下载测试。

一直想学学oci编程,无奈基础不好,几次都是看了几页文档就放下了。所以比较佩服老楼,写了很多优秀的工具,例如广泛使用的ociuldr,以及为很多人解决了难题的AUL等。最近老楼焕发第二春,对ociuldr做了大量改进,并且升级成了sqluldr2,刚刚获得的最新消息是,sqluldr2开始支持gzip压缩格式了,牛人就是牛。

上周六一大早跑到公司,处理完一点小事后,想想反正来了,就多呆会儿吧。干什么呢?溜达到老楼的blog上,看到一对sqluldr的信息,就花了一上午的时间研究了下老版的ociuldr的源代码,再参考hrb_qiuyb写的oci8版的ociuldr2,这次终于能看明白了,还是oci8的函数比较容易懂,于是就开始自己动手编译。hrb_qiuyb版的bug比较多,动不动就segment fault,想了想不如多花点时间,好好的重新改写一下,虽然老楼已经出了sqludr2,珠玉在前,不过最近流行山寨,他做企业版,我来做山寨版,哈哈。山寨版的名字,就叫tbuldr(ToolBox*UnLoader),因为是基于老楼开放出来的源代码弄的,那就继续开源吧,希望不要抢了sqluldr2的生意哈。

到今天为止,代码终于差不多稳定了,修复了几个主要的bug,同时把sqluldr2最新的一些特性也用山寨的方法实现了,可能效率不如老楼的,不过至少外观上看是差不多了,如输出到stdout新版本的sqlldr控制文件固定长度导出指定表名导出按列输出等功能一一实现了。

另外还实现了一些小的功能:

  • feedback参数,指定输出多少行以后打印一条日志,可以更好的观察进度,默认还是50w条。
  • enclose参数,为每列加入包含字符。当选择的field字符在列值中有出现的时候,enclose就有作用了。
  • fixlen参数,表示固定长度输出。而不是像sqluldr2一样当field指定为0×20(空格)的时候采用固定长度。这个主要是考虑到某些非常特殊的情况下,可能会有人希望用空格做分隔符而又不希望是固定长度的。
  • 还有个隐含的debug参数,打开后会输出一些debug信息,主要array fetch时为各列分配的内存等数据。这个主要是dw用了老楼很早以前的一个debug版本,觉得log里输出了列名还挺有用,就保留了,不过默认是不显示的,也没有写在help里,这里偷偷的透露一下了,哈哈
$tbuldr

----------------------------------------------------------------------------
- tbuldr: Release 2.21 (ociuldr)
- First issued by Lou Fangxin (@) Copyright 2004/2008, all rights reserved.
- Modified by Ning Haiyuan (http://www.NinGoo.net).
----------------------------------------------------------------------------
 Usage: TBULDR keyword=value [,keyword=value,...]
 Valid Keywords:
       user     = username/password@tnsname
       query    = select statement, can simply speicify a table name
       sql      = SQL file name
       field    = seperator string between fields
       record   = seperator string between records
       enclose  = fields enclose string
       file     = output file name, default: uldrdata.txt
       head     = print row header(Yes|No,ON|OFF,1|0)
       read     = set DB_FILE_MULTIBLOCK_READ_COUNT at session level
       sort     = set SORT_AREA_SIZE at session level (UNIT:MB)
       hash     = set HASH_AREA_SIZE at session level (UNIT:MB)
       serial   = set _serial_direct_read to TRUE if 1 at session level
       trace    = set event 10046 to given level at session level
       table    = table name in the sqlldr control file
       mode     = sqlldr option, INSERT or APPEND or REPLACE or TRUNCATE
       log      = log file name, prefix with + to append mode
       long     = maximum long field size, default 8192 max 65534
       array    = array fetch size, default 50
       buffer   = sqlldr READSIZE and BINDSIZE, default 16 (MB)
       feedback = display progress every x rows, default 500000
       form     = display rows as form (Yes|No)
       fixlen   = fix length format (Yes|No)

  for field, record and enclose, use '0x' to specify hex character code
  r=0x0d n=0x0a |=0x7c ,=0x2c t=0x09  (more: man ascii)
$tbuldr user=test/test query=t
       0 rows exported at 2009-04-16 20:43:53
    400 rows exported at 2009-04-16 20:43:54
         output file uldrdata.txt closed at 4 rows. Elapsed time: 0 min 1 sec.
         control file is t_sqlldr.ctl.

当然,山寨版就是山寨版,以下sqluldr2的新功能暂未实现:

  • parfile,这个是比较有用功能,可以防止命令行中显式输入密码导致密码泄漏等。因为涉及到文件内容解析,对我来说,难度有点高,以后再说。
  • gzip压缩,这是下午老楼刚刚加入的新特性,还有待研究。不过这是利用了zlib实现的,网上有不少现成的代码,集成进来应当是能搞定的。另外也可以输出到stdout后通过管道调用gzip实现压缩,这个已经支持了。
  • BLOB/BFILE等不提供支持,虽然BLOB可以按照LONG RAW的方式导出成16进制字符,不过不保证没问题,如果BLOB里存储的是字符应当问题不大。CLOB/LONG最大只支持到65534字节,对于大部分情况应当是足够了。

第一次用c和oci正儿八经的写东西,bug肯定一大堆。山寨有风险,慎用,如果是生产环境有需求的,建议还是找老楼的企业版,支持山寨版的同学,可以自行编译帮忙做测试,有bug和建议欢迎提交^_^