TODBCStatement.cxx

Go to the documentation of this file.
00001 // @(#)root/odbc:$Id: TODBCStatement.cxx 36159 2010-10-07 14:33:51Z rdm $
00002 // Author: Sergey Linev   6/02/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 //________________________________________________________________________
00014 //
00015 //  SQL statement class for ODBC
00016 //
00017 //  See TSQLStatement class documentation for more details
00018 //
00019 //________________________________________________________________________
00020 
00021 
00022 #include "TODBCStatement.h"
00023 #include "TODBCServer.h"
00024 #include "TDataType.h"
00025 #include "Riostream.h"
00026 
00027 #include <sqlext.h>
00028 #include <stdlib.h>
00029 
00030 #define kSqlTime      123781
00031 #define kSqlDate      123782
00032 #define kSqlTimestamp 123783
00033 #define kSqlBinary    123784
00034 
00035 
00036 ClassImp(TODBCStatement)
00037 
00038 //______________________________________________________________________________
00039 TODBCStatement::TODBCStatement(SQLHSTMT stmt, Int_t rowarrsize, Bool_t errout) :
00040    TSQLStatement(errout)
00041 {
00042    //constructor
00043 
00044    fHstmt = stmt;
00045    fBufferPreferredSize = rowarrsize;
00046 
00047    fBuffer = 0;
00048    fStatusBuffer = 0;
00049    fNumBuffers = 0;
00050    fBufferLength = 0;
00051    fBufferCounter = 0;
00052 
00053    fWorkingMode = 0;
00054 
00055    fNumParsProcessed = 0;
00056    fNumRowsFetched = 0;
00057 
00058    SQLSMALLINT   paramsCount = 0;
00059    SQLRETURN retcode = SQLNumParams(fHstmt, &paramsCount);
00060    if (ExtractErrors(retcode,"Constructor"))
00061       paramsCount = 0;
00062 
00063    if (paramsCount>0) {
00064 
00065       fWorkingMode = 1; // we are now using buffers for parameters
00066       fNumParsProcessed = 0;
00067 
00068       SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
00069 
00070       SQLUINTEGER setsize = fBufferPreferredSize;
00071       retcode = SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) setsize, 0);
00072       ExtractErrors(retcode,"Constructor");
00073 
00074       SQLUINTEGER getsize = 0;
00075 
00076       retcode = SQLGetStmtAttr(fHstmt, SQL_ATTR_PARAMSET_SIZE, &getsize, 0, 0);
00077       ExtractErrors(retcode,"Constructor");
00078 
00079       Int_t bufferlen = fBufferPreferredSize;
00080 
00081       // MySQL is not yet support array of parameters
00082       if (getsize<=1) bufferlen=1; else
00083       if (getsize!=setsize) {
00084          SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) 1, 0);
00085          bufferlen = 1;
00086       }
00087 
00088       SetNumBuffers(paramsCount, bufferlen);
00089 
00090       SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAM_STATUS_PTR, fStatusBuffer, 0);
00091       SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &fNumParsProcessed, 0);
00092 
00093       // indicates that we are starting
00094       fBufferCounter = -1;
00095    }
00096 
00097    fNumRowsFetched = 0;
00098    fLastResultRow = 0;
00099 }
00100 
00101 //______________________________________________________________________________
00102 TODBCStatement::~TODBCStatement()
00103 {
00104    //destructor
00105 
00106    Close();
00107 }
00108 
00109 //______________________________________________________________________________
00110 void TODBCStatement::Close(Option_t *)
00111 {
00112    // Close statement
00113 
00114    FreeBuffers();
00115 
00116    SQLFreeHandle(SQL_HANDLE_STMT, fHstmt);
00117 
00118    fHstmt=0;
00119 }
00120 
00121 //______________________________________________________________________________
00122 Bool_t TODBCStatement::Process()
00123 {
00124    // process statement
00125 
00126    ClearError();
00127 
00128    SQLRETURN retcode = SQL_SUCCESS;
00129 
00130    if (IsParSettMode()) {
00131 
00132       // check if we start filling buffers, but not complete it
00133       if (fBufferCounter>=0) {
00134          // if buffer used not fully, set smaller size of buffer arrays
00135          if ((fBufferCounter>0) && (fBufferCounter<fBufferLength-1)) {
00136             SQLUINTEGER setsize = fBufferCounter+1;
00137             SQLSetStmtAttr(fHstmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) setsize, 0);
00138          }
00139          retcode = SQLExecute(fHstmt);
00140       }
00141 
00142       // after Process we finish working with parameters data,
00143       // if necessary, user can try to access resultset of statement
00144       fWorkingMode = 0;
00145       FreeBuffers();
00146       fBufferCounter = -1;
00147    } else {
00148 
00149       // just execute statement,
00150       // later one can try to access results of statement
00151       retcode = SQLExecute(fHstmt);
00152    }
00153 
00154    return !ExtractErrors(retcode, "Process");
00155 }
00156 
00157 //______________________________________________________________________________
00158 Int_t TODBCStatement::GetNumAffectedRows()
00159 {
00160    //get number of affected rows
00161 
00162    ClearError();
00163 
00164    SQLLEN    rowCount;
00165    SQLRETURN retcode = SQL_SUCCESS;
00166 
00167    retcode = SQLRowCount(fHstmt, &rowCount);
00168 
00169    if (ExtractErrors(retcode, "GetNumAffectedRows")) return -1;
00170 
00171    return rowCount;
00172 }
00173 
00174 //______________________________________________________________________________
00175 Bool_t TODBCStatement::StoreResult()
00176 {
00177    // Store result of statement processing.
00178    // Results set, produced by processing of statement, can be stored, and accessed by
00179    // TODBCStamenet methoods like NextResultRow(), GetInt(), GetLong() and so on.
00180 
00181    ClearError();
00182 
00183    if (IsParSettMode()) {
00184       SetError(-1,"Call Process() method before","StoreResult");
00185       return kFALSE;
00186    }
00187 
00188    FreeBuffers();
00189 
00190    SQLSMALLINT columnCount = 0;
00191 
00192    SQLRETURN retcode = SQLNumResultCols(fHstmt, &columnCount);
00193    if (ExtractErrors(retcode, "StoreResult")) return kFALSE;
00194 
00195    if (columnCount==0) return kFALSE;
00196 
00197    SetNumBuffers(columnCount, fBufferPreferredSize);
00198 
00199    SQLULEN arrsize = fBufferLength;
00200 
00201    SQLSetStmtAttr(fHstmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
00202    SQLSetStmtAttr(fHstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) arrsize, 0);
00203    SQLSetStmtAttr(fHstmt, SQL_ATTR_ROW_STATUS_PTR, fStatusBuffer, 0);
00204    SQLSetStmtAttr(fHstmt, SQL_ATTR_ROWS_FETCHED_PTR, &fNumRowsFetched, 0);
00205 
00206    for (int n=0;n<fNumBuffers;n++) {
00207       SQLCHAR     columnName[1024];
00208       SQLSMALLINT nameLength;
00209       SQLSMALLINT dataType;
00210       SQLULEN     columnSize;
00211       SQLSMALLINT decimalDigits;
00212       SQLSMALLINT nullable;
00213 
00214       retcode = SQLDescribeCol(fHstmt, n+1, columnName, 1024,
00215                                &nameLength, &dataType,
00216                                &columnSize, &decimalDigits, &nullable);
00217 
00218       BindColumn(n, dataType, columnSize);
00219 
00220       if (nameLength>0) {
00221          fBuffer[n].fBnamebuffer = new char[nameLength+1];
00222          strcpy(fBuffer[n].fBnamebuffer, (const char*) columnName);
00223       }
00224    }
00225 
00226    fNumRowsFetched = 0;
00227    fLastResultRow = 0;
00228 
00229    fWorkingMode = 2;
00230 
00231    return kTRUE;
00232 }
00233 
00234 //______________________________________________________________________________
00235 Int_t TODBCStatement::GetNumFields()
00236 {
00237    //return number of fields
00238 
00239    return IsResultSet() ? fNumBuffers : -1;
00240 }
00241 
00242 //______________________________________________________________________________
00243 const char* TODBCStatement::GetFieldName(Int_t nfield)
00244 {
00245    //return field name
00246 
00247    ClearError();
00248 
00249    if (!IsResultSet() || (nfield<0) || (nfield>=fNumBuffers)) return 0;
00250 
00251    return fBuffer[nfield].fBnamebuffer;
00252 }
00253 
00254 
00255 //______________________________________________________________________________
00256 Bool_t TODBCStatement::NextResultRow()
00257 {
00258    //next result row
00259 
00260    ClearError();
00261 
00262    if (!IsResultSet()) return kFALSE;
00263 
00264    if ((fNumRowsFetched==0) ||
00265        (1.*fBufferCounter >= 1.*(fNumRowsFetched-1))) {
00266 
00267       fBufferCounter = 0;
00268       fNumRowsFetched = 0;
00269 
00270       SQLRETURN retcode = SQLFetchScroll(fHstmt, SQL_FETCH_NEXT, 0);
00271       if (retcode==SQL_NO_DATA) fNumRowsFetched=0; else
00272          ExtractErrors(retcode,"NextResultRow");
00273 
00274       // this is workaround of Oracle Linux ODBC driver
00275       // it does not returns number of fetched lines, therefore one should
00276       // calculate it from current row number
00277       if (!IsError() && (retcode!=SQL_NO_DATA) && (fNumRowsFetched==0)) {
00278          SQLULEN rownumber = 0;
00279          SQLRETURN retcode2 = SQLGetStmtAttr(fHstmt, SQL_ATTR_ROW_NUMBER, &rownumber, 0, 0);
00280          ExtractErrors(retcode2, "NextResultRow");
00281 
00282          if (!IsError()) {
00283             fNumRowsFetched = rownumber - fLastResultRow;
00284             fLastResultRow = rownumber;
00285          }
00286       }
00287 
00288       if (1.*fNumRowsFetched>fBufferLength)
00289          SetError(-1, "Missmatch between buffer length and fetched rows number", "NextResultRow");
00290 
00291       if (IsError() || (fNumRowsFetched==0)) {
00292          fWorkingMode = 0;
00293          FreeBuffers();
00294       }
00295 
00296    } else
00297       fBufferCounter++;
00298 
00299    return IsResultSet();
00300 }
00301 
00302 //______________________________________________________________________________
00303 Bool_t TODBCStatement::ExtractErrors(SQLRETURN retcode, const char* method)
00304 {
00305    // Extract errors, produced by last ODBC function call
00306 
00307    if ((retcode== SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO)) return kFALSE;
00308 
00309    SQLINTEGER i = 0;
00310    SQLINTEGER native;
00311    SQLCHAR state[ 7 ];
00312    SQLCHAR text[256];
00313    SQLSMALLINT len;
00314    SQLRETURN ret;
00315    do {
00316       ret = SQLGetDiagRec(SQL_HANDLE_STMT, fHstmt, ++i, state, &native, text,
00317                           sizeof(text), &len );
00318       if (ret == SQL_SUCCESS) SetError(native, (const char*) text, method);
00319 //         Error(method, "%s:%ld:%ld:%s\n", state, i, native, text);
00320    }
00321    while( ret == SQL_SUCCESS );
00322    return kTRUE;
00323 }
00324 
00325 //______________________________________________________________________________
00326 Bool_t TODBCStatement::NextIteration()
00327 {
00328    //run next iteration
00329 
00330    ClearError();
00331 
00332    if (!IsParSettMode() || (fBuffer==0) || (fBufferLength<=0)) return kFALSE;
00333 
00334    if (fBufferCounter>=fBufferLength-1) {
00335       SQLRETURN retcode = SQLExecute(fHstmt);
00336       if (ExtractErrors(retcode,"NextIteration")) return kFALSE;
00337       fBufferCounter = 0;
00338    } else
00339       fBufferCounter++;
00340 
00341    // probably, we do not need it, but anyway
00342    fStatusBuffer[fBufferCounter] = SQL_ROW_SUCCESS;
00343 
00344    return kTRUE;
00345 }
00346 
00347 //______________________________________________________________________________
00348 Int_t TODBCStatement::GetNumParameters()
00349 {
00350    //return number of parameters
00351 
00352    return IsParSettMode() ? fNumBuffers : 0;
00353 }
00354 
00355 //______________________________________________________________________________
00356 void TODBCStatement::SetNumBuffers(Int_t isize, Int_t ilen)
00357 {
00358    //set number of buffers
00359 
00360    FreeBuffers();
00361 
00362    fNumBuffers = isize;
00363    fBufferLength = ilen;
00364    fBufferCounter = 0;
00365 
00366    fBuffer = new ODBCBufferRec_t[fNumBuffers];
00367    for (Int_t n=0;n<fNumBuffers;n++) {
00368       fBuffer[n].fBroottype = 0;
00369       fBuffer[n].fBsqltype = 0;
00370       fBuffer[n].fBsqlctype = 0;
00371       fBuffer[n].fBbuffer = 0;
00372       fBuffer[n].fBelementsize = 0;
00373       fBuffer[n].fBlenarray = 0;
00374       fBuffer[n].fBstrbuffer = 0;
00375       fBuffer[n].fBnamebuffer = 0;
00376    }
00377 
00378    fStatusBuffer = new SQLUSMALLINT[fBufferLength];
00379 }
00380 
00381 //______________________________________________________________________________
00382 void TODBCStatement::FreeBuffers()
00383 {
00384    // Free allocated buffers
00385 
00386    if (fBuffer==0) return;
00387    for (Int_t n=0;n<fNumBuffers;n++) {
00388       if (fBuffer[n].fBbuffer!=0)
00389         free(fBuffer[n].fBbuffer);
00390       delete[] fBuffer[n].fBlenarray;
00391       delete[] fBuffer[n].fBstrbuffer;
00392       delete[] fBuffer[n].fBnamebuffer;
00393    }
00394 
00395    delete[] fStatusBuffer;
00396    delete[] fBuffer;
00397    fBuffer = 0;
00398    fNumBuffers = 0;
00399    fBufferLength = 0;
00400    fStatusBuffer = 0;
00401 }
00402 
00403 //______________________________________________________________________________
00404 Bool_t TODBCStatement::BindColumn(Int_t ncol, SQLSMALLINT sqltype, SQLUINTEGER size)
00405 {
00406    // Bind result column to buffer. Allocate buffer of appropriate type
00407 
00408    ClearError();
00409 
00410    if ((ncol<0) || (ncol>=fNumBuffers)) {
00411       SetError(-1,"Internal error. Column number invalid","BindColumn");
00412       return kFALSE;
00413    }
00414 
00415    if (fBuffer[ncol].fBsqltype!=0) {
00416       SetError(-1,"Internal error. Bind for column already done","BindColumn");
00417       return kFALSE;
00418    }
00419 
00420    SQLSMALLINT sqlctype = 0;
00421    switch (sqltype) {
00422       case SQL_CHAR:
00423       case SQL_VARCHAR:   sqlctype = SQL_C_CHAR; break;
00424       case SQL_BINARY:
00425       case SQL_LONGVARBINARY:
00426       case SQL_VARBINARY: sqlctype = SQL_C_BINARY; break;
00427       case SQL_LONGVARCHAR: Info("BindColumn","BIG VARCHAR not supported yet"); return kFALSE; break;
00428 
00429       case SQL_DECIMAL:   sqlctype = SQL_C_DOUBLE; break;
00430       case SQL_NUMERIC:   sqlctype = SQL_C_DOUBLE; break;
00431       case SQL_SMALLINT:  sqlctype = SQL_C_SLONG; break;
00432       case SQL_INTEGER:   sqlctype = SQL_C_SLONG; break;
00433       case SQL_FLOAT:     sqlctype = SQL_C_FLOAT; break;
00434       case SQL_REAL:
00435       case SQL_DOUBLE:    sqlctype = SQL_C_DOUBLE; break;
00436       case SQL_TINYINT:   sqlctype = SQL_C_STINYINT; break;
00437       case SQL_BIGINT:    sqlctype = SQL_C_SBIGINT; break;
00438       case SQL_TYPE_DATE: sqlctype = SQL_C_TYPE_DATE; break;
00439       case SQL_TYPE_TIME: sqlctype = SQL_C_TYPE_TIME; break;
00440       case SQL_TYPE_TIMESTAMP: sqlctype = SQL_C_TYPE_TIMESTAMP; break;
00441       default: {
00442          SetError(-1, Form("SQL type %d not supported",sqltype), "BindColumn");
00443          return kFALSE;
00444       }
00445    }
00446 
00447    int elemsize = 0;
00448 
00449    switch (sqlctype) {
00450       case SQL_C_ULONG:    elemsize = sizeof(SQLUINTEGER); break;
00451       case SQL_C_SLONG:    elemsize = sizeof(SQLINTEGER); break;
00452       case SQL_C_UBIGINT:  elemsize = sizeof(ULong64_t); break; // should be SQLUBIGINT, but it is 64-bit structure on some platforms
00453       case SQL_C_SBIGINT:  elemsize = sizeof(Long64_t); break; // should be SQLBIGINT, but it is 64-bit structure on some platforms
00454       case SQL_C_USHORT:   elemsize = sizeof(SQLUSMALLINT); break;
00455       case SQL_C_SSHORT:   elemsize = sizeof(SQLSMALLINT); break;
00456       case SQL_C_UTINYINT: elemsize = sizeof(SQLCHAR); break;
00457       case SQL_C_STINYINT: elemsize = sizeof(SQLSCHAR); break;
00458       case SQL_C_FLOAT:    elemsize = sizeof(SQLREAL); break;
00459       case SQL_C_DOUBLE:   elemsize = sizeof(SQLDOUBLE); break;
00460       case SQL_C_CHAR:     elemsize = size; break;
00461       case SQL_C_BINARY:   elemsize = size; break;
00462       case SQL_C_TYPE_DATE: elemsize = sizeof(DATE_STRUCT); break;
00463       case SQL_C_TYPE_TIME: elemsize = sizeof(TIME_STRUCT); break;
00464       case SQL_C_TYPE_TIMESTAMP: elemsize = sizeof(TIMESTAMP_STRUCT); break;
00465 
00466       default: {
00467          SetError(-1, Form("SQL C Type %d is not supported",sqlctype), "BindColumn");
00468          return kFALSE;
00469       }
00470    }
00471 
00472    fBuffer[ncol].fBroottype    = 0;
00473    fBuffer[ncol].fBsqltype     = sqltype;
00474    fBuffer[ncol].fBsqlctype    = sqlctype;
00475    fBuffer[ncol].fBbuffer      = malloc(elemsize * fBufferLength);
00476    fBuffer[ncol].fBelementsize = elemsize;
00477    fBuffer[ncol].fBlenarray    = new SQLLEN[fBufferLength];
00478 
00479    SQLRETURN retcode =
00480       SQLBindCol(fHstmt, ncol+1, sqlctype, fBuffer[ncol].fBbuffer,
00481                  elemsize,
00482                  fBuffer[ncol].fBlenarray);
00483 
00484    return !ExtractErrors(retcode, "BindColumn");
00485 }
00486 
00487 //______________________________________________________________________________
00488 Bool_t TODBCStatement::BindParam(Int_t npar, Int_t roottype, Int_t size)
00489 {
00490    // Bind query parameter with buffer. Creates buffer of appropriate type
00491 
00492    ClearError();
00493 
00494    if ((npar<0) || (npar>=fNumBuffers)) return kFALSE;
00495 
00496    if (fBuffer[npar].fBroottype!=0) {
00497       SetError(-1,Form("ParameterType for par %d already specified", npar),"BindParam");
00498       return kFALSE;
00499    }
00500 
00501    SQLSMALLINT sqltype = 0, sqlctype = 0;
00502    int elemsize = 0;
00503 
00504    switch (roottype) {
00505       case kUInt_t:     sqltype = SQL_INTEGER; sqlctype = SQL_C_ULONG;    elemsize = sizeof(SQLUINTEGER); break;
00506       case kInt_t:      sqltype = SQL_INTEGER; sqlctype = SQL_C_SLONG;    elemsize = sizeof(SQLINTEGER); break;
00507       case kULong_t:    sqltype = SQL_INTEGER; sqlctype = SQL_C_ULONG;    elemsize = sizeof(SQLUINTEGER); break;
00508       case kLong_t:     sqltype = SQL_INTEGER; sqlctype = SQL_C_SLONG;    elemsize = sizeof(SQLINTEGER); break;
00509 
00510       // here SQLUBIGINT/SQLBIGINT types should be used,
00511        // but on 32-bit platforms it is structures, which makes its usage inconvinient
00512       case kULong64_t:  sqltype = SQL_BIGINT;  sqlctype = SQL_C_UBIGINT;  elemsize = sizeof(ULong64_t); break;
00513       case kLong64_t:   sqltype = SQL_BIGINT;  sqlctype = SQL_C_SBIGINT;  elemsize = sizeof(Long64_t); break;
00514 
00515       case kUShort_t:   sqltype = SQL_SMALLINT;sqlctype = SQL_C_USHORT;   elemsize = sizeof(SQLUSMALLINT); break;
00516       case kShort_t:    sqltype = SQL_SMALLINT;sqlctype = SQL_C_SSHORT;   elemsize = sizeof(SQLSMALLINT); break;
00517       case kUChar_t:    sqltype = SQL_TINYINT; sqlctype = SQL_C_UTINYINT; elemsize = sizeof(SQLCHAR); break;
00518       case kChar_t:     sqltype = SQL_TINYINT; sqlctype = SQL_C_STINYINT; elemsize = sizeof(SQLSCHAR); break;
00519       case kBool_t:     sqltype = SQL_TINYINT; sqlctype = SQL_C_UTINYINT; elemsize = sizeof(SQLCHAR); break;
00520       case kFloat_t:    sqltype = SQL_FLOAT;   sqlctype = SQL_C_FLOAT;    elemsize = sizeof(SQLREAL); break;
00521       case kFloat16_t:  sqltype = SQL_FLOAT;   sqlctype = SQL_C_FLOAT;    elemsize = sizeof(SQLREAL); break;
00522       case kDouble_t:   sqltype = SQL_DOUBLE;  sqlctype = SQL_C_DOUBLE;   elemsize = sizeof(SQLDOUBLE); break;
00523       case kDouble32_t: sqltype = SQL_DOUBLE;  sqlctype = SQL_C_DOUBLE;   elemsize = sizeof(SQLDOUBLE); break;
00524       case kCharStar:   sqltype = SQL_CHAR;    sqlctype = SQL_C_CHAR;     elemsize = size; break;
00525       case kSqlBinary:  sqltype = SQL_BINARY;  sqlctype = SQL_C_BINARY;   elemsize = size; break;
00526       case kSqlDate:    sqltype = SQL_TYPE_DATE; sqlctype = SQL_C_TYPE_DATE; elemsize = sizeof(DATE_STRUCT); break;
00527       case kSqlTime:    sqltype = SQL_TYPE_TIME; sqlctype = SQL_C_TYPE_TIME; elemsize = sizeof(TIME_STRUCT); break;
00528       case kSqlTimestamp: sqltype = SQL_TYPE_TIMESTAMP; sqlctype = SQL_C_TYPE_TIMESTAMP; elemsize = sizeof(TIMESTAMP_STRUCT); break;
00529       default: {
00530          SetError(-1, Form("Root type %d is not supported", roottype), "BindParam");
00531          return kFALSE;
00532       }
00533    }
00534 
00535    void* buffer = malloc(elemsize * fBufferLength);
00536    SQLLEN* lenarray = new SQLLEN[fBufferLength];
00537    SQLRETURN retcode =
00538       SQLBindParameter(fHstmt, npar+1, SQL_PARAM_INPUT,
00539                        sqlctype, sqltype, 0, 0,
00540                        buffer, elemsize, lenarray);
00541 
00542    if (ExtractErrors(retcode, "BindParam")) {
00543       free(buffer);
00544       delete[] lenarray;
00545       return kFALSE;
00546    }
00547 
00548    fBuffer[npar].fBroottype = roottype;
00549    fBuffer[npar].fBsqlctype = sqlctype;
00550    fBuffer[npar].fBsqltype = sqltype;
00551    fBuffer[npar].fBbuffer = buffer;
00552    fBuffer[npar].fBelementsize = elemsize;
00553    fBuffer[npar].fBlenarray = lenarray;
00554 
00555    return kTRUE;
00556 }
00557 
00558 //______________________________________________________________________________
00559 void* TODBCStatement::GetParAddr(Int_t npar, Int_t roottype, Int_t length)
00560 {
00561    // Get parameter address
00562 
00563    ClearError();
00564 
00565    if ((fBuffer==0) || (npar<0) || (npar>=fNumBuffers) || (fBufferCounter<0)) {
00566       SetError(-1, "Invalid parameter number","GetParAddr");
00567       return 0;
00568    }
00569 
00570    if (fBuffer[npar].fBbuffer==0) {
00571       if (IsParSettMode() && (roottype!=0) && (fBufferCounter==0))
00572          if (!BindParam(npar, roottype, length)) return 0;
00573 
00574       if (fBuffer[npar].fBbuffer==0) return 0;
00575    }
00576 
00577    if (roottype!=0)
00578       if (fBuffer[npar].fBroottype!=roottype) return 0;
00579 
00580    return (char*)fBuffer[npar].fBbuffer + fBufferCounter*fBuffer[npar].fBelementsize;
00581 }
00582 
00583 //______________________________________________________________________________
00584 long double TODBCStatement::ConvertToNumeric(Int_t npar)
00585 {
00586    //convert to numeric type
00587    void* addr = GetParAddr(npar);
00588    if (addr==0) return 0;
00589 
00590    switch (fBuffer[npar].fBsqlctype) {
00591       case SQL_C_ULONG:    return *((SQLUINTEGER*) addr); break;
00592       case SQL_C_SLONG:    return *((SQLINTEGER*) addr); break;
00593       case SQL_C_UBIGINT:  return *((ULong64_t*) addr); break;
00594       case SQL_C_SBIGINT:  return *((Long64_t*) addr); break;
00595       case SQL_C_USHORT:   return *((SQLUSMALLINT*) addr); break;
00596       case SQL_C_SSHORT:   return *((SQLSMALLINT*) addr); break;
00597       case SQL_C_UTINYINT: return *((SQLCHAR*) addr); break;
00598       case SQL_C_STINYINT: return *((SQLSCHAR*) addr); break;
00599       case SQL_C_FLOAT:    return *((SQLREAL*) addr); break;
00600       case SQL_C_DOUBLE:   return *((SQLDOUBLE*) addr); break;
00601       case SQL_C_TYPE_DATE: {
00602          DATE_STRUCT* dt = (DATE_STRUCT*) addr;
00603          TDatime rtm(dt->year, dt->month,  dt->day, 0, 0, 0);
00604          return rtm.GetDate();
00605          break;
00606       }
00607       case SQL_C_TYPE_TIME: {
00608          TIME_STRUCT* tm = (TIME_STRUCT*) addr;
00609          TDatime rtm(2000, 1, 1, tm->hour, tm->minute, tm->second);
00610          return rtm.GetTime();
00611          break;
00612       }
00613       case SQL_C_TYPE_TIMESTAMP: {
00614          TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
00615          TDatime rtm(tm->year, tm->month,  tm->day,
00616                      tm->hour, tm->minute, tm->second);
00617          return rtm.Get();
00618          break;
00619       }
00620    }
00621    return 0;
00622 }
00623 
00624 //______________________________________________________________________________
00625 const char* TODBCStatement::ConvertToString(Int_t npar)
00626 {
00627    //convert to string
00628    void* addr = GetParAddr(npar);
00629    if (addr==0) return 0;
00630    if (fBuffer[npar].fBstrbuffer==0)
00631       fBuffer[npar].fBstrbuffer = new char[100];
00632 
00633    char* buf = fBuffer[npar].fBstrbuffer;
00634 
00635    switch(fBuffer[npar].fBsqlctype) {
00636 #if (SIZEOF_LONG == 8)
00637       case SQL_C_SLONG:   snprintf(buf, 100, "%d", *((SQLINTEGER*) addr)); break;
00638       case SQL_C_ULONG:   snprintf(buf, 100, "%u", *((SQLUINTEGER*) addr)); break;
00639 #else
00640       case SQL_C_SLONG:   snprintf(buf, 100, "%ld", *((SQLINTEGER*) addr)); break;
00641       case SQL_C_ULONG:   snprintf(buf, 100, "%lu", *((SQLUINTEGER*) addr)); break;
00642 #endif
00643       case SQL_C_SBIGINT: snprintf(buf, 100, "%lld", *((Long64_t*) addr)); break;
00644       case SQL_C_UBIGINT: snprintf(buf, 100, "%llu", *((ULong64_t*) addr)); break;
00645       case SQL_C_SSHORT:  snprintf(buf, 100, "%hd", *((SQLSMALLINT*) addr)); break;
00646       case SQL_C_USHORT:  snprintf(buf, 100, "%hu", *((SQLUSMALLINT*) addr)); break;
00647       case SQL_C_STINYINT:snprintf(buf, 100, "%d", *((SQLSCHAR*) addr)); break;
00648       case SQL_C_UTINYINT:snprintf(buf, 100, "%u", *((SQLCHAR*) addr)); break;
00649       case SQL_C_FLOAT:   snprintf(buf, 100, TSQLServer::GetFloatFormat(), *((SQLREAL*) addr)); break;
00650       case SQL_C_DOUBLE:  snprintf(buf, 100, TSQLServer::GetFloatFormat(), *((SQLDOUBLE*) addr)); break;
00651       case SQL_C_TYPE_DATE: {
00652          DATE_STRUCT* dt = (DATE_STRUCT*) addr;
00653          snprintf(buf,100,"%4.4d-%2.2d-%2.2d",
00654                   dt->year, dt->month,  dt->day);
00655          break;
00656       }
00657       case SQL_C_TYPE_TIME: {
00658          TIME_STRUCT* tm = (TIME_STRUCT*) addr;
00659          snprintf(buf,100,"%2.2d:%2.2d:%2.2d",
00660                   tm->hour, tm->minute, tm->second);
00661          break;
00662       }
00663       case SQL_C_TYPE_TIMESTAMP: {
00664          TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
00665          snprintf(buf,100,"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
00666                   tm->year, tm->month,  tm->day,
00667                   tm->hour, tm->minute, tm->second);
00668          break;
00669       }
00670       default: return 0;
00671    }
00672 
00673    return buf;
00674 }
00675 
00676 //______________________________________________________________________________
00677 Bool_t TODBCStatement::IsNull(Int_t npar)
00678 {
00679    // Verifies if field value is NULL
00680 
00681    void* addr = GetParAddr(npar);
00682    if (addr==0) return kTRUE;
00683 
00684    return fBuffer[npar].fBlenarray[fBufferCounter] == SQL_NULL_DATA;
00685 }
00686 
00687 //______________________________________________________________________________
00688 Int_t TODBCStatement::GetInt(Int_t npar)
00689 {
00690    //get parameter as integer
00691    void* addr = GetParAddr(npar);
00692    if (addr==0) return 0;
00693 
00694    if (fBuffer[npar].fBsqlctype==SQL_C_SLONG)
00695       return (Int_t) *((SQLINTEGER*) addr);
00696 
00697    return (Int_t) ConvertToNumeric(npar);
00698 }
00699 
00700 //______________________________________________________________________________
00701 UInt_t TODBCStatement::GetUInt(Int_t npar)
00702 {
00703    //get parameter as unsigned integer
00704    void* addr = GetParAddr(npar);
00705    if (addr==0) return 0;
00706 
00707    if (fBuffer[npar].fBsqlctype==SQL_C_ULONG)
00708       return (UInt_t) *((SQLUINTEGER*) addr);
00709 
00710    return (UInt_t) ConvertToNumeric(npar);
00711 }
00712 
00713 //______________________________________________________________________________
00714 Long_t TODBCStatement::GetLong(Int_t npar)
00715 {
00716    //get parameter as Long_t
00717    void* addr = GetParAddr(npar);
00718    if (addr==0) return 0;
00719 
00720    if (fBuffer[npar].fBsqlctype==SQL_C_SLONG)
00721      return (Long_t) *((SQLINTEGER*) addr);
00722 
00723    return (Long_t) ConvertToNumeric(npar);
00724 }
00725 
00726 //______________________________________________________________________________
00727 Long64_t TODBCStatement::GetLong64(Int_t npar)
00728 {
00729    //get parameter as Long64_t
00730    void* addr = GetParAddr(npar);
00731    if (addr==0) return 0;
00732 
00733    if (fBuffer[npar].fBsqlctype==SQL_C_SBIGINT)
00734      return *((Long64_t*) addr);
00735 
00736    return (Long64_t) ConvertToNumeric(npar);
00737 }
00738 
00739 //______________________________________________________________________________
00740 ULong64_t TODBCStatement::GetULong64(Int_t npar)
00741 {
00742    //get parameter as ULong64_t
00743    void* addr = GetParAddr(npar);
00744    if (addr==0) return 0;
00745 
00746    if (fBuffer[npar].fBsqlctype==SQL_C_UBIGINT)
00747      return *((ULong64_t*) addr);
00748 
00749    return (ULong64_t) ConvertToNumeric(npar);
00750 }
00751 
00752 //______________________________________________________________________________
00753 Double_t TODBCStatement::GetDouble(Int_t npar)
00754 {
00755    //get parameter as Double_t
00756    void* addr = GetParAddr(npar);
00757    if (addr==0) return 0;
00758 
00759    if (fBuffer[npar].fBsqlctype==SQL_C_DOUBLE)
00760      return *((SQLDOUBLE*) addr);
00761 
00762    return (Double_t) ConvertToNumeric(npar);
00763 }
00764 
00765 //______________________________________________________________________________
00766 const char* TODBCStatement::GetString(Int_t npar)
00767 {
00768    //get parameter as string
00769 
00770    void* addr = GetParAddr(npar);
00771    if (addr==0) return 0;
00772 
00773    if (fBuffer[npar].fBsqlctype==SQL_C_CHAR) {
00774       // first check if string is null
00775 
00776       int len = fBuffer[npar].fBlenarray[fBufferCounter];
00777 
00778       if ((len == SQL_NULL_DATA) || (len==0)) return 0;
00779 
00780       char* res = (char*) addr;
00781       if (len < fBuffer[npar].fBelementsize) {
00782          *(res + len) = 0;
00783          return res;
00784       }
00785 
00786       if (len > fBuffer[npar].fBelementsize) {
00787          SetError(-1, Form("Problems with string size %d", len), "GetString");
00788          return 0;
00789       }
00790 
00791       if (fBuffer[npar].fBstrbuffer==0)
00792          fBuffer[npar].fBstrbuffer = new char[len+1];
00793 
00794       strlcpy(fBuffer[npar].fBstrbuffer, res, len+1);
00795 
00796       res = fBuffer[npar].fBstrbuffer;
00797       *(res + len) = 0;
00798       return res;
00799    }
00800 
00801    return ConvertToString(npar);
00802 }
00803 
00804 //______________________________________________________________________________
00805 Bool_t TODBCStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
00806 {
00807    // return parameter as binary data
00808 
00809    mem = 0;
00810    size = 0;
00811 
00812    void* addr = GetParAddr(npar);
00813    if (addr==0) return kFALSE;
00814 
00815    if ((fBuffer[npar].fBsqlctype==SQL_C_BINARY) ||
00816        (fBuffer[npar].fBsqlctype==SQL_C_CHAR)) {
00817 
00818       // first check if data length is null
00819       int len = fBuffer[npar].fBlenarray[fBufferCounter];
00820 
00821       if ((len == SQL_NULL_DATA) || (len==0)) return kTRUE;
00822 
00823       size = len;
00824 
00825       if (fBuffer[npar].fBstrbuffer==0)
00826          fBuffer[npar].fBstrbuffer = new char[size];
00827 
00828       memcpy(fBuffer[npar].fBstrbuffer, addr, size);
00829 
00830       mem = fBuffer[npar].fBstrbuffer;
00831 
00832       return kTRUE;
00833    }
00834 
00835    return kFALSE;
00836 }
00837 
00838 
00839 //______________________________________________________________________________
00840 Bool_t TODBCStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
00841 {
00842    // return field value as date
00843 
00844    void* addr = GetParAddr(npar);
00845    if (addr==0) return kFALSE;
00846 
00847    if (fBuffer[npar].fBsqlctype!=SQL_C_TYPE_DATE) return kFALSE;
00848 
00849    DATE_STRUCT* dt = (DATE_STRUCT*) addr;
00850    year = dt->year;
00851    month = dt->month;
00852    day = dt->day;
00853 
00854    return kTRUE;
00855 }
00856 
00857 //______________________________________________________________________________
00858 Bool_t TODBCStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
00859 {
00860    // return field value as time
00861 
00862    void* addr = GetParAddr(npar);
00863    if (addr==0) return kFALSE;
00864 
00865    if (fBuffer[npar].fBsqlctype!=SQL_C_TYPE_TIME) return kFALSE;
00866 
00867    TIME_STRUCT* tm = (TIME_STRUCT*) addr;
00868    hour = tm->hour;
00869    min = tm->minute;
00870    sec = tm->second;
00871 
00872    return kTRUE;
00873 }
00874 
00875 //______________________________________________________________________________
00876 Bool_t TODBCStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
00877 {
00878    // return field value as date & time
00879 
00880    void* addr = GetParAddr(npar);
00881    if (addr==0) return kFALSE;
00882 
00883    if (fBuffer[npar].fBsqlctype!=SQL_C_TYPE_TIMESTAMP) return kFALSE;
00884 
00885    TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
00886 
00887    year = tm->year;
00888    month = tm->month;
00889    day = tm->day;
00890    hour = tm->hour;
00891    min = tm->minute;
00892    sec = tm->second;
00893    return kTRUE;
00894 }
00895 
00896 //______________________________________________________________________________
00897 Bool_t TODBCStatement::GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t& frac)
00898 {
00899    // return field value as time stamp
00900 
00901    void* addr = GetParAddr(npar);
00902    if (addr==0) return kFALSE;
00903 
00904    if (fBuffer[npar].fBsqlctype!=SQL_C_TYPE_TIMESTAMP) return kFALSE;
00905 
00906    TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
00907 
00908    year = tm->year;
00909    month = tm->month;
00910    day = tm->day;
00911    hour = tm->hour;
00912    min = tm->minute;
00913    sec = tm->second;
00914    frac = tm->fraction;
00915    return kTRUE;
00916 }
00917 
00918 
00919 //______________________________________________________________________________
00920 Bool_t TODBCStatement::SetNull(Int_t npar)
00921 {
00922    // Set NULL as parameter value
00923    // If NULL should be set for statement parameter during first iteration,
00924    // one should call before proper Set... method to identify type of argument for
00925    // the future. For instance, if one suppose to have double as type of parameter,
00926    // code should look like:
00927    //    stmt->SetDouble(2, 0.);
00928    //    stmt->SetNull(2);
00929 
00930    void* addr = GetParAddr(npar, kInt_t);
00931    if (addr!=0)
00932       *((SQLINTEGER*) addr) = 0;
00933 
00934    if ((npar>=0) && (npar<fNumBuffers))
00935       fBuffer[npar].fBlenarray[fBufferCounter] = SQL_NULL_DATA;
00936 
00937    return kTRUE;
00938 }
00939 
00940 //______________________________________________________________________________
00941 Bool_t TODBCStatement::SetInt(Int_t npar, Int_t value)
00942 {
00943    //set parameter as Int_t
00944    void* addr = GetParAddr(npar, kInt_t);
00945    if (addr==0) return kFALSE;
00946 
00947    *((SQLINTEGER*) addr) = value;
00948 
00949    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
00950 
00951    return kTRUE;
00952 }
00953 
00954 //______________________________________________________________________________
00955 Bool_t TODBCStatement::SetUInt(Int_t npar, UInt_t value)
00956 {
00957    //set parameter as UInt_t
00958    void* addr = GetParAddr(npar, kUInt_t);
00959    if (addr==0) return kFALSE;
00960 
00961    *((SQLUINTEGER*) addr) = value;
00962 
00963    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
00964 
00965    return kTRUE;
00966 }
00967 
00968 //______________________________________________________________________________
00969 Bool_t TODBCStatement::SetLong(Int_t npar, Long_t value)
00970 {
00971    //set parameter as Long_t
00972    void* addr = GetParAddr(npar, kLong_t);
00973    if (addr==0) return kFALSE;
00974 
00975    *((SQLINTEGER*) addr) = value;
00976 
00977    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
00978 
00979    return kTRUE;
00980 }
00981 
00982 //______________________________________________________________________________
00983 Bool_t TODBCStatement::SetLong64(Int_t npar, Long64_t value)
00984 {
00985    //set parameter as Long64_t
00986    void* addr = GetParAddr(npar, kLong64_t);
00987    if (addr==0) return kFALSE;
00988 
00989    *((Long64_t*) addr) = value;
00990 
00991    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
00992 
00993    return kTRUE;
00994 }
00995 
00996 //______________________________________________________________________________
00997 Bool_t TODBCStatement::SetULong64(Int_t npar, ULong64_t value)
00998 {
00999    //set parameter as ULong64_t
01000 
01001    void* addr = GetParAddr(npar, kULong64_t);
01002    if (addr==0) return kFALSE;
01003 
01004    *((ULong64_t*) addr) = value;
01005 
01006    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01007 
01008    return kTRUE;
01009 }
01010 
01011 //______________________________________________________________________________
01012 Bool_t TODBCStatement::SetDouble(Int_t npar, Double_t value)
01013 {
01014    //set parameter as Double_t
01015 
01016    void* addr = GetParAddr(npar, kDouble_t);
01017    if (addr==0) return kFALSE;
01018 
01019    *((SQLDOUBLE*) addr) = value;
01020 
01021    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01022 
01023    return kTRUE;
01024 }
01025 
01026 //______________________________________________________________________________
01027 Bool_t TODBCStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
01028 {
01029    //set parameter as string
01030    void* addr = GetParAddr(npar, kCharStar, maxsize);
01031 
01032    if (addr==0) return kFALSE;
01033 
01034    int len = value==0 ? 0 : strlen(value);
01035 
01036    if (len>=fBuffer[npar].fBelementsize) {
01037       len = fBuffer[npar].fBelementsize;
01038       strlcpy((char*) addr, value, len+1);
01039       fBuffer[npar].fBlenarray[fBufferCounter] = len;
01040    } else
01041    if (len>0) {
01042       strcpy((char*) addr, value);
01043       fBuffer[npar].fBlenarray[fBufferCounter] = SQL_NTS;
01044    } else {
01045       *((char*) addr) = 0;
01046       fBuffer[npar].fBlenarray[fBufferCounter] = SQL_NTS;
01047    }
01048 
01049    return kTRUE;
01050 }
01051 
01052 //______________________________________________________________________________
01053 Bool_t TODBCStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize)
01054 {
01055    //set parameter value as binary data
01056 
01057    void* addr = GetParAddr(npar, kSqlBinary, maxsize);
01058    if (addr==0) return kFALSE;
01059 
01060    if (size>fBuffer[npar].fBelementsize)
01061       size = fBuffer[npar].fBelementsize;
01062 
01063    memcpy(addr, mem, size);
01064    fBuffer[npar].fBlenarray[fBufferCounter] = size;
01065 
01066    return kTRUE;
01067 }
01068 
01069 //______________________________________________________________________________
01070 Bool_t TODBCStatement::SetDate(Int_t npar, Int_t year, Int_t month, Int_t day)
01071 {
01072    // set parameter value as date
01073 
01074    void* addr = GetParAddr(npar, kSqlDate);
01075    if (addr==0) return kFALSE;
01076 
01077    DATE_STRUCT* dt = (DATE_STRUCT*) addr;
01078    dt->year = year;
01079    dt->month = month;
01080    dt->day = day;
01081 
01082    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01083 
01084    return kTRUE;
01085 }
01086 
01087 //______________________________________________________________________________
01088 Bool_t TODBCStatement::SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec)
01089 {
01090    // set parameter value as time
01091 
01092    void* addr = GetParAddr(npar, kSqlTime);
01093    if (addr==0) return kFALSE;
01094 
01095    TIME_STRUCT* tm = (TIME_STRUCT*) addr;
01096    tm->hour = hour;
01097    tm->minute = min;
01098    tm->second = sec;
01099 
01100    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01101 
01102    return kTRUE;
01103 }
01104 
01105 //______________________________________________________________________________
01106 Bool_t TODBCStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
01107 {
01108    // set parameter value as date & time
01109 
01110    void* addr = GetParAddr(npar, kSqlTimestamp);
01111    if (addr==0) return kFALSE;
01112 
01113    TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
01114    tm->year = year;
01115    tm->month = month;
01116    tm->day = day;
01117    tm->hour = hour;
01118    tm->minute = min;
01119    tm->second = sec;
01120    tm->fraction = 0;
01121 
01122    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01123 
01124    return kTRUE;
01125 }
01126 
01127 //______________________________________________________________________________
01128 Bool_t TODBCStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t frac)
01129 {
01130    // set parameter value as timestamp
01131 
01132    void* addr = GetParAddr(npar, kSqlTimestamp);
01133    if (addr==0) return kFALSE;
01134 
01135    TIMESTAMP_STRUCT* tm = (TIMESTAMP_STRUCT*) addr;
01136    tm->year = year;
01137    tm->month = month;
01138    tm->day = day;
01139    tm->hour = hour;
01140    tm->minute = min;
01141    tm->second = sec;
01142    tm->fraction = frac;
01143 
01144    fBuffer[npar].fBlenarray[fBufferCounter] = 0;
01145 
01146    return kTRUE;
01147 }

Generated on Tue Jul 5 15:14:38 2011 for ROOT_528-00b_version by  doxygen 1.5.1