cgi_odbc.c

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /* cgi_odbc.cpp © Copyright 2004-2005 by Raosoft Inc. All Rights Reserved.    */
00003 /*                                                                            */
00004 /* You may use and modify this file for your own use, but may not distribute  */
00005 /* it or derivative works without the prior written consent of Raosoft, Inc.  */
00006 /*                                                                            */
00007 /* If you choose to share your modifications with Raosoft, Inc. the company   */
00008 /* will attempt to incorporate them into future versions of this file.        */
00009 /*                                                                            */
00010 /* This software is provided "as is," and Raosoft makes no warranty, express  */
00011 /* or implied, of fitness for a particular application. Every measure has been*/
00012 /* taken to anticipate risks inherent to computer networks, but we cannot     */
00013 /* guarantee safety or reliability of this program in every situation.        */
00014 /*                                                                            */
00015 /******************************************************************************/
00016 
00017 #include "cgi.h"
00018 
00019 /*-------*/
00020 #ifdef CGI_ODBC
00021 #ifdef __BORLANDC__
00022 #include <odbc/sqltypes.h>
00023 #include <odbc/sql.h>
00024 #include <odbc/sqlext.h>
00025 #define SQL_NOUNICODEMAP
00026 #include <odbc/sqlucode.h>
00027 #else
00028 #ifdef __GNUC__
00029 #include <odbcinst.h>
00030 #endif
00031 #include <sqltypes.h>
00032 #include <sql.h>
00033 #include <sqlext.h>
00034 #ifdef XP_WIN
00035 #define SQL_NOUNICODEMAP
00036 #include <sqlucode.h>
00037 #endif
00038 #endif
00039 
00081 typedef struct
00082 {
00083  TextBuffer* ErrorMessage;
00084  SQLHENV henv;
00085  SQLHDBC hdbc;
00086  int debug;
00087 } ODBCSession;
00088 
00089 
00090 void ListErrors(TextBuffer* Message,SQLHANDLE hHandle, SQLSMALLINT hType)
00091 {
00092     SQLSMALLINT iRec = 0;
00093     SQLINTEGER  iError;
00094    char szMessage[1024], szState[8];
00095    SQLSMALLINT len=0;
00096 
00097    szMessage[0]=0;
00098    memset(szState,0,sizeof(szState));
00099 
00100     while (SQLGetDiagRec(hType,
00101                          hHandle,
00102                          ++iRec,
00103                          (unsigned char*)szState,
00104                          &iError,
00105                          (unsigned char*)szMessage,
00106                          sizeof(szMessage),
00107                          &len) == SQL_SUCCESS)
00108     {
00109 #define WRITE(a,x) LogError(x); if (Message) BufferWrite(Message,x)
00110     // Hide "data truncated" messages
00111     LogError("\n");
00112     WRITE(Message,"[");
00113     WRITE(Message,szState);
00114     WRITE(Message,"] ");
00115     WRITE(Message,szMessage);
00116     WRITE(Message," (");
00117     sprintf(szMessage,"%d",iError);
00118     WRITE(Message,szMessage);
00119     WRITE(Message,")");
00120     if (Message)BufferWrite(Message,"\n");
00121 #undef WRITE
00122     }
00123 }
00124 
00125 SQLDB* ODBCConnect(char * service, char* uid, char* pwd, TextBuffer* errors)
00126 {
00127  int r;
00128  ODBCSession * database = (ODBCSession*)CGIMALLOC(sizeof(ODBCSession));
00129  database->debug = 0;
00130  if (strlen(service) > 256 || strlen(uid) > 256  || strlen(pwd) > 256) return 0;
00131 
00132  if (service[0] == '?')
00133   {
00134    database->debug=1;
00135    service++;
00136   }
00137 
00138  r = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &database->henv);
00139  if (!SQL_SUCCEEDED(r))
00140   {
00141    CGIFREE(database);
00142    LogError("\nCouldn't allocate a SQL environment handle");
00143    return 0;
00144   }
00145 
00146  r = SQLSetEnvAttr(database->henv, SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,0);
00147  if (!SQL_SUCCEEDED(r)||database->debug)
00148   {
00149    ListErrors(errors,database->henv,SQL_HANDLE_ENV);
00150   }
00151  if (!SQL_SUCCEEDED(r))
00152   {
00153    SQLFreeHandle(SQL_HANDLE_ENV, database->henv);
00154    CGIFREE(database);
00155    return 0;
00156    }
00157 
00158  r = SQLAllocHandle(SQL_HANDLE_DBC,database->henv,&database->hdbc);
00159 
00160  if (!SQL_SUCCEEDED(r)||database->debug)
00161   {
00162    ListErrors(errors,database->henv,SQL_HANDLE_ENV);
00163   }
00164 
00165  if (!SQL_SUCCEEDED(r))
00166   {
00167    LogError("\nCouldn't allocate a SQL database handle");
00168    SQLFreeHandle(SQL_HANDLE_ENV, database->henv);
00169    CGIFREE(database);
00170    return 0;
00171   }
00172 
00173  if (strchr(service,'='))
00174  {
00175      SQLCHAR outConn[1024];
00176      SQLSMALLINT l = 1024;
00177      r = SQLDriverConnect(database->hdbc,0,(SQLCHAR*)service, SQL_NTS,
00178                           outConn,l,&l,SQL_DRIVER_NOPROMPT);
00179 }
00180 else
00181 {
00182  r = SQLConnect(database->hdbc,
00183  (SQLCHAR*)service, SQL_NTS,
00184  (SQLCHAR*)uid, SQL_NTS,
00185  (SQLCHAR*)pwd, SQL_NTS);
00186 }
00187  if (!SQL_SUCCEEDED(r)||database->debug)
00188   {
00189    ListErrors(errors,database->hdbc,SQL_HANDLE_DBC);
00190    ListErrors(errors,database->henv,SQL_HANDLE_ENV);
00191   }
00192  if (!SQL_SUCCEEDED(r))
00193   {
00194    SQLFreeHandle(SQL_HANDLE_DBC, database->hdbc);
00195    SQLFreeHandle(SQL_HANDLE_ENV, database->henv);
00196    CGIFREE(database);
00197    return 0;
00198   }
00199 
00200  database->ErrorMessage = NewBuffer(1024);
00201  return (SQLDB*)database;
00202 }
00203 
00204 int ODBCDisconnect(SQLDB* db)
00205 {
00206  ODBCSession* database = (ODBCSession*)db;
00207  if (!database) return 0;
00208 
00209  SQLDisconnect(database->hdbc);
00210  SQLFreeHandle(SQL_HANDLE_DBC, database->hdbc);
00211  SQLFreeHandle(SQL_HANDLE_ENV, database->henv);
00212 
00213  DeleteBuffer(database->ErrorMessage);
00214  CGIFREE(database);
00215  return 0;
00216 }
00217 
00218 int ODBCCommit(SQLDB* db)
00219 {
00220  ODBCSession* database = (ODBCSession*)db;
00221  if (!database) return 0;
00222  return (SQL_SUCCEEDED(SQLEndTran(SQL_HANDLE_DBC,database->hdbc,SQL_COMMIT)));
00223 }
00224 
00225 int ODBCStart(ODBCSession* database,char* command,SQLHSTMT* st)
00226 {
00227  int r;
00228 
00229  r = SQLAllocHandle(SQL_HANDLE_STMT, database->hdbc, st);
00230  if (!SQL_SUCCEEDED(r))
00231   {
00232    LogError("\nCan't allocate a statement handle");
00233    BufferWrite(database->ErrorMessage,"Can't allocate a statement handle\n");
00234    return 54;
00235   }
00236 
00237  r = SQLExecDirect(*st, (unsigned char*)command, SQL_NTS);
00238 
00239  if (database->debug)
00240    {
00241      char x[32];
00242      LogError("\nSQL statement:");
00243      LogError(command);
00244      LogError("\nSQL result:");
00245      sprintf(x,"%d",r);
00246      LogError(x);
00247    }
00248 
00249  if (database->ErrorMessage)
00250  {
00251    if (!SQL_SUCCEEDED(r))
00252    {
00253      BufferWrite(database->ErrorMessage,"SQL error in:");
00254      BufferWrite(database->ErrorMessage,command);
00255      BufferWrite(database->ErrorMessage,"\n");
00256    }
00257    if (!SQL_SUCCEEDED(r) || database->debug)
00258    {
00259      ListErrors(database->ErrorMessage, st, SQL_HANDLE_STMT);
00260      ListErrors(database->ErrorMessage, database->hdbc, SQL_HANDLE_DBC);
00261      ListErrors(database->ErrorMessage, database->henv, SQL_HANDLE_ENV);
00262    }
00263  }
00264 
00265  if (!SQL_SUCCEEDED(r))
00266    return 54;
00267 
00268  return 0;
00269 }
00270 
00271 int ODBCFinish(void* st,int *modified)
00272 {
00273  if (modified)
00274  {
00275   SQLINTEGER i=0;
00276   SQLRowCount((SQLHSTMT)st,&i);
00277   *modified = i;
00278  }
00279  if (!SQL_SUCCEEDED(SQLFreeHandle(SQL_HANDLE_STMT, (SQLHSTMT)st)))
00280    return 54;
00281 
00282  return 0;
00283 }
00284 
00285 int ODBCExec(SQLDB* db,char* command,int *modified)
00286 {
00287  ODBCSession* database = (ODBCSession*)db;
00288  SQLHSTMT st;
00289  int ret;
00290  if (!database) return 0;
00291 
00292  ret = ODBCStart(database,command,&st);
00293  if (ret)
00294  {
00295    SQLFreeHandle(SQL_HANDLE_STMT, (SQLHSTMT)st);
00296    return ret;
00297  }
00298 
00299  ODBCFinish(st,modified);
00300 
00301  return 0;
00302 }
00303 
00304 
00305 CGINameValue* ODBCQuery(SQLDB* database, char* command,int* modified)
00306 {
00307  void* handle=0;
00308  CGINameValue* ret;
00309  if (ODBCSelect(database,command,&handle)) return NULL;
00310  ret = ODBCRead(handle);
00311  ODBCFinish(handle,modified);
00312  return ret;
00313 }
00314 
00315 
00316 int ODBCSelect(SQLDB* db,char* command,void** st)
00317 {
00318  ODBCSession* database = (ODBCSession*)db;
00319  int ret;
00320  if (!database) return 0;
00321 
00322  ret= ODBCStart(database,command,st);
00323  return ret;
00324 }
00325 
00326 CGINameValue* ODBCRead(void* st)
00327 {
00328   SQLSMALLINT columnCount = 0;
00329   CGINameValue * data;
00330   SQLSMALLINT i;
00331 
00332   int ret = SQLNumResultCols((SQLHSTMT)st,&columnCount);
00333   if (columnCount ==0) return NULL;
00334 
00335   data = NewNVP(columnCount);
00336   /* bind*/
00337   for (i=1; i<= columnCount; i++)
00338     {
00339     char szTitle[256];
00340     long size=0;
00341     szTitle[0]=0;
00342 
00343     ret = SQLColAttribute((SQLHSTMT)st,i,SQL_DESC_LENGTH,
00344                                      NULL,0,NULL,&size);
00345 
00346     if (!SQL_SUCCEEDED(ret) || size <= 0) size = 128;
00347 
00348     SQLColAttribute((SQLHSTMT)st,i,SQL_DESC_NAME,szTitle,
00349                             sizeof(szTitle),NULL,NULL);
00350 
00351     data[i-1].name = strndup(szTitle,sizeof(szTitle));
00352     data[i-1].value = (char*)CGIMALLOC(size+1);
00353     memset(data[i-1].value,0,size+1);
00354 
00355     SQLBindCol((SQLHSTMT)st,i,SQL_C_CHAR,(SQLPOINTER) data[i-1].value,
00356                (size + 1) * sizeof(char),&size);
00357     }
00358   /* end bind */
00359   ret = SQLFetch((SQLHSTMT)st);
00360   if (SQL_SUCCEEDED(ret)) return data;
00361   DeleteNVP(data);
00362   return NULL;
00363 }
00364 
00365 #endif


Raosoft, Inc.
Raosoft EZReport, EZSurvey, InterForm, RapidReport, Raosoft, and SurveyWin are registered trademarks of Raosoft, Inc. Page contents © 1996-2007 by Raosoft, Inc. You may use and modify this file for your own use, but may not distribute it or derivative works without the prior written consent of Raosoft, Inc. This software is provided "as is," and Raosoft makes no warranty, express or implied, of fitness for a particular application. Every measure has been taken to anticipate risks inherent to computer networks, but we cannot guarantee safety or reliability of this program in every situation.
Tel: 206-525-4025 (US) Email: raosoft@raosoft.com
http://www.raosoft.com/