分享
 
 
 

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

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

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

作者:徐小锋

下载源代码

一、前言

当前不少单位在进行系统改造升级时,面临着如何将各个独立部门开发的应用所采用的数据库统一,以便适应数据大集中的需求,方便将来进行数据挖掘等更高层次的应用。在数据库统一的过程中,如何快速、高效的将已有的基于异种数据库的程序,特别是采用C/C++开发的运行于linux/unix下的程序转换到现有数据库下,成为不少单位面临的问题。当然了,基于RAD开发的程序,基本上不需要进行修改,就能达到目的。

针对如何快速地将Sybase C程序移植为Oracle

Pro*C程序,本文将指出一个方向,并给出一个粗糙的框架。仅以此文抛砖引玉,希望各位指导。(计划编写一个转换系列,看看各位反应如何吧)

二、原理

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

Sybase程序采用的是C函数调用的方式,这给将Sybase程序转换到其他任意一种数据库程序带来了很大的方便!仅仅需要使用目的数据库的语法,实现老程序使用到的Sybase函数就可以了!并且不需要对原来的C程序进行任何逻辑方面的修改!

Oracle的Pro*C提供了动态sql的开发方式,这给移植带来了极大的方便。

Oracle Pro*C与Sybase同样提供进程多连接方式。

Oracle 9采用parse=full的编译选项时,C的定义变量可以直接在EXEC SQL中使用,这给程序的编写方便了不少。

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

三、实现

废话少说,下面转入正题:

针对Sybase的几个主要函数,下面概述处理办法,具体的实现参照源代码:

dbinit():该函数仅仅将针对数据库操作的一些变量进行初始化。

一些用户名、密码的设置,没有太多可说的。比较简单。

dbopen():该函数实际进行数据库的连接,在连接过程中,我设置了全局变量AllOpenProcess用于保存所有的连接指针,并产生了一个连接串用于标识该连接。保存于全局变量中是因为Sybase函数dbexit没有输入参数。

dbcmd():该函数进行sql语句的分析,以便进一步进行判断。

dbexec():该函数进行命令的执行(不太清楚为什么Sybase将该函数与dbcmd分开)。对无返回结果集的命令(insert、update、delete)直接通过EXEC

SQL AT EXECUTE

IMMEDIATE的语法执行。对与存在返回结果集的select,采用oracle动态sql4的方法进行处理。因为时间以及老的程序的关系,本函数的实现仅仅针对了传入完整sql语句的字符串。

dbresults():判断返回结果。

dbbind():绑定存储值的地址,并判断传入的类型是否正确。因为老程序仅仅使用了NTBSTRINGBIND类型,所以示例中也仅仅处理了此种类型。

dbnumcols():返回数据列数目,在语句类型为select时有效。

dbnextrow():取得下一条数据值,并填写到dbbind所绑定的地址空间内。此处需要根据源类型select_dp->T[]以及目标类型进行相关的数据转换。

dbdead():判断数据库连接是否正常。采用从DUAL表中取值的方式来测试。

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

{

charchLogName[256];

charchLogPass[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 ;

longrowindex ;/*执行本次sql后,被取出的行的数目/下次需要取出的索引*/

longrownum ;/*本次sql得到的行数目*/

longcolnum ;/*当前列数目*/

longsqlerror ;/*SQL语句错误号*/

void *ppbuff[MAXPOINTNUM] ;/*当前绑定了字段的内存地址*/

longpbufftype[MAXPOINTNUM] ;

/*当前sql语句值,在执行后更改上面的rowindex,rownum,colnum*/

charsqldata[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 ;

}

voiddbloginfree (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);

elseselect_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 ;

}

/*

判断该连接是否正常

*/

DBBOOLdbdead(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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有