📄 ifmxdb.c
字号:
/* ifmxdb.c - Informix SQLweb Interface/*/* Copyright (c) 1995-1999 Applied Information Technologies, Inc./* All Rights Reserved./* /* Distributed uder the GNU General Public License which was included in/* the file named "LICENSE" in the package that you recieved./* If not, write to:/* The Free Software Foundation, Inc.,/* 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <ctype.h>#include <string.h>#include <malloc.h>#include "sqlweb.h"/*/* Informix INCLUDES. */#include "infxcli.h"/*/* The DBINFO struct. */typedef struct { long ind; /* Indicator Variable BIND & SELECT */ SDWORD rlen; /* Bind/Fetch Return Length */ char *pValue; /* Another pointer to the SYMBOL Value */ long iLen; /* Symbol pValue's (Malloced) Length */ SWORD iScale; /* Scale of Number ... */ SWORD iColType; /* Type of Number ... */} DbInfo_t;/*/* Internal/Private Functions */static eBoolean_t DescribeBindVars (SQLWEB_CURSOR *pCursor);static eBoolean_t DescribeSelectVars(SQLWEB_CURSOR *pCDA);static eBoolean_t GetCursorIndex(int *piCursorIndex);static void PushDBErr(HENV pLDA,HSTMT pCDA,char *pErrMsg);static eBoolean_t SetDbNulls(DbInfo_t *pDbInfo);static DbInfo_t * NewDbInfo();static eBoolean_t FreeDbInfo(DbInfo_t *pDbInfo);static eBoolean_t PrepareParameters(SQLWEB_CURSOR *pCursor);static eBoolean_t FreeStmt(SQLWEB_CURSOR *pCursor);#define MAX_ITEM_BUFFER_SIZE 33#define MAX_SQL_IDENTIFIER 31/*/* Global Variables */char *gpIfExpr = "SELECT 1 SQLWEB_IF_EXPR FROM DUAL WHERE" ,*gpNullSelect = "SELECT 1 FROM DUAL WHERE 1=2" ;static LIST *glDbInfoList=NULL_LIST;/*/* THE LDA Array.... */HENV gaLDA[MAX_CONNECTIONS]; /* Lda_Def gaLDA[MAX_CONNECTIONS]; */HDBC gaHDA[MAX_CONNECTIONS]; /* ub1 gaHDA[MAX_CONNECTIONS][512]; *//*/* THE CURSOR Array */HSTMT gaCDA[MAX_CURSORS]; /* Cda_Def gaCDA[MAX_CURSORS]; */eBoolean_t gbaOpen[MAX_CURSORS]; /* Open indicator *//*/* MAIN for testing only#define MAIN_TEST */#ifdef MAIN_TESTeBoolean_t gbCookFlag;main(){ char sBuf[BUFSIZ]; FRMSym("name","steve"); FRMSym("nameb","so"); FRMSym("V2PGN","55"); (void)x(); while( MsgPop(sBuf) ) { printf("%s\n",sBuf); }}int x(){ SQLWEB_LDA lda; SQLWEB_CURSOR cda; char *p1 = "SELECT \n\ pi.pi_level \n\ ,pi.page_gen_nbr pgn \n\ ,nvl(pi.pi_seq_nbr,'0') pi_seq_nbr \n\ ,pi.pi_gen_nbr \n\ ,pi.tag_name \n\ ,nvl(pi.page_gen_nbr_link,'') page_gen_nbr_link \n\ ,pi.pi_contents \n\ FROM html_V_page_items pi \n\ WHERE pi.page_gen_nbr = :V2PGN "; char *pSql1 = "select to_char(sysdate,'mm/dd/yyyy hh24:mi') da_dat \n\ ,t.*\n\ from html_pages t\n\ where :name='steve' and :nameb='so'"; char *pDaDat, *pPageName, *pPageTitle; RETeFalse(DbConnect("sqlweb/sqlweb",&lda),"Connect Failed"); RETeFalse(DbOpenCursor(&lda,p1,&cda),"Open Failed"); GetSymbolValueREF("PI_CONTENTS",&pDaDat); GetSymbolValueREF("PI_SEQ_NBR",&pPageName); GetSymbolValueREF("TAG_NAME",&pPageTitle); do{ RETeFalse(DbFetchCursor(&cda,eFalse),"Fetch Failed"); fprintf(stderr,"%s %s C(%s)\n",pPageName,pPageTitle,pDaDat); } while(cda.bFound==eTrue); RETeFalse(DbDisconnect(&lda,eFalse),"Disconnect Failed"); return(0);}#endif /* MAIN_TEST *//*/* Connect to the INFORMIX DATABASE./* The pConnect parameter should be passed as (char *)0 to instruct/* the DBI to use the INFORMIX_DRIVERCONNECT Symobl. The pConnect is/* only used to Override the INFORMIX_DRIVERCONNECT symbol./* usage:/* SQLWEB_LDA lLda;/* RETeFalse( DbConnect((char*)0 ,&lLda), "Connect Failed");/* RETeFalse( DbConnect("scott/tiger",&lLda), "Connect Failed"); */eBoolean_tDbConnect(char *pConnect /* Database Specific Connect String */ ,SQLWEB_LDA *pLDA /* This Function must Fills-in /* the SQLWEB_LDA structure */ ){ static int siConnectIndex; /* Connections are NOT re-used. */ char sEnvBuf[MAX_TOKVAL_SIZE] ,sBuf[BUFSIZ] ,*pBuf ; short sOutSize; RETCODE rc; if( siConnectIndex > MAX_CONNECTIONS ){ MsgPush("Exceeded Maximum Connections"); return(eFalse); } /* /* Must be Sure INFORMIXDIR is in the Environment! */ pBuf = getenv("INFORMIXDIR"); /* The Environment overrides the SYMBOL TABLE */ if(!pBuf) { RETeFalse(GetSymbolValueREF("INFORMIXDIR",&pBuf) ,"Can't find INFORMIXDIR" ); sprintf(sEnvBuf,"INFORMIXDIR=%s",pBuf); putenv(DupBuf(sEnvBuf)); } /* /* pConnect Parameter overrides the INFORMIX_DRIVERCONNECT env variable */ if( pConnect ) { pBuf=pConnect; } else { RETeFalse(GetSymbolValueREF("INFORMIX_DRIVERCONNECT",&pBuf) ,"Can't find INFORMIX_DRIVERCONNECT" ); } /* /* Update the Generic DBI LDA Struct */ pLDA->iLdaIndex = siConnectIndex; pLDA->bConnected= eFalse; pLDA->pConnect = pBuf; /* Allocate the Environment handle */ if( SQLAllocEnv( &gaLDA[pLDA->iLdaIndex] ) ) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Connect Failed (SQLAllocEnv)." ); return(eFalse); } /* Allocate the Connection handle */ rc=SQLAllocConnect(gaLDA[pLDA->iLdaIndex],&gaHDA[pLDA->iLdaIndex]); if(rc){ PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Connect Failed (SQLAllocConnect)." ); return(eFalse); } rc=SQLDriverConnect(gaHDA[pLDA->iLdaIndex] ,NULL ,(UCHAR*)pBuf ,SQL_NTS ,(UCHAR*)sBuf ,BUFSIZ ,&sOutSize ,SQL_DRIVER_NOPROMPT ); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Connect Failed (SQLDriverConnect)." ); return(eFalse); } siConnectIndex++; /* Bump the Connection Index */ pLDA->bConnected = eTrue; /* Set Connected Flag */ DebugHTML(__FILE__,__LINE__,3,"DbConnect(%s) OK!",pBuf); return(eTrue); /* Oh, sweet success! */}/*/* Disconnect from the DATABASE./* bCommit Flag: bCommit=eTrue means essentially "COMMIT RELEASE"/* bCommit=eFalse means essentially "ROLLBACK RELEASE"/* usage:/* SQLWEB_LDA lLda;/* ... connect .../* RETeFalse( DbDisonnect(&lLda,eTrue), "Connect Failed"); -- Commit/* RETeFalse( DbDisonnect(&lLda,eFalse),"Connect Failed"); -- Rollback */eBoolean_tDbDisconnect(SQLWEB_LDA *pLDA /* LDA struct from DbConnect() */ ,eBoolean_t bCommit /* Commit/Rollback Flag */ ){ /* Perform the COMMIT/ROLLBACK */ if(ISeTrue(bCommit)) (void)DbCommit(pLDA); else (void)DbRollback(pLDA); if(SQLDisconnect(&gaLDA[pLDA->iLdaIndex])){ PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Disconnect Failed." ); return(eFalse); } pLDA->bConnected = eFalse; /* Set Connected Flag */ return(eTrue);}/*/* Commit Transaction */eBoolean_tDbCommit(SQLWEB_LDA *pLDA) /* LDA struct from DbConnect() */{ RETCODE rc; rc=SQLTransact(gaLDA[pLDA->iLdaIndex],gaHDA[pLDA->iLdaIndex],SQL_COMMIT); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Commit Failed." ); return(eFalse); } return(eTrue);}/*/* Rollback a Transaction. */eBoolean_tDbRollback(SQLWEB_LDA *pLDA) /* LDA struct ftom DbConnect() */{ RETCODE rc; rc=SQLTransact(gaLDA[pLDA->iLdaIndex],gaHDA[pLDA->iLdaIndex],SQL_ROLLBACK); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,(HSTMT)0 ,"Rollback Failed." ); return(eFalse); } return(eTrue);}/*/* Open a CURSOR. Must deal with SELECT and non-SELECT statements./* All BIND variables are taken from the SYMBOL TABLE/* All SELECT-LIST variables are installed into the SYMBOL TABLE/* usage:/* SQLWEB_LDA lLda;/* SQLWEB_CURSOR cCur;/* char *pSQL = "select ename from emp where ename like :SYM_NAME";/* ... connect .../* RETeFalse( DbOpenCursor(&lLda,pSQL,&cCur), "Open Failed"); */eBoolean_tDbOpenCursor(SQLWEB_LDA *pLDA /* SQLWEB LDA struct created by DbConnect() */ ,char *pStmt /* SQL Statement, All BIND Variables will /* be extracted from the SYMBOL TABLE and /* The SELECT LIST must be INSTALLED into /* The SYMBOL TABLE */ ,SQLWEB_CURSOR *pCursor /* This Function must Populate /* The SQLWEB_CURSOR structure */ ){ int iCursorIndex; RETCODE rc; if(pStmt==(char*)0) return(eTrue); if(pLDA==(SQLWEB_LDA*)0) return(eTrue); if(pCursor==(SQLWEB_CURSOR*)0) return(eTrue); /* Supports Delayed Connect */ if( ISeFalse(pLDA->bConnected)) { RETeFalse(DbConnect(0,pLDA),"DbOpen (Connect) Failed"); } RETeFalse(GetCursorIndex(&iCursorIndex),"GetCursorIndex Failed"); DebugHTML(__FILE__,__LINE__,4,"DbOpenCursor:CursorIndex=%d",iCursorIndex); /* /* Initialize the SQLWEB_CURSOR */ pCursor->pLDA = pLDA; pCursor->iCursorIndex= iCursorIndex; pCursor->bOpen = eFalse; gbaOpen[iCursorIndex] = eFalse; pCursor->bFound = eFalse; pCursor->pStmt = pStmt; pCursor->lSelect = l_create("INORDER"); /* Indicator Variables */ pCursor->lBind = l_create("INORDER"); /* cleanup */ /* Modify the SQL Stmt to meet Informix standards /* -- replace symbol refs with '?' */ RETeFalse(PrepareParameters(pCursor),"PrepareParameters Failed"); /* Allocate the statement handle */ rc=SQLAllocStmt(gaHDA[pLDA->iLdaIndex],&gaCDA[iCursorIndex]); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,gaCDA[iCursorIndex] ,"SQLAllocStmt Failed." ); return(eFalse); } rc=SQLPrepare(gaCDA[iCursorIndex],(UCHAR*)pCursor->pStmt,SQL_NTS); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,gaCDA[iCursorIndex] ,"SQLPrepare Failed." ); return(eFalse); } /* /* Describe the BIND & SELECT-List variables */ RETeFalse(DescribeBindVars(pCursor),"Describe Bind Variables Failed"); RETeFalse(DescribeSelectVars(pCursor) ,"Describe Select Variables Failed"); /* Off with his head! --EXECUTE THE STMT */ rc=SQLExecute( gaCDA[iCursorIndex] ); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { PushDBErr(gaLDA[pLDA->iLdaIndex] ,gaCDA[iCursorIndex] ,"SQLExecute Failed." ); return(eFalse); } /* pCursor->bOpen is set by "side-effect" in DescribeSelectVars... */ if(ISeFalse(pCursor->bOpen)) { RETeFalse(FreeStmt(pCursor),"FreeStmt Failed"); } /* Alls well that end well! */ return(eTrue);}/*/* Fetch a ROW from the CURSOR and install each SELECT ITEM into/* The SYMBOL TABLE./* bClose Flag: bClose=eTrue means CLOSE CURSOR after the FETCH/* bClose=eFalse means CLOSE CURSOR when exhausted/*/* ******* SPECIAL NOTE ABOUT RETURN CODE: *******/* ONLY return(eFalse) on DATABASE ERROR/* USE pCursor->bFound=eFalse; to indicate NOT FOUND/* ******* SPECIAL NOTE ABOUT RETURN CODE: *******/* usage:/* SQLWEB_CURSOR cCur;/* ... connect .../* ... open .../* for(;;) {/* RETeFalse( DbFetchCursor(&cCur,eFalse), "Close Failed");/* if(cCur.bFound) break;/* } */eBoolean_tDbFetchCursor(SQLWEB_CURSOR *pCursor /* the CURSOR (from Open) */ ,eBoolean_t bClose /* Force Close after Fetch */ ){ eBoolean_t bStatus; RETCODE rc; if(ISeFalse(pCursor->bOpen)) { DebugHTML(__FILE__,__LINE__,3,"DbFetchCursor:Not Open"); pCursor->bFound=eFalse; return(eTrue); } /* Process the Fetch Request */ rc=SQLFetch(gaCDA[pCursor->iCursorIndex]); if(rc!=SQL_SUCCESS && rc!=SQL_SUCCESS_WITH_INFO) { pCursor->bFound = eFalse; if(rc==SQL_NO_DATA_FOUND) { bStatus =eTrue; } else { PushDBErr(gaLDA[pCursor->pLDA->iLdaIndex] ,gaCDA[pCursor->iCursorIndex] ,"SQLFetch failed." ); bStatus = eFalse; } /* /* Close the Cursor */ bStatus = FreeStmt(pCursor); /* /* Free the DbInfo_t's Created for this Cursor */ l_scan(pCursor->lBind,(PFI)FreeDbInfo); l_scan(pCursor->lSelect,(PFI)FreeDbInfo); return(bStatus); } /* OK, Found a ROW, Check for NULLs */ l_scan(pCursor->lSelect,(PFI)SetDbNulls); pCursor->bFound=eTrue; bStatus = eTrue; /* /* Force a Close, good for single row queries */ if(bClose) return( FreeStmt(pCursor) ); return(eTrue);}/*************************************************************/* /* Supporting Routines, not part of the API, all additional/* functions should be declared static! *//*/* Set NULLs based on the INDICATOR Variable/* This is called from the DbFetchCursor() routine */static eBoolean_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -