国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > Oracle > 正文

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

2024-08-29 13:38:14
字體:
來源:轉載
供稿:網友

  一、前言
  
  當前不少單位在進行系統改造升級時,面臨著如何將各個獨立部門開發的應用所采用的數據庫統一,以便適應數據大集中的需求,方便將來進行數據挖掘等更高層次的應用。 在數據庫統一的過程中,如何快速、高效的將已有的基于異種數據庫的程序,非凡是采用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
  {
  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 ;
  st

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新源县| 综艺| 青岛市| 万年县| 宁河县| 澎湖县| 沁源县| 西华县| 涞水县| 新化县| 贵州省| 囊谦县| 景宁| 青州市| 石阡县| 筠连县| 中方县| 铜山县| 五台县| 封丘县| 湖州市| 阿尔山市| 惠水县| 稷山县| 政和县| 斗六市| 苍梧县| 武乡县| 义乌市| 五莲县| 盐源县| 应用必备| 柘城县| 东乌| 岑巩县| 敦煌市| 神农架林区| 综艺| 定远县| 广西| 永泰县|