00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TODBCServer.h"
00013
00014 #include "TODBCRow.h"
00015 #include "TODBCResult.h"
00016 #include "TODBCStatement.h"
00017 #include "TSQLColumnInfo.h"
00018 #include "TSQLTableInfo.h"
00019 #include "TUrl.h"
00020 #include "TString.h"
00021 #include "TObjString.h"
00022 #include "TList.h"
00023 #include "Riostream.h"
00024
00025
00026 #include <sqlext.h>
00027
00028
00029 ClassImp(TODBCServer)
00030
00031
00032 TODBCServer::TODBCServer(const char *db, const char *uid, const char *pw) :
00033 TSQLServer()
00034 {
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 TString connstr;
00085 Bool_t simpleconnect = kTRUE;
00086
00087 SQLRETURN retcode;
00088 SQLHWND hwnd;
00089
00090 fPort = 1;
00091
00092 if ((strncmp(db, "odbc", 4)!=0) || (strlen(db)<8)) {
00093 SetError(-1, "db argument should be started from odbc...","TODBCServer");
00094 goto zombie;
00095 }
00096
00097 if (strncmp(db, "odbc://", 7)==0) {
00098 TUrl url(db);
00099 if (!url.IsValid()) {
00100 SetError(-1, Form("not valid URL: %s", db), "TODBCServer");
00101 goto zombie;
00102 }
00103 const char* driver = "MyODBC";
00104 const char* dbase = url.GetFile();
00105 if (dbase!=0)
00106 if (*dbase=='/') dbase++;
00107
00108 if (((uid==0) || (*uid==0)) && (strlen(url.GetUser())>0)) {
00109 uid = url.GetUser();
00110 pw = url.GetPasswd();
00111 }
00112
00113 if (strlen(url.GetOptions())!=0) driver = url.GetOptions();
00114
00115 connstr.Form("DRIVER={%s};"
00116 "SERVER=%s;"
00117 "DATABASE=%s;"
00118 "USER=%s;"
00119 "PASSWORD=%s;"
00120 "OPTION=3;",
00121 driver, url.GetHost(), dbase, uid, pw);
00122 if (url.GetPort()>0)
00123 connstr += Form("PORT=%d;", url.GetPort());
00124
00125 fHost = url.GetHost();
00126 fPort = url.GetPort()>0 ? url.GetPort() : 1;
00127 fDB = dbase;
00128 simpleconnect = kFALSE;
00129 } else
00130 if (strncmp(db, "odbcd://", 8)==0) {
00131 connstr = db+8;
00132 simpleconnect = kFALSE;
00133 } else
00134 if (strncmp(db, "odbcn://", 8)==0) {
00135 connstr = db+8;
00136 simpleconnect = kTRUE;
00137 } else {
00138 SetError(-1, "db argument is invalid", "TODBCServer");
00139 goto zombie;
00140 }
00141
00142 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fHenv);
00143 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00144
00145
00146 retcode = SQLSetEnvAttr(fHenv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
00147 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00148
00149
00150 retcode = SQLAllocHandle(SQL_HANDLE_DBC, fHenv, &fHdbc);
00151 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00152
00153
00154 retcode = SQLSetConnectAttr(fHdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER) 5, 0);
00155 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00156
00157 char sbuf[2048];
00158
00159 SQLSMALLINT reslen;
00160 SQLINTEGER reslen1;
00161
00162 hwnd = 0;
00163
00164 if (simpleconnect)
00165 retcode = SQLConnect(fHdbc, (SQLCHAR*) connstr.Data(), SQL_NTS,
00166 (SQLCHAR*) uid, SQL_NTS,
00167 (SQLCHAR*) pw, SQL_NTS);
00168 else
00169 retcode = SQLDriverConnect(fHdbc, hwnd,
00170 (SQLCHAR*) connstr.Data(), SQL_NTS,
00171 (SQLCHAR*) sbuf, sizeof(sbuf), &reslen, SQL_DRIVER_NOPROMPT);
00172
00173 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00174
00175 fType = "ODBC";
00176
00177 retcode = SQLGetInfo(fHdbc, SQL_USER_NAME, sbuf, sizeof(sbuf), &reslen);
00178 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00179 fUserId = sbuf;
00180
00181 retcode = SQLGetInfo(fHdbc, SQL_DBMS_NAME, sbuf, sizeof(sbuf), &reslen);
00182 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00183 fServerInfo = sbuf;
00184 fType = sbuf;
00185
00186 retcode = SQLGetInfo(fHdbc, SQL_DBMS_VER, sbuf, sizeof(sbuf), &reslen);
00187 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00188 fServerInfo += " ";
00189 fServerInfo += sbuf;
00190
00191
00192 retcode = SQLGetConnectAttr(fHdbc, SQL_ATTR_CURRENT_CATALOG, sbuf, sizeof(sbuf), &reslen1);
00193 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00194 if (fDB.Length()==0) fDB = sbuf;
00195
00196 retcode = SQLGetInfo(fHdbc, SQL_SERVER_NAME, sbuf, sizeof(sbuf), &reslen);
00197 if (ExtractErrors(retcode, "TODBCServer")) goto zombie;
00198 if (fHost.Length()==0) fHost = sbuf;
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 return;
00217
00218 zombie:
00219 fPort = -1;
00220 fHost = "";
00221 MakeZombie();
00222 }
00223
00224
00225 TODBCServer::~TODBCServer()
00226 {
00227
00228
00229 if (IsConnected())
00230 Close();
00231 }
00232
00233
00234 TList* TODBCServer::ListData(Bool_t isdrivers)
00235 {
00236
00237
00238
00239 SQLHENV henv;
00240 SQLRETURN retcode;
00241
00242 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
00243 if ((retcode!=SQL_SUCCESS) && (retcode!=SQL_SUCCESS_WITH_INFO)) return 0;
00244
00245 retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
00246 if ((retcode!=SQL_SUCCESS) && (retcode!=SQL_SUCCESS_WITH_INFO)) return 0;
00247
00248 TList* lst = 0;
00249
00250 char namebuf[2048], optbuf[2048];
00251 SQLSMALLINT reslen1, reslen2;
00252
00253 do {
00254 strcpy(namebuf, "");
00255 strcpy(optbuf, "");
00256 if (isdrivers)
00257 retcode = SQLDrivers(henv, (lst==0 ? SQL_FETCH_FIRST : SQL_FETCH_NEXT),
00258 (SQLCHAR*) namebuf, sizeof(namebuf), &reslen1,
00259 (SQLCHAR*) optbuf, sizeof(optbuf), &reslen2);
00260 else
00261 retcode = SQLDataSources(henv, (lst==0 ? SQL_FETCH_FIRST : SQL_FETCH_NEXT),
00262 (SQLCHAR*) namebuf, sizeof(namebuf), &reslen1,
00263 (SQLCHAR*) optbuf, sizeof(optbuf), &reslen2);
00264
00265 if (retcode==SQL_NO_DATA) break;
00266 if ((retcode==SQL_SUCCESS) || (retcode==SQL_SUCCESS_WITH_INFO)) {
00267 if (lst==0) {
00268 lst = new TList;
00269 lst->SetOwner(kTRUE);
00270 }
00271 for (int n=0;n<reslen2-1;n++)
00272 if (optbuf[n]=='\0') optbuf[n] = ';';
00273
00274 lst->Add(new TNamed(namebuf, optbuf));
00275 }
00276 } while ((retcode==SQL_SUCCESS) || (retcode==SQL_SUCCESS_WITH_INFO));
00277
00278 SQLFreeHandle(SQL_HANDLE_ENV, henv);
00279
00280 return lst;
00281
00282 }
00283
00284
00285
00286 TList* TODBCServer::GetDrivers()
00287 {
00288
00289
00290
00291
00292
00293 return ListData(kTRUE);
00294 }
00295
00296
00297 void TODBCServer::PrintDrivers()
00298 {
00299
00300
00301
00302 TList* lst = GetDrivers();
00303 cout << "List of ODBC drivers:" << endl;
00304 TIter iter(lst);
00305 TNamed* n = 0;
00306 while ((n = (TNamed*) iter()) != 0)
00307 cout << " " << n->GetName() << " : " << n->GetTitle() << endl;
00308 delete lst;
00309 }
00310
00311
00312 TList* TODBCServer::GetDataSources()
00313 {
00314
00315
00316
00317
00318
00319 return ListData(kFALSE);
00320 }
00321
00322
00323 void TODBCServer::PrintDataSources()
00324 {
00325
00326
00327
00328 TList* lst = GetDataSources();
00329 cout << "List of ODBC data sources:" << endl;
00330 TIter iter(lst);
00331 TNamed* n = 0;
00332 while ((n = (TNamed*) iter()) != 0)
00333 cout << " " << n->GetName() << " : " << n->GetTitle() << endl;
00334 delete lst;
00335 }
00336
00337
00338 Bool_t TODBCServer::ExtractErrors(SQLRETURN retcode, const char* method)
00339 {
00340
00341
00342 if ((retcode==SQL_SUCCESS) || (retcode==SQL_SUCCESS_WITH_INFO)) return kFALSE;
00343
00344 SQLINTEGER i = 0;
00345 SQLINTEGER native;
00346 SQLCHAR state[7];
00347 SQLCHAR text[256];
00348 SQLSMALLINT len;
00349
00350 while (SQLGetDiagRec(SQL_HANDLE_ENV, fHenv, ++i, state, &native, text,
00351 sizeof(text), &len ) == SQL_SUCCESS)
00352
00353 SetError(native, (const char*) text, method);
00354
00355 i = 0;
00356
00357 while (SQLGetDiagRec(SQL_HANDLE_DBC, fHdbc, ++i, state, &native, text,
00358 sizeof(text), &len ) == SQL_SUCCESS)
00359
00360 SetError(native, (const char*) text, method);
00361
00362 return kTRUE;
00363 }
00364
00365
00366 #define CheckConnect(method, res) \
00367 { \
00368 ClearError(); \
00369 if (!IsConnected()) { \
00370 SetError(-1,"ODBC driver is not connected",method); \
00371 return res; \
00372 } \
00373 }
00374
00375
00376 void TODBCServer::Close(Option_t *)
00377 {
00378
00379
00380 SQLDisconnect(fHdbc);
00381 SQLFreeHandle(SQL_HANDLE_DBC, fHdbc);
00382 SQLFreeHandle(SQL_HANDLE_ENV, fHenv);
00383 fPort = -1;
00384 }
00385
00386
00387 TSQLResult *TODBCServer::Query(const char *sql)
00388 {
00389
00390
00391
00392
00393 CheckConnect("Query", 0);
00394
00395 SQLRETURN retcode;
00396 SQLHSTMT hstmt;
00397
00398 SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00399
00400 retcode = SQLExecDirect(hstmt, (SQLCHAR*) sql, SQL_NTS);
00401 if (ExtractErrors(retcode, "Query")) {
00402 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00403 return 0;
00404 }
00405
00406 return new TODBCResult(hstmt);
00407 }
00408
00409
00410 Bool_t TODBCServer::Exec(const char* sql)
00411 {
00412
00413
00414
00415 CheckConnect("Exec", 0);
00416
00417 SQLRETURN retcode;
00418 SQLHSTMT hstmt;
00419
00420 SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00421
00422 retcode = SQLExecDirect(hstmt, (SQLCHAR*) sql, SQL_NTS);
00423
00424 Bool_t res = !ExtractErrors(retcode, "Exec");
00425
00426 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00427
00428 return res;
00429 }
00430
00431
00432 Int_t TODBCServer::SelectDataBase(const char *db)
00433 {
00434
00435
00436
00437
00438 CheckConnect("SelectDataBase", -1);
00439
00440 SQLRETURN retcode = SQLSetConnectAttr(fHdbc, SQL_ATTR_CURRENT_CATALOG, (SQLCHAR*) db, SQL_NTS);
00441 if (ExtractErrors(retcode, "SelectDataBase")) return -1;
00442
00443 fDB = db;
00444
00445 return 0;
00446 }
00447
00448
00449 TSQLResult *TODBCServer::GetDataBases(const char *)
00450 {
00451
00452
00453
00454
00455
00456 CheckConnect("GetDataBases", 0);
00457
00458 return 0;
00459 }
00460
00461
00462 TSQLResult *TODBCServer::GetTables(const char*, const char* wild)
00463 {
00464
00465
00466
00467
00468
00469 CheckConnect("GetTables", 0);
00470
00471 SQLRETURN retcode;
00472 SQLHSTMT hstmt;
00473
00474 SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00475
00476 SQLCHAR* schemaName = 0;
00477 SQLSMALLINT schemaNameLength = 0;
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 SQLCHAR* tableName = 0;
00492 SQLSMALLINT tableNameLength = 0;
00493
00494 if ((wild!=0) && (strlen(wild)!=0)) {
00495 tableName = (SQLCHAR*) wild;
00496 tableNameLength = strlen(wild);
00497 SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID, (SQLPOINTER) SQL_FALSE, 0);
00498 }
00499
00500 retcode = SQLTables(hstmt, NULL, 0, schemaName, schemaNameLength, tableName, tableNameLength, (SQLCHAR*) "TABLE", 5);
00501 if (ExtractErrors(retcode, "GetTables")) {
00502 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00503 return 0;
00504 }
00505
00506 return new TODBCResult(hstmt);
00507 }
00508
00509
00510 TList* TODBCServer::GetTablesList(const char* wild)
00511 {
00512
00513
00514
00515 CheckConnect("GetTablesList", 0);
00516
00517 TSQLResult* res = GetTables(0, wild);
00518 if (res==0) return 0;
00519
00520 TList* lst = 0;
00521
00522 TSQLRow* row = 0;
00523
00524 while ((row = res->Next())!=0) {
00525 const char* tablename = row->GetField(2);
00526 if (tablename!=0) {
00527
00528 if (lst==0) {
00529 lst = new TList;
00530 lst->SetOwner(kTRUE);
00531 }
00532 lst->Add(new TObjString(tablename));
00533 }
00534 delete row;
00535 }
00536
00537 delete res;
00538
00539 return lst;
00540 }
00541
00542
00543
00544 TSQLTableInfo* TODBCServer::GetTableInfo(const char* tablename)
00545 {
00546
00547
00548
00549 CheckConnect("GetTableInfo", 0);
00550
00551 #define STR_LEN 128+1
00552 #define REM_LEN 254+1
00553
00554
00555
00556 SQLCHAR szCatalog[STR_LEN], szSchema[STR_LEN];
00557 SQLCHAR szTableName[STR_LEN], szColumnName[STR_LEN];
00558 SQLCHAR szTypeName[STR_LEN], szRemarks[REM_LEN];
00559 SQLCHAR szColumnDefault[STR_LEN], szIsNullable[STR_LEN];
00560 SQLLEN columnSize, bufferLength, charOctetLength, ordinalPosition;
00561 SQLSMALLINT dataType, decimalDigits, numPrecRadix, nullable;
00562 SQLSMALLINT sqlDataType, datetimeSubtypeCode;
00563 SQLRETURN retcode;
00564 SQLHSTMT hstmt;
00565
00566
00567
00568 SQLLEN cbCatalog, cbSchema, cbTableName, cbColumnName;
00569 SQLLEN cbDataType, cbTypeName, cbColumnSize, cbBufferLength;
00570 SQLLEN cbDecimalDigits, cbNumPrecRadix, cbNullable, cbRemarks;
00571 SQLLEN cbColumnDefault, cbSQLDataType, cbDatetimeSubtypeCode, cbCharOctetLength;
00572 SQLLEN cbOrdinalPosition, cbIsNullable;
00573
00574
00575 SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00576
00577 retcode = SQLColumns(hstmt, NULL, 0, NULL, 0, (SQLCHAR*) tablename, SQL_NTS, NULL, 0);
00578 if (ExtractErrors(retcode, "GetTableInfo")) {
00579 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00580 return 0;
00581 }
00582
00583 TList* lst = 0;
00584
00585
00586
00587 SQLBindCol(hstmt, 1, SQL_C_CHAR, szCatalog, STR_LEN,&cbCatalog);
00588 SQLBindCol(hstmt, 2, SQL_C_CHAR, szSchema, STR_LEN, &cbSchema);
00589 SQLBindCol(hstmt, 3, SQL_C_CHAR, szTableName, STR_LEN,&cbTableName);
00590 SQLBindCol(hstmt, 4, SQL_C_CHAR, szColumnName, STR_LEN, &cbColumnName);
00591 SQLBindCol(hstmt, 5, SQL_C_SSHORT, &dataType, 0, &cbDataType);
00592 SQLBindCol(hstmt, 6, SQL_C_CHAR, szTypeName, STR_LEN, &cbTypeName);
00593 SQLBindCol(hstmt, 7, SQL_C_SLONG, &columnSize, 0, &cbColumnSize);
00594 SQLBindCol(hstmt, 8, SQL_C_SLONG, &bufferLength, 0, &cbBufferLength);
00595 SQLBindCol(hstmt, 9, SQL_C_SSHORT, &decimalDigits, 0, &cbDecimalDigits);
00596 SQLBindCol(hstmt, 10, SQL_C_SSHORT, &numPrecRadix, 0, &cbNumPrecRadix);
00597 SQLBindCol(hstmt, 11, SQL_C_SSHORT, &nullable, 0, &cbNullable);
00598 SQLBindCol(hstmt, 12, SQL_C_CHAR, szRemarks, REM_LEN, &cbRemarks);
00599 SQLBindCol(hstmt, 13, SQL_C_CHAR, szColumnDefault, STR_LEN, &cbColumnDefault);
00600 SQLBindCol(hstmt, 14, SQL_C_SSHORT, &sqlDataType, 0, &cbSQLDataType);
00601 SQLBindCol(hstmt, 15, SQL_C_SSHORT, &datetimeSubtypeCode, 0, &cbDatetimeSubtypeCode);
00602 SQLBindCol(hstmt, 16, SQL_C_SLONG, &charOctetLength, 0, &cbCharOctetLength);
00603 SQLBindCol(hstmt, 17, SQL_C_SLONG, &ordinalPosition, 0, &cbOrdinalPosition);
00604 SQLBindCol(hstmt, 18, SQL_C_CHAR, szIsNullable, STR_LEN, &cbIsNullable);
00605
00606 retcode = SQLFetch(hstmt);
00607
00608 while ((retcode==SQL_SUCCESS) || (retcode==SQL_SUCCESS_WITH_INFO)) {
00609
00610 Int_t sqltype = kSQL_NONE;
00611
00612 Int_t data_size = -1;
00613 Int_t data_length = -1;
00614 Int_t data_scale = -1;
00615 Int_t data_sign = -1;
00616
00617 switch (dataType) {
00618 case SQL_CHAR:
00619 sqltype = kSQL_CHAR;
00620 data_size = columnSize;
00621 data_length = charOctetLength;
00622 break;
00623 case SQL_VARCHAR:
00624 case SQL_LONGVARCHAR:
00625 sqltype = kSQL_VARCHAR;
00626 data_size = columnSize;
00627 data_length = charOctetLength;
00628 break;
00629 case SQL_DECIMAL:
00630 case SQL_NUMERIC:
00631 sqltype = kSQL_NUMERIC;
00632 data_size = columnSize;
00633 data_length = columnSize;
00634 data_scale = decimalDigits;
00635 break;
00636 case SQL_INTEGER:
00637 case SQL_TINYINT:
00638 case SQL_BIGINT:
00639 sqltype = kSQL_INTEGER;
00640 data_size = columnSize;
00641 break;
00642 case SQL_REAL:
00643 case SQL_FLOAT:
00644 sqltype = kSQL_FLOAT;
00645 data_size = columnSize;
00646 data_sign = 1;
00647 break;
00648 case SQL_DOUBLE:
00649 sqltype = kSQL_DOUBLE;
00650 data_size = columnSize;
00651 data_sign = 1;
00652 break;
00653 case SQL_BINARY:
00654 case SQL_VARBINARY:
00655 case SQL_LONGVARBINARY:
00656 sqltype = kSQL_BINARY;
00657 data_size = columnSize;
00658 break;
00659 case SQL_TYPE_TIMESTAMP:
00660 sqltype = kSQL_TIMESTAMP;
00661 data_size = columnSize;
00662 break;
00663 }
00664
00665 if (lst==0) lst = new TList;
00666
00667 lst->Add(new TSQLColumnInfo((const char*) szColumnName,
00668 (const char*) szTypeName,
00669 nullable!=0,
00670 sqltype,
00671 data_size,
00672 data_length,
00673 data_scale,
00674 data_sign));
00675
00676 retcode = SQLFetch(hstmt);
00677 }
00678
00679 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00680
00681 return new TSQLTableInfo(tablename, lst);
00682 }
00683
00684
00685 TSQLResult *TODBCServer::GetColumns(const char*, const char *table, const char*)
00686 {
00687
00688
00689
00690
00691
00692 CheckConnect("GetColumns", 0);
00693
00694 SQLRETURN retcode;
00695 SQLHSTMT hstmt;
00696
00697 SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00698
00699 retcode = SQLColumns(hstmt, NULL, 0, NULL, 0, (SQLCHAR*) table, SQL_NTS, NULL, 0);
00700 if (ExtractErrors(retcode, "GetColumns")) {
00701 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00702 return 0;
00703 }
00704
00705 return new TODBCResult(hstmt);
00706 }
00707
00708
00709 Int_t TODBCServer::GetMaxIdentifierLength()
00710 {
00711
00712
00713 CheckConnect("GetMaxIdentifierLength", 20);
00714
00715 SQLUINTEGER info = 0;
00716 SQLRETURN retcode;
00717
00718 retcode = SQLGetInfo(fHdbc, SQL_MAX_IDENTIFIER_LEN, (SQLPOINTER)&info, sizeof(info), NULL);
00719
00720 if (ExtractErrors(retcode, "GetMaxIdentifierLength")) return 20;
00721
00722 return info;
00723 }
00724
00725
00726 Int_t TODBCServer::CreateDataBase(const char*)
00727 {
00728
00729
00730 CheckConnect("CreateDataBase", -1);
00731
00732 return -1;
00733 }
00734
00735
00736 Int_t TODBCServer::DropDataBase(const char*)
00737 {
00738
00739
00740
00741 CheckConnect("DropDataBase", -1);
00742
00743 return -1;
00744 }
00745
00746
00747 Int_t TODBCServer::Reload()
00748 {
00749
00750
00751
00752 CheckConnect("Reload", -1);
00753
00754 return -1;
00755 }
00756
00757
00758 Int_t TODBCServer::Shutdown()
00759 {
00760
00761
00762
00763 CheckConnect("Shutdown", -1);
00764
00765 return -1;
00766 }
00767
00768
00769 const char *TODBCServer::ServerInfo()
00770 {
00771
00772
00773 CheckConnect("ServerInfo", 0);
00774
00775 return fServerInfo;
00776 }
00777
00778
00779 TSQLStatement *TODBCServer::Statement(const char *sql, Int_t bufsize)
00780 {
00781
00782
00783
00784 CheckConnect("Statement", 0);
00785
00786 if (!sql || !*sql) {
00787 SetError(-1, "no query string specified", "Statement");
00788 return 0;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798 SQLRETURN retcode;
00799 SQLHSTMT hstmt;
00800
00801 retcode = SQLAllocHandle(SQL_HANDLE_STMT, fHdbc, &hstmt);
00802 if (ExtractErrors(retcode, "Statement")) return 0;
00803
00804 retcode = SQLPrepare(hstmt, (SQLCHAR*) sql, SQL_NTS);
00805 if (ExtractErrors(retcode, "Statement")) {
00806 SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
00807 return 0;
00808 }
00809
00810 return new TODBCStatement(hstmt, bufsize, fErrorOut);
00811 }
00812
00813
00814 Bool_t TODBCServer::StartTransaction()
00815 {
00816
00817
00818
00819
00820 CheckConnect("StartTransaction", kFALSE);
00821
00822 SQLUINTEGER info = 0;
00823 SQLRETURN retcode;
00824
00825 retcode = SQLGetInfo(fHdbc, SQL_TXN_CAPABLE, (SQLPOINTER)&info, sizeof(info), NULL);
00826 if (ExtractErrors(retcode, "StartTransaction")) return kFALSE;
00827
00828 if (info==0) {
00829 SetError(-1,"Transactions not supported","StartTransaction");
00830 return kFALSE;
00831 }
00832
00833 if (!Commit()) return kFALSE;
00834
00835 retcode = SQLSetConnectAttr(fHdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_OFF, 0);
00836 if (ExtractErrors(retcode, "StartTransaction")) return kFALSE;
00837
00838 return kTRUE;
00839 }
00840
00841
00842 Bool_t TODBCServer::EndTransaction(Bool_t commit)
00843 {
00844
00845
00846
00847 const char* method = commit ? "Commit" : "Rollback";
00848
00849 CheckConnect(method, kFALSE);
00850
00851 SQLRETURN retcode = SQLEndTran(SQL_HANDLE_DBC, fHdbc, commit ? SQL_COMMIT : SQL_ROLLBACK);
00852 if (ExtractErrors(retcode, method)) return kFALSE;
00853
00854 retcode = SQLSetConnectAttr(fHdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_ON, 0);
00855
00856 return kTRUE;
00857 }
00858
00859
00860 Bool_t TODBCServer::Commit()
00861 {
00862
00863
00864 return EndTransaction(kTRUE);
00865 }
00866
00867
00868 Bool_t TODBCServer::Rollback()
00869 {
00870
00871
00872 return EndTransaction(kFALSE);
00873 }