Chinaunix首页 | 论坛 | 博客
  • 博客访问: 465786
  • 博文数量: 724
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(724)

文章存档

2011年(1)

2008年(723)

我的朋友

分类:

2008-10-13 17:07:09

将Sybase C程序快速移植到Oracle Pro*C程序

作者:



一、前言

  当前不少单位在进行系统改造升级时,面临着如何将各个独立部门开发的应用所采用的数据库统一,以便适应数据大集中的需求,方便将来进行数据挖掘等更高层次的应用。在数据库统一的过程中,如何快速、高效的将已有的基于异种数据库的程序,特别是采用C/C++开发的运行于linux/unix下的程序转换到现有数据库下,成为不少单位面临的问题。当然了,基于RAD开发的程序,基本上不需要进行修改,就能达到目的。
  针对如何快速地将Sybase C程序移植为Oracle Pro*C程序,本文将指出一个方向,并给出一个粗糙的框架。仅以此文抛砖引玉,希望各位指导。(计划编写一个转换系列,看看各位反应如何吧)

二、原理

  Sybase的C程序转换到Oracle的Pro*C程序,相对于其他类型的转换有很多优势(原谅我挑了可能是最简单的一种转换):

  1. Sybase程序采用的是C函数调用的方式,这给将Sybase程序转换到其他任意一种数据库程序带来了很大的方便!仅仅需要使用目的数据库的语法,实现老程序使用到的Sybase函数就可以了!并且不需要对原来的C程序进行任何逻辑方面的修改!
  2. Oracle的Pro*C提供了动态sql的开发方式,这给移植带来了极大的方便。
  3. Oracle Pro*C与Sybase同样提供进程多连接方式。
  4. Oracle 9采用parse=full的编译选项时,C的定义变量可以直接在EXEC SQL中使用,这给程序的编写方便了不少。

还有其他优势,不再一一列举。

三、实现

废话少说,下面转入正题:
针对Sybase的几个主要函数,下面概述处理办法,具体的实现参照源代码:

  1. dbinit():该函数仅仅将针对数据库操作的一些变量进行初始化。
  2. 一些用户名、密码的设置,没有太多可说的。比较简单。
  3. dbopen():该函数实际进行数据库的连接,在连接过程中,我设置了全局变量AllOpenProcess用于保存所有的连接指针,并产生了一个连接串用于标识该连接。保存于全局变量中是因为Sybase函数dbexit没有输入参数。
  4. dbcmd():该函数进行sql语句的分析,以便进一步进行判断。
  5. dbexec():该函数进行命令的执行(不太清楚为什么Sybase将该函数与dbcmd分开)。对无返回结果集的命令(insert、update、delete)直接通过EXEC SQL AT EXECUTE IMMEDIATE的语法执行。对与存在返回结果集的select,采用oracle动态sql4的方法进行处理。因为时间以及老的程序的关系,本函数的实现仅仅针对了传入完整sql语句的字符串。
  6. dbresults():判断返回结果。
  7. dbbind():绑定存储值的地址,并判断传入的类型是否正确。因为老程序仅仅使用了NTBSTRINGBIND类型,所以示例中也仅仅处理了此种类型。
  8. dbnumcols():返回数据列数目,在语句类型为select时有效。
  9. dbnextrow():取得下一条数据值,并填写到dbbind所绑定的地址空间内。此处需要根据源类型select_dp->T[]以及目标类型进行相关的数据转换。
  10. dbdead():判断数据库连接是否正常。采用从DUAL表中取值的方式来测试。
  11. dbexit():退出数据库连接。

还有其他很多函数,但是因为我没有使用到,嘿嘿,就不作实现了。

四.移植

  移植的方法很简单,将原来c/c++文件中#include "Sybfront.h" #include "sybdb.h"等引用Sybase头文件的地方去掉,更换为附件中的#include "database_op.h",同时将附件中database_op.cxx加入到工程中,加上适当的编译语句(PROC),然后去除原来连接sybase的lib,加入oracle的lib:orasql9.lib。就可以在基本不修改源程序的情况下完成程序的移植!当然,如果你的sybase程序采用了非NTBSTRINGBIND类型的话,自己在cxx文件中加入相关的处理方式吧!祝好运!欢迎探讨。

五、技巧

  下面我总结一些开发过程中使用到的一些小的技巧,各位见笑。如何充分利用 Visual C++ 的开发环境进行 Pro*C 程序开发:

  相信各位对 Visual C++ 的集成开发环境使用比较熟吧,别告诉我你开发 Unix 下的 C/C++ 程序还在使用 vi、UltraEdit、EditPlus 吧!当然了,如果你坚持我也不反对,不过您老此时就不用浪费时间向下翻页了。
  oracle 的 Pro*C 程序一般以 PC 结尾。而以 PC 结尾的程序,没法按照 C/C++ 的语法在 Visual C++ 的集成开发环境下显示!只是白纸黑字一片。不像 UltraEdit,可以定制使得 PC 文件按照 C/C++ 的语法显示(在 UltraEdit 安装目录下的 WORDFILE.TXT 文件中包含 "C CPP CC CXX H HPP AWK" 内容的后面加上 "PC" 就可以了)(也许VC有这个功能,不过我没找到)。怎么办呢?简单,修改PC文件后缀为CXX,此时,文件就按照C/C++语法进行显示了!此时,设置该文件属性页(在VC开发环境的WORKSPACE中选中该文件,按 ALT+F7 )中 General 下的 Always use custom build step 为选中状态,Curstom Build 页下的 Commands/Outputs 下参考 oracle 的 example 输入相应的编译选项。记得将对应的PC后缀修改为 cxx 后缀。

database_op.cxx

/*
database_op.cxx  
负责兼容 sybase 和 oracle对数据库的操作
*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "database_op.h"
#ifdef SYBASE_PLATFORM
/*
*	不需要任何动作
*/
#endif
#ifdef MSSQL_PLATFORM
#endif
#ifdef ORACLE_PLATFORM
EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE sqlda;
EXEC SQL WHENEVER NOT FOUND CONTINUE ;
EXEC SQL WHENEVER SQLWARNING CONTINUE ;
EXEC SQL WHENEVER SQLERROR CONTINUE ;
char    dyn_statement[1024];
SQLDA *select_dp = NULL;
#define  MAXCOLNUM 126
#define  MAXCOLVALUE 1024
char chValueBuff[MAXCOLNUM][MAXCOLVALUE]={0};
/* Maximum lengths of the _names_ of the
select-list items or indicator variables. */
#define MAX_VNAME_LEN     80
#define MAX_INAME_LEN     80
typedef struct Securepair
{
	struct Securepair	*next;
	char		*labelname;
	char		*labelvalue;
} SECLABELS;
typedef struct loginrec
{
	char	chLogName[256];
	char	chLogPass[256];
} LOGINREC_STR;
enum SQLTYPE_ENUM{SQL_NULL=0,SQL_SELECT,SQL_INSERT,SQL_UPDATE,SQL_DELETE};
struct dbprocess {
	sql_context ctx;
	char connName[20];
	
   /*当前sql语句类型,包括查询select  insert update delete,*/
   /*通过在sqldata中查找上述字符串获得*/
	enum SQLTYPE_ENUM sqltype ;
	long	rowindex ;	/*执行本次sql后,被取出的行的数目/下次需要取出的索引*/
	long	rownum ;	/*本次sql得到的行数目*/
	long	colnum ;	/*当前列数目*/
	long	sqlerror ;/*SQL语句错误号*/
	void *	ppbuff[MAXPOINTNUM] ;	/*当前绑定了字段的内存地址*/
	long	pbufftype[MAXPOINTNUM] ;
         /*当前sql语句值,在执行后更改上面的rowindex,rownum,colnum*/
	char	sqldata[SQLDATALEN] ; 
};
typedef struct dbprocess    DBPROC_STR;
DBPROC_STR * AllOpenProcess[20]={0};
EHANDLEFUNC ehandfunc = 0 ;
MHANDLEFUNC mhandfunc = 0 ;
RETCODE dbinit		(void)
{
	int i ;
	if( select_dp ) return SUCCEED ;
    if ((select_dp =sqlald (MAXPOINTNUM, MAX_VNAME_LEN, MAX_INAME_LEN)) == (SQLDA *) 0)
    {
        fprintf(stderr,"Cannot allocate memory for select descriptor.");
        return FAIL;
    }
	
    select_dp->N = MAXPOINTNUM;
	
    /* Allocate the pointers to the indicator variables, and the
	actual data. */
    for (i = 0; i < MAXPOINTNUM; i++) {
        select_dp->I[i] = (short *) malloc(sizeof(short));
        select_dp->V[i] = (char *) malloc(1);
    }
	
	return SUCCEED;
}
void errhandlefunc()
{
	if( ehandfunc )
		(*ehandfunc)(0,0,0,0,"","") ;
}
void mhandlefunc()
{
	if( mhandfunc )
		(*mhandfunc)(0,0,0,0,"","","",0) ;
}
EHANDLEFUNC dberrhandle  (EHANDLEFUNC handler)
{
	ehandfunc  =  handler ;
	/*	EXEC SQL WHENEVER SQLERROR DO errhandlefunc() ;*/
	return 0 ;
}
MHANDLEFUNC dbmsghandle  (MHANDLEFUNC handler)
{
	mhandfunc = handler ;
	/*	EXEC SQL WHENEVER SQLWARNING DO mhandlefunc() ;***/
	return 0 ;
}
void *	dblogin (void)
{
	LOGINREC_STR * rec ;
	rec = (LOGINREC_STR*)malloc(sizeof(LOGINREC_STR)) ;
	if( NULL == rec ) return rec ;
	memset(rec,0,sizeof(LOGINREC_STR));
	return rec;
}
RETCODE dbsetlname  (LOGINREC_STR *lptr,char *values,int type)
{
	if( NULL == lptr || NULL == values ) return FAIL ;
	if( (DBSETUSER != type) &&(DBSETPWD != type) ) return FAIL ;
	if( DBSETUSER == type )
	{
		if( strlen(values) >= sizeof(lptr->chLogName) ) return FAIL ;
		strcpy( lptr->chLogName,values) ;
	}
	
	if( DBSETPWD == type )
	{
		if( strlen(values) >= sizeof(lptr->chLogPass) ) return FAIL ;
		strcpy( lptr->chLogPass,values) ;
	}
	return SUCCEED ;
}
/*
该函数内进行数据库连接尝试
*/
DBPROCESS *dbopen	(LOGINREC_STR *logon_ptr,char *servername)
{
	int iLen ,iIndex ;
	DBPROC_STR * dbprocess ;
	EXEC SQL BEGIN DECLARE SECTION;
	VARCHAR  username[256];
	VARCHAR  password[256];
	VARCHAR	 dbstring[256];
    EXEC SQL END DECLARE SECTION;
	
	if( NULL == logon_ptr ) return NULL ;
	dbprocess = (DBPROC_STR*)malloc(sizeof(DBPROC_STR));
	if( NULL == dbprocess ) return NULL ;
	memset(dbprocess,0,sizeof(DBPROC_STR));
	iLen = sizeof(AllOpenProcess)/sizeof(DBPROC_STR * );
	
	for ( iIndex = 0 ; iIndex < iLen ; iIndex ++ )
	{
		if( NULL == AllOpenProcess[iIndex] ) 
		{
			AllOpenProcess[iIndex] = dbprocess ;
			sprintf(dbprocess->connName,"conn%d",iIndex);
			break ;
		}
	}
	
	if( iIndex == iLen ) 
	{
		free(dbprocess) ;
		dbprocess  = NULL ;
	}
	/*
	此处进行连接尝试!!!!!!!!!
	*/
	strncpy((char *) username.arr, logon_ptr->chLogName, sizeof(username.arr));
	username.len = strlen((char *) username.arr);
	strncpy((char *) password.arr, logon_ptr->chLogPass, sizeof(password.arr));
	password.len = strlen((char *) password.arr);
    EXEC SQL CONTEXT ALLOCATE :dbprocess->ctx;
    EXEC SQL CONTEXT USE :dbprocess->ctx;
	if( NULL == servername )
	{
		EXEC SQL CONNECT :username IDENTIFIED BY :password AT:dbprocess->connName ;
	}
	else
	{
		strncpy((char*)dbstring.arr,servername,sizeof(dbstring.arr) ) ;
		dbstring.len = strlen((char*)dbstring.arr);
		EXEC SQL CONNECT :username IDENTIFIED BY 
		                 :password  
		                 AT:dbprocess->connName 
		                 USING :dbstring ;
	}
	
	if (sqlca.sqlcode < 0 ) 
	{
		printf("\n%d %s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
		printf("CONNECT ERROR!");		
		return FAIL ;
	}
	return (DBPROCESS*)dbprocess ;
}
void	dbloginfree (LOGINREC_STR *loginptr)
{
	if( NULL != loginptr ) 
	{
		memset( loginptr,0,sizeof(LOGINREC_STR));
		free(loginptr) ;
	}
}
/*
该函数仅仅拷贝命令,做简单的命令检查
*/
RETCODE dbcmd		(DBPROC_STR *dbproc,const char *cmdstring)
{
	long l_len ;
	char * pSelect , *pInsert , *pUpdate,*pDelete ,*pMin;
	if( NULL == dbproc || NULL == cmdstring ) return FAIL ;
	/*
	仅仅拷贝命令,做简单的命令检查!!!!!!!!!!!!!!!!!!!!!
	*/
	l_len = strlen(cmdstring) ;
	if(	l_len >= sizeof(dbproc->sqldata) )  return FAIL ;
	memcpy( dbproc->sqldata, cmdstring , l_len + 1) ;
	strupr(dbproc->sqldata);
	dbproc->colnum  =0 ;
	dbproc->rowindex = 0 ;
	dbproc->rownum = 0 ;
	memset(dbproc->ppbuff,0,sizeof(dbproc->ppbuff));
	memset(dbproc->pbufftype,0,sizeof(dbproc->pbufftype));
	
	/*分析命令类型*/	
	pSelect = strstr(dbproc->sqldata,"SELECT");
	pInsert = strstr(dbproc->sqldata,"INSERT");
	pUpdate = strstr(dbproc->sqldata,"UPDATE");
	pDelete = strstr(dbproc->sqldata,"DELETE");
	
	pMin = dbproc->sqldata + strlen(dbproc->sqldata) ;
	dbproc->sqltype = SQL_NULL ;
	if( (pSelect) && (pSelect < pMin) ) { pMin = pSelect ;dbproc->sqltype = SQL_SELECT ; }
	if( (pInsert) && (pInsert < pMin) ) { pMin = pInsert ;dbproc->sqltype = SQL_INSERT ; }
	if( (pUpdate) && (pUpdate < pMin) ) { pMin = pUpdate ;dbproc->sqltype = SQL_UPDATE ; }
	if( (pDelete) && (pDelete < pMin) ) { pMin = pDelete ;dbproc->sqltype = SQL_DELETE ; }
	if( SQL_NULL == dbproc->sqltype ) 
	{
		dbproc->sqlerror = -1 ;
		return FAIL ;
	}
	return SUCCEED ;
}
/*
该函数	执行命令
*/
RETCODE dbsqlexec	(DBPROC_STR *dbproc)
{
	int i,null_ok, precision, scale;
	EXEC SQL BEGIN DECLARE SECTION;
	VARCHAR  chSqlStr[SQLDATALEN];
    EXEC SQL END DECLARE SECTION;
	if( NULL == dbproc ) return FAIL ;
	
	if( SQL_NULL == dbproc->sqltype ) return FAIL ;
	
	dbproc->colnum = 0 ;
	dbproc->rowindex = 0 ;
	dbproc->rownum = 0 ;
	dbproc->sqlerror = 0 ;
	memset( dbproc->ppbuff,0,sizeof(dbproc->ppbuff) );
	memset(dbproc->pbufftype,0,sizeof(dbproc->pbufftype));
	strcpy(chSqlStr.arr,dbproc->sqldata);
	chSqlStr.len = strlen(chSqlStr.arr);
	
	if( SQL_INSERT == dbproc->sqltype ||
		SQL_UPDATE == dbproc->sqltype ||
		SQL_DELETE == dbproc->sqltype 
		)
	{
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName execute immediate :chSqlStr ;
		dbproc->sqlerror = sqlca.sqlcode ;
		if( dbproc->sqlerror < 0 )
		{
			printf("\n%s\n",sqlca.sqlerrm.sqlerrmc);
			EXEC SQL ROLLBACK ;
			return FAIL ;
		}
		dbproc->rownum =  sqlca.sqlerrd[2]  ;
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName COMMIT ;
		return SUCCEED ;
	}
	
	
	/*采用CURSOR游标方式*/
	/*
	采用动态sql 4 方法
	*/
	if( SQL_SELECT == dbproc->sqltype )
	{
		sqlca.sqlcode = 0 ;
		if (sqlca.sqlcode != 0 ) 
		{
			printf("\nDECLARE  err = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			return FAIL ;
		}
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName  PREPARE SSS FROM :chSqlStr;
		
		if (sqlca.sqlcode != 0 ) 
		{
			printf("\nPREPARE err = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			return FAIL ;
		}
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName  DECLARE CCC CURSOR FOR SSS;
		if (sqlca.sqlcode != 0 ) 
		{
			printf("\nDECLARE CCC err = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			return FAIL ;
		}
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName  OPEN CCC ; 
		if (sqlca.sqlcode != 0 ) 
		{
			printf("\nOPEN CCC err = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			return FAIL ;
		}
		select_dp->N = MAXPOINTNUM;
		EXEC SQL CONTEXT USE :dbproc->ctx;
		EXEC SQL AT :dbproc->connName  DESCRIBE SELECT LIST FOR SSS INTO select_dp;
		
		dbproc->sqlerror = sqlca.sqlcode ;
		
		if( dbproc->sqlerror < 0 )
		{
			printf("\nerr = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  CLOSE CCC ;
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  ROLLBACK ;
			return FAIL ;
		}
		if (select_dp->F < 0 )
		{
			printf("\nerr = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  CLOSE CCC ;
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  ROLLBACK ;	
			return FAIL ;
		}
		if (select_dp->F > MAXPOINTNUM )
		{
			printf("\nerr = %d\n%s\n",
			sqlca.sqlcode , 
			sqlca.sqlerrm.sqlerrmc);
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  CLOSE CCC ;
			EXEC SQL CONTEXT USE :dbproc->ctx;
			EXEC SQL AT :dbproc->connName  ROLLBACK ;	
			return FAIL ;
		}
		
		select_dp->N = select_dp->F;
		
		dbproc->colnum = select_dp->N ;
		/*不能直接取到所有行的数目,所以直接采用当前行加1的方式处理*/
		dbproc->rownum =  dbproc->rowindex + 1 ;
		for (i = 0; i < select_dp->F; i++)
		{
			/*char title[MAX_VNAME_LEN]; */
			/* Turn off high-order bit of datatype (in this example, it does not */
			/* matter if the column is NOT NULL). */
			sqlnul ((unsigned short *)&(select_dp->T[i]), 
			(unsigned short *)&(select_dp->T[i]), 
			&null_ok);
			/*
			VARCHAR2 1 char[n]
			NUMBER 2 char[n] ( n <= 22)
			INTEGER 3 int
			FLOAT 4 float
			STRING 5 char[n+1]
			VARNUM 6 char[n] (n <= 22)
			DECIMAL 7 float
			LONG 8 char[n]
			VARCHAR 9 char[n+2]
			ROWID 11 char[n]
			DATE 12 char[n]
			VARRAW 15 char[n]
			RAW 23 unsigned char[n]
			LONG RAW 24 unsigned char[n]
			UNSIGNED 68 unsigned int
			DISPLAY 91 char[n]
			LONG VARCHAR 94 char[n+4]
			LONG VARRAW 95 unsigned char[n+4]
			CHAR 96 char[n]
			CHARF 96 char[n]
			CHARZ 97 char[n+1]			
			*/
			switch (select_dp->T[i])
			{
			/* CHAR datatype: no change in length needed, except */
			/* possibly for TO_CHAR conversions (not handled here). */
			case  1 : 
				break;
                           /* NUMBER datatype: use sqlprc() to extract precision and scale. */
			case  2 : 
				sqlprc ((unsigned long *)&(select_dp->L[i]), 
                                             &precision, &scale);
				/* Allow for maximum size of NUMBER. */
				if (precision == 0) precision = 40;
				/* Also allow for decimal point and possible sign. */
				/* convert NUMBER datatype to FLOAT if scale > 0,*/
                                    /* INT otherwise. */
				if (scale > 0)	select_dp->L[i] = sizeof(float);
				else	select_dp->L[i] = sizeof(int);
				break;
			case  8 : /* LONG datatype */
				select_dp->L[i] = 240;
				break;
			case 11 : /* ROWID datatype */
			case 104 : /* Universal ROWID datatype */
				select_dp->L[i] = 18;
				break;
			case 12 : /* DATE datatype */
				select_dp->L[i] = 9;
				break;
			case 23 : /* RAW datatype */
				break;
			case 24 : /* LONG RAW datatype */
				select_dp->L[i] = 240;
				break;
			}
			/* Allocate space for the select-list data values.sqlald() */
			/* reserves a pointer location for V[i] but does not allocate */
			/* the full space for the pointer.  */
			if (select_dp->T[i] != 2)
			{
				select_dp->V[i] = (char *) realloc(select_dp->V[i],
					select_dp->L[i] + 1);  
			}
			else
				select_dp->V[i] = (char *) realloc(select_dp->V[i],
				select_dp->L[i]);  
			/* Print column headings, right-justifying number column headings. */
			
			/* Copy to temporary buffer in case name is null-terminated */
			/* strncpy(title, select_dp->S[i], select_dp->C[i]);
			if (select_dp->T[i] == 2)
			if (scale > 0)
			printf ("%.*s ", select_dp->L[i]+3, title);
			else
			printf ("%.*s ", select_dp->L[i], title);
			else
			printf("%-.*s ", select_dp->L[i], title);
			*/
			/* Coerce ALL datatypes except for LONG RAW and NUMBER to character. */
			if (select_dp->T[i] != 24 && select_dp->T[i] != 2)
			     select_dp->T[i] = 1;
			/* Coerce the datatypes of NUMBERs to float or int */
			/* depending on the scale. */
			if (select_dp->T[i] == 2)
			{
				if (scale > 0)
					select_dp->T[i] = 4;  /* float */
				else
					select_dp->T[i] = 3;  /* int */
			}
		}
	}
	
	return SUCCEED ;
}
/*
该函数判断数据库返回结果,操作DBPROC_STR的特定字段
SUCCEED  NO_MORE_RESULTS
*/
RETCODE dbresults	(DBPROC_STR *dbproc)
{
	if( NULL == dbproc ) return NO_MORE_RESULTS;
	
	if( dbproc->sqlerror < 0 ) return NO_MORE_RESULTS ;
	if( dbproc->rowindex != dbproc->rownum ) return SUCCEED ;
	return NO_MORE_RESULTS ;
}
/*
绑定值,绑定存储值的位子
*/
RETCODE dbbind		(DBPROC_STR *dbproc,int colnum,int vartype,DBINT varlen,BYTE *destvar)
{
	if( colnum <= 0 ) return FAIL ;
	if( colnum > dbproc->colnum ) return FAIL ;
	if( colnum >= MAXPOINTNUM ) return FAIL ;
	
	/*
	当前仅支持此类型
	*/
	if( NTBSTRINGBIND != vartype )
	{
		printf("\n!!!!!!!!!!!!!UNKNOWN TYPE  %d  !!!!!!!!\n\n",vartype);
		exit(0);/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   */
	}
	dbproc->ppbuff[colnum - 1 ]	= destvar ;
	dbproc->pbufftype[colnum - 1 ] = vartype ;
	
	return FAIL ;
}
/*
获得本次执行返回多少列
*/
int dbnumcols		(DBPROC_STR *dbproc)
{
	return dbproc->colnum ;
}
/*
将下一条值赋值到绑定的变量上
*/
STATUS dbnextrow	(DBPROC_STR *dbprocess)
{
	int i ;
	if( NULL == dbprocess ) return NO_MORE_ROWS ;
	/* FETCH each row selected and print the column values. */
	EXEC SQL CONTEXT USE :dbprocess->ctx;
	EXEC SQL WHENEVER NOT FOUND GOTO end_select_loop;
	
	EXEC SQL CONTEXT USE :dbprocess->ctx;
	EXEC SQL AT :dbprocess->connName  FETCH CCC USING DESCRIPTOR select_dp;
	
	/* Since each variable returned has been coerced to a character string, */
	/* int, or float very little processing is required here.  This routine */
	/* just prints out the values on the terminal. */
	for (i = 0; i < select_dp->F; i++)
	{
		if( NULL == dbprocess->ppbuff[i] ) continue ;
		if (*select_dp->I[i] < 0)
		{
			switch(dbprocess->pbufftype[i]) 
			{
			case NTBSTRINGBIND :
			/*
			if (select_dp->T[i] == 4) 
			sprintf ("%-*c ",(int)select_dp->L[i]+3, '' '');
			else
			printf ("%-*c ",(int)select_dp->L[i], '' '');
				*/
				strcpy(dbprocess->ppbuff[i],"");
				break;
			case CHARBIND:
				*((char*)dbprocess->ppbuff[i]) = 0 ;
				break ;
				
			case INTBIND:
				*((int*)dbprocess->ppbuff[i]) = 0 ;
				break ;
				
			default:
			/*
			*	ERROR ! not support type!
				*/
				dbprocess->sqlerror = -50001;
				return NO_MORE_ROWS ;
			}
		}
		else
		{
			switch(dbprocess->pbufftype[i]) 
			{
			case NTBSTRINGBIND :
				if (select_dp->T[i] == 3)     /* int datatype */
					sprintf (dbprocess->ppbuff[i],
					"%*d", (int)select_dp->L[i],
					*(int *)select_dp->V[i]);
				else if (select_dp->T[i] == 4)     /* float datatype */
					sprintf (dbprocess->ppbuff[i],
					"%*.2f", (int)select_dp->L[i],
					*(float *)select_dp->V[i]);
				else                          /* character string */
					sprintf (dbprocess->ppbuff[i],
					"%-*.*s", 
					(int)select_dp->L[i],
					(int)select_dp->L[i],
					select_dp->V[i]);
				break;
			case CHARBIND:
				*((char*)dbprocess->ppbuff[i]) = *(char*) select_dp->V[i] ;
				break ;
				
			case INTBIND:
				*((int*)dbprocess->ppbuff[i]) = *(int*) select_dp->V[i] ;
				break ;
				
			default:
			/*
			*	ERROR ! not support type!
				*/
				dbprocess->sqlerror = -50001;
				return NO_MORE_ROWS ;
			}
		}
	}
	return SUCCEED ;
	
end_select_loop :
	dbprocess->rownum = dbprocess->rowindex ;
	
	return NO_MORE_ROWS ;
}
/*
判断该连接是否正常
*/
DBBOOL	dbdead		(DBPROC_STR *a)
{
	char chbuff[8];	
	
	chbuff[0]=''\0'';
	EXEC SQL WHENEVER NOT FOUND GOTO end_select_loop;
	EXEC SQL CONTEXT USE :a->ctx;
	EXEC SQL AT :a->connName SELECT ''A'' INTO :chbuff FROM DUAL ;
	
	if (''A'' != chbuff[0]) 
	{
		return FAIL ;
	}
	return SUCCEED ;
end_select_loop:
	return FAIL ;
}
/*
该函数释放dbopen产生的内存,同时断开数据库连接
需要进一步的考虑!
*/
void dbexit			(void)
{
	int i,iLen ,iIndex ;
    EXEC SQL WHENEVER SQLERROR CONTINUE;
	
	iLen = sizeof(AllOpenProcess)/sizeof(DBPROC_STR * );
	
	for ( iIndex = 0 ; iIndex < iLen ; iIndex ++ )
	{
		if( NULL != AllOpenProcess[iIndex] ) 
		{
		/*
		*	此处开始断开数据库连接!!!!!!!!!!!!!!
			*/
			EXEC SQL CONTEXT USE : AllOpenProcess[iIndex]->ctx;
			EXEC SQL WHENEVER NOT FOUND GOTO end_select_loop;
			
			/* Close the cursor. */
			EXEC SQL AT :AllOpenProcess[iIndex]->connName CLOSE CCC;
			
			EXEC SQL AT :AllOpenProcess[iIndex]->connName COMMIT WORK RELEASE;
			
			free(AllOpenProcess[iIndex]);
			AllOpenProcess[iIndex] = NULL ;
		}
	}
	if( select_dp )
	{
		for (i = 0; i < MAXPOINTNUM; i++)
		{    
			if (select_dp->V[i] != (char *) 0)
				free(select_dp->V[i]);
			free(select_dp->I[i]); /* MAXPOINTNUM were allocated. */
		}
		
		/* Free space used by the descriptors themselves. */
		sqlclu(select_dp);
		select_dp = NULL ;
	}
	return;
}
#endif
#ifdef MSSQL_PLATFORM
#endif 
 


--------------------next---------------------

阅读(165) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~