00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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
00359 ret = SQLFetch((SQLHSTMT)st);
00360 if (SQL_SUCCEEDED(ret)) return data;
00361 DeleteNVP(data);
00362 return NULL;
00363 }
00364
00365 #endif