From 8aa8bb839d93fdbd2181a7bd5eef7aab81b39a0f Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Tue, 5 Sep 2006 13:37:08 +0000
Subject: [PATCH] From Sergey Linev: 1. Support of
 date/time/date&time/timestamp data introduced in TSQLStatement    All such
 data now can be accessed without text conversion.    The following methods
 can be used:

   SetTime()/GetTime() - only time (hour:min:sec),
   SetDate()/GetDate() - only date (year-month-day),
   SetDatime()/GetDatime() - date and time
   SetTimestamp()/GetTimestamp() - timestamp with seconds fraction
   For some of these methods TDatime type can be used as parameter / return value.
   Be aware, that TDatime supports only dates after 1995-01-01.
   There are also methods to get separately year, month, day, hour, minutes and seconds.

2. Support of binary data in TSQLStatement
    Most of modern data bases support just binary data, which is
    typically has SQL type name 'BLOB'. To access data in such
    columns, GetBinary()/SetBinary() methods should be used.
    Current implementation supposes, that complete content of the
    column must be retrieved at once. Therefore very big data of
    gigabytes size may cause a problem.


git-svn-id: http://root.cern.ch/svn/root/trunk@16204 27541ba8-7e3a-0410-8455-c3a389f83636
---
 mysql/inc/TMySQLStatement.h     |  14 +-
 mysql/src/TMySQLStatement.cxx   | 357 ++++++++++++++++++++++++++++++--
 net/inc/TSQLStatement.h         |  29 ++-
 net/src/TSQLStatement.cxx       | 175 +++++++++++++++-
 odbc/inc/TODBCStatement.h       |  12 +-
 oracle/inc/TOracleStatement.h   |  21 +-
 oracle/src/TOracleRow.cxx       |  20 +-
 oracle/src/TOracleServer.cxx    |   8 +-
 oracle/src/TOracleStatement.cxx | 310 ++++++++++++++++++++++++---
 9 files changed, 881 insertions(+), 65 deletions(-)

diff --git a/mysql/inc/TMySQLStatement.h b/mysql/inc/TMySQLStatement.h
index 97dd3412f39..609b8e6ce20 100644
--- a/mysql/inc/TMySQLStatement.h
+++ b/mysql/inc/TMySQLStatement.h
@@ -1,4 +1,4 @@
-// @(#)root/mysql:$Name:  $:$Id: TMySQLStatement.h,v 1.4 2006/06/25 18:43:24 brun Exp $
+// @(#)root/mysql:$Name:  $:$Id: TMySQLStatement.h,v 1.5 2006/06/29 20:36:43 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -67,7 +67,7 @@ private:
    void        FreeBuffers();
    void        SetBuffersNumber(Int_t n);
 
-   void       *BeforeSet(Int_t npar, Int_t sqltype, Bool_t sig = kTRUE, Int_t size = 0);
+   void       *BeforeSet(const char* method, Int_t npar, Int_t sqltype, Bool_t sig = kTRUE, Int_t size = 0);
 
 public:
    TMySQLStatement(MYSQL_STMT* stmt, Bool_t errout = kTRUE);
@@ -86,6 +86,11 @@ public:
    virtual Bool_t      SetULong64(Int_t npar, ULong64_t value);
    virtual Bool_t      SetDouble(Int_t npar, Double_t value);
    virtual Bool_t      SetString(Int_t npar, const char* value, Int_t maxsize = 256);
+   virtual Bool_t      SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize = 0x1000);
+   virtual Bool_t      SetDate(Int_t npar, Int_t year, Int_t month, Int_t day);
+   virtual Bool_t      SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      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 = 0);
 
    virtual Bool_t      NextIteration();
 
@@ -105,6 +110,11 @@ public:
    virtual ULong64_t   GetULong64(Int_t npar);
    virtual Double_t    GetDouble(Int_t npar);
    virtual const char *GetString(Int_t npar);
+   virtual Bool_t      GetBinary(Int_t npar, void* &mem, Long_t& size);
+   virtual Bool_t      GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day);
+   virtual Bool_t      GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t&);
 
    ClassDef(TMySQLStatement, 0);  // SQL statement class for MySQL DB
 };
diff --git a/mysql/src/TMySQLStatement.cxx b/mysql/src/TMySQLStatement.cxx
index 90c4e13bb37..b84ff498a08 100644
--- a/mysql/src/TMySQLStatement.cxx
+++ b/mysql/src/TMySQLStatement.cxx
@@ -1,4 +1,4 @@
-// @(#)root/mysql:$Name:  $:$Id: TMySQLStatement.cxx,v 1.7 2006/07/17 12:36:49 brun Exp $
+// @(#)root/mysql:$Name:  $:$Id: TMySQLStatement.cxx,v 1.8 2006/08/30 12:55:09 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -310,7 +310,7 @@ void TMySQLStatement::SetBuffersNumber(Int_t numpars)
    memset(fBind, 0, sizeof(MYSQL_BIND)*fNumBuffers);
 
    fBuffer = new TParamData[fNumBuffers];
-   memset(fBuffer, 0, sizeof(fNumBuffers)*fNumBuffers);
+   memset(fBuffer, 0, sizeof(TParamData)*fNumBuffers);
 }
 
 //______________________________________________________________________________
@@ -452,7 +452,6 @@ long double TMySQLStatement::ConvertToNumeric(Int_t npar)
          return rtm.GetTime();
          break;
       }
-
       
       default:
          return 0;
@@ -571,6 +570,140 @@ const char *TMySQLStatement::GetString(Int_t npar)
    return ConvertToString(npar);
 }
 
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
+{
+   // Return field value as binary array 
+
+   mem = 0;  
+   size = 0;
+   
+   CheckGetField("GetBinary", kFALSE);
+
+   if ((fBind[npar].buffer_type==MYSQL_TYPE_STRING) ||
+       (fBind[npar].buffer_type==MYSQL_TYPE_VAR_STRING) ||
+       (fBind[npar].buffer_type==MYSQL_TYPE_BLOB) || 
+       (fBind[npar].buffer_type==MYSQL_TYPE_TINY_BLOB) || 
+       (fBind[npar].buffer_type==MYSQL_TYPE_MEDIUM_BLOB) || 
+       (fBind[npar].buffer_type==MYSQL_TYPE_LONG_BLOB)) {
+         if (fBuffer[npar].fResNull) return kTRUE;
+         mem = fBuffer[npar].fMem;
+         size = fBuffer[npar].fResLength;
+         return kTRUE;
+      }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
+{
+   // return field value as date
+   
+   CheckGetField("GetDate", kFALSE);
+
+   if (fBuffer[npar].fResNull) return kFALSE;
+
+   switch(fBind[npar].buffer_type) {
+      case MYSQL_TYPE_DATETIME:
+      case MYSQL_TYPE_TIMESTAMP: 
+      case MYSQL_TYPE_DATE: {
+         MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
+         if (tm==0) return kFALSE;
+         year = tm->year;
+         month = tm->month;
+         day = tm->day;
+         break;
+      }
+      default:
+         return kFALSE;
+   }
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // return field value as time
+   
+   CheckGetField("GetTime", kFALSE);
+
+   if (fBuffer[npar].fResNull) return kFALSE;
+
+   switch(fBind[npar].buffer_type) {
+      case MYSQL_TYPE_DATETIME:
+      case MYSQL_TYPE_TIMESTAMP: 
+      case MYSQL_TYPE_TIME: {
+         MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
+         if (tm==0) return kFALSE;
+         hour = tm->hour;
+         min = tm->minute;
+         sec = tm->second;
+         break;
+      }
+      default:
+         return kFALSE;
+   }
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // return field value as date & time
+   
+   CheckGetField("GetDatime", kFALSE);
+
+   if (fBuffer[npar].fResNull) return kFALSE;
+
+   switch(fBind[npar].buffer_type) {
+      case MYSQL_TYPE_DATETIME:
+      case MYSQL_TYPE_TIMESTAMP: {
+         MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
+         if (tm==0) return kFALSE;
+         year = tm->year;
+         month = tm->month;
+         day = tm->day;
+         hour = tm->hour;
+         min = tm->minute;
+         sec = tm->second;
+         break;
+      }
+      default:
+         return kFALSE;
+   }
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::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)
+{
+   // return field value as time stamp
+
+   CheckGetField("GetTimstamp", kFALSE);
+
+   if (fBuffer[npar].fResNull) return kFALSE;
+
+   switch(fBind[npar].buffer_type) {
+      case MYSQL_TYPE_DATETIME:
+      case MYSQL_TYPE_TIMESTAMP: {
+         MYSQL_TIME* tm = (MYSQL_TIME*) fBuffer[npar].fMem;
+         if (tm==0) return kFALSE;
+         year = tm->year;
+         month = tm->month;
+         day = tm->day;
+         hour = tm->hour;
+         min = tm->minute;
+         sec = tm->second;
+         frac = 0;
+         break;
+      }
+      default:
+         return kFALSE;
+   }
+   return kTRUE;
+}
+
 //______________________________________________________________________________
 Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, bool sig, int sqlsize)
 {
@@ -587,6 +720,7 @@ Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, bool sig, int s
    fBuffer[npar].fStrBuffer = 0;
 
    int allocsize = 0;
+   bool doreset = false;
 
    switch (sqltype) {
       case MYSQL_TYPE_LONG:     allocsize = sizeof(long);  break;
@@ -601,7 +735,7 @@ Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, bool sig, int s
       case MYSQL_TYPE_TIME:
       case MYSQL_TYPE_DATE:
       case MYSQL_TYPE_TIMESTAMP:
-      case MYSQL_TYPE_DATETIME: allocsize = sizeof(MYSQL_TIME); break;
+      case MYSQL_TYPE_DATETIME: allocsize = sizeof(MYSQL_TIME); doreset = true; break;
       default: SetError(-1,"Nonsupported SQL type","SetSQLParamType"); return kFALSE;
    }
 
@@ -609,6 +743,9 @@ Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, bool sig, int s
    fBuffer[npar].fSize = allocsize;
    fBuffer[npar].fSqlType = sqltype;
    fBuffer[npar].fSign = sig;
+   
+   if ((allocsize>0) && fBuffer[npar].fMem && doreset)
+      memset(fBuffer[npar].fMem, 0, allocsize);
 
    fBind[npar].buffer_type = enum_field_types(sqltype);
    fBind[npar].buffer = fBuffer[npar].fMem;
@@ -621,26 +758,26 @@ Bool_t TMySQLStatement::SetSQLParamType(Int_t npar, int sqltype, bool sig, int s
 }
 
 //______________________________________________________________________________
-void *TMySQLStatement::BeforeSet(Int_t npar, Int_t sqltype, Bool_t sig, Int_t size)
+void *TMySQLStatement::BeforeSet(const char* method, Int_t npar, Int_t sqltype, Bool_t sig, Int_t size)
 {
    // Check boundary condition before setting value of parameter
    // Return address of parameter buffer
-    
+
    ClearError(); 
     
    if (!IsSetParsMode()) {
-      SetError(-1,"Cannot set parameter for statement","Set***");
+      SetError(-1,"Cannot set parameter for statement", method);
       return 0;   
    }
    
    if ((npar<0) || (npar>=fNumBuffers)) {
-      SetError(-1,Form("Invalid parameter number %d",npar), "Set***");
+      SetError(-1,Form("Invalid parameter number %d",npar), method);
       return 0;
    }
 
    if ((fIterationCount==0) && (fBuffer[npar].fSqlType==0))
       if (!SetSQLParamType(npar, sqltype, sig, size)) {
-         SetError(-1,"Cannot initialize parameter buffer","BeforeSet");
+         SetError(-1,"Cannot initialize parameter buffer", method);
          return 0;
       }
 
@@ -663,7 +800,7 @@ Bool_t TMySQLStatement::SetNull(Int_t npar)
    //    stmt->SetDouble(2, 0.);
    //    stmt->SetNull(2);
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONG);
+   void* addr = BeforeSet("SetNull", npar, MYSQL_TYPE_LONG);
 
    if (addr!=0) 
       *((long*) addr) = 0;
@@ -679,7 +816,7 @@ Bool_t TMySQLStatement::SetInt(Int_t npar, Int_t value)
 {
    // Set parameter value as integer 
     
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONG);
+   void* addr = BeforeSet("SetInt", npar, MYSQL_TYPE_LONG);
 
    if (addr!=0)
       *((long*) addr) = value;
@@ -692,7 +829,7 @@ Bool_t TMySQLStatement::SetUInt(Int_t npar, UInt_t value)
 {
    // Set parameter value as unsigned integer 
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONG, kFALSE);
+   void* addr = BeforeSet("SetUInt", npar, MYSQL_TYPE_LONG, kFALSE);
 
    if (addr!=0)
       *((unsigned long*) addr) = value;
@@ -705,7 +842,7 @@ Bool_t TMySQLStatement::SetLong(Int_t npar, Long_t value)
 {
    // Set parameter value as long integer 
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONG);
+   void* addr = BeforeSet("SetLong", npar, MYSQL_TYPE_LONG);
 
    if (addr!=0)
       *((long*) addr) = value;
@@ -718,7 +855,7 @@ Bool_t TMySQLStatement::SetLong64(Int_t npar, Long64_t value)
 {
    // Set parameter value as 64-bit integer 
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONGLONG);
+   void* addr = BeforeSet("SetLong64", npar, MYSQL_TYPE_LONGLONG);
 
    if (addr!=0)
       *((long long*) addr) = value;
@@ -731,7 +868,7 @@ Bool_t TMySQLStatement::SetULong64(Int_t npar, ULong64_t value)
 {
    // Set parameter value as unsigned 64-bit integer 
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_LONGLONG, kFALSE);
+   void* addr = BeforeSet("SetULong64", npar, MYSQL_TYPE_LONGLONG, kFALSE);
 
    if (addr!=0)
       *((unsigned long long*) addr) = value;
@@ -744,7 +881,7 @@ Bool_t TMySQLStatement::SetDouble(Int_t npar, Double_t value)
 {
    // Set parameter value as double
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_DOUBLE, kFALSE);
+   void* addr = BeforeSet("SetDouble", npar, MYSQL_TYPE_DOUBLE, kFALSE);
 
    if (addr!=0)
       *((double*) addr) = value;
@@ -759,7 +896,7 @@ Bool_t TMySQLStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
 
    Int_t len = value ? strlen(value) : 0;
 
-   void* addr = BeforeSet(npar, MYSQL_TYPE_STRING, true, maxsize);
+   void* addr = BeforeSet("SetString", npar, MYSQL_TYPE_STRING, true, maxsize);
 
    if (addr==0) return kFALSE;
 
@@ -783,6 +920,110 @@ Bool_t TMySQLStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
    return kTRUE;
 }
 
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize)
+{
+   // set parameter value as binary data
+   
+   if (size>=maxsize) maxsize = size + 1;
+   
+   void* addr = BeforeSet("SetBinary", npar, MYSQL_TYPE_BLOB, true, maxsize);
+
+   if (addr==0) return kFALSE;
+
+   if (size >= fBuffer[npar].fSize) {
+      free(fBuffer[npar].fMem);
+
+      fBuffer[npar].fMem = malloc(size+1);
+      fBuffer[npar].fSize = size + 1;
+
+      fBind[npar].buffer = fBuffer[npar].fMem;
+      fBind[npar].buffer_length = fBuffer[npar].fSize;
+
+      addr = fBuffer[npar].fMem;
+      fNeedParBind = kTRUE;
+   }
+
+   memcpy(addr, mem, size);
+
+   fBuffer[npar].fResLength = size;
+
+   return kTRUE;
+
+}
+
+
+
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetDate(Int_t npar, Int_t year, Int_t month, Int_t day)
+{
+   // set parameter value as date 
+
+   MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetDate", npar, MYSQL_TYPE_DATE);
+
+   if (addr!=0) {
+      addr->year = year;
+      addr->month = month;
+      addr->day = day;
+   }
+
+   return (addr!=0);
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec)
+{
+   // set parameter value as time 
+
+   MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetTime", npar, MYSQL_TYPE_TIME);
+
+   if (addr!=0) {
+      addr->hour = hour;
+      addr->minute = min;
+      addr->second = sec;
+   }
+
+   return (addr!=0);
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
+{
+   // set parameter value as date & time 
+
+   MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetDatime", npar, MYSQL_TYPE_DATETIME);
+
+   if (addr!=0) {
+      addr->year = year;
+      addr->month = month;
+      addr->day = day;
+      addr->hour = hour;
+      addr->minute = min;
+      addr->second = sec;
+   }
+
+   return (addr!=0);
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t)
+{
+   // set parameter value as timestamp
+
+   MYSQL_TIME* addr = (MYSQL_TIME*) BeforeSet("SetTimestamp", npar, MYSQL_TYPE_TIMESTAMP);
+
+   if (addr!=0) {
+      addr->year = year;
+      addr->month = month;
+      addr->day = day;
+      addr->hour = hour;
+      addr->minute = min;
+      addr->second = sec;
+   }
+
+   return (addr!=0);
+}
 
 #else
 
@@ -965,6 +1206,47 @@ const char *TMySQLStatement::GetString(Int_t)
    return 0;
 }
 
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetBinary(Int_t, void* &, Long_t&)
+{
+   // Return field value as binary array 
+   
+   return kFALSE;
+}
+
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetDate(Int_t, Int_t&, Int_t&, Int_t&)
+{
+   // return field value as date
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetTime(Int_t, Int_t&, Int_t&, Int_t&)
+{
+   // return field value as time
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetDatime(Int_t, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&)
+{
+   // return field value as date & time
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::GetTimestamp(Int_t, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&)
+{
+   // return field value as time stamp
+   
+   return kFALSE;
+}
+
 //______________________________________________________________________________
 Bool_t TMySQLStatement::SetSQLParamType(Int_t, int, bool, int)
 {
@@ -976,7 +1258,7 @@ Bool_t TMySQLStatement::SetSQLParamType(Int_t, int, bool, int)
 }
 
 //______________________________________________________________________________
-void *TMySQLStatement::BeforeSet(Int_t, Int_t, Bool_t, Int_t)
+void *TMySQLStatement::BeforeSet(const char*, Int_t, Int_t, Bool_t, Int_t)
 {
    // Check boundary condition before setting value of parameter
    // Return address of parameter buffer
@@ -1054,5 +1336,44 @@ Bool_t TMySQLStatement::SetString(Int_t, const char*, Int_t)
    return kFALSE;
 }
 
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetBinary(Int_t, void*, Long_t, Long_t)
+{
+   // set parameter value as binary data
+   
+   return kFALSE;  
+}   
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetDate(Int_t, Int_t, Int_t, Int_t)
+{
+   // set parameter value as date 
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetTime(Int_t, Int_t, Int_t, Int_t)
+{
+   // set parameter value as time 
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetDatime(Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t)
+{
+   // set parameter value as date & time 
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TMySQLStatement::SetTimestamp(Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t)
+{
+   // set parameter value as timestamp 
+   
+   return kFALSE;
+}
 
 #endif // MYSQL_VERSION_ID > 40100
diff --git a/net/inc/TSQLStatement.h b/net/inc/TSQLStatement.h
index 153cc20f275..3a04262257a 100644
--- a/net/inc/TSQLStatement.h
+++ b/net/inc/TSQLStatement.h
@@ -1,4 +1,4 @@
-// @(#)root/net:$Name:  $:$Id: TSQLStatement.h,v 1.4 2006/06/02 14:02:03 brun Exp $
+// @(#)root/net:$Name:  $:$Id: TSQLStatement.h,v 1.5 2006/06/25 18:43:24 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -18,6 +18,9 @@
 #ifndef ROOT_TString
 #include "TString.h"
 #endif
+#ifndef ROOT_TDatime
+#include "TDatime.h"
+#endif
 
 class TSQLStatement : public TObject {
 
@@ -48,6 +51,16 @@ public:
    virtual Bool_t      SetULong64(Int_t, ULong64_t) { return kFALSE; }
    virtual Bool_t      SetDouble(Int_t, Double_t) { return kFALSE; }
    virtual Bool_t      SetString(Int_t, const char*, Int_t = 256) { return kFALSE; }
+   virtual Bool_t      SetDate(Int_t, Int_t, Int_t, Int_t) { return kFALSE; }
+           Bool_t      SetDate(Int_t, const TDatime&);
+   virtual Bool_t      SetTime(Int_t, Int_t, Int_t, Int_t) { return kFALSE; }
+           Bool_t      SetTime(Int_t, const TDatime&);
+   virtual Bool_t      SetDatime(Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t) { return kFALSE; }
+           Bool_t      SetDatime(Int_t, const TDatime&);
+   virtual Bool_t      SetTimestamp(Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, Int_t = 0) { return kFALSE; }
+           Bool_t      SetTimestamp(Int_t, const TDatime&);
+   virtual void        SetTimeFormating(const char*) {}
+   virtual Bool_t      SetBinary(Int_t, void*, Long_t, Long_t = 0x1000) { return kFALSE; }
 
    virtual Bool_t      Process() = 0;
    virtual Int_t       GetNumAffectedRows() { return 0; }
@@ -65,6 +78,20 @@ public:
    virtual ULong64_t   GetULong64(Int_t) { return 0; }
    virtual Double_t    GetDouble(Int_t) { return 0.; }
    virtual const char *GetString(Int_t) { return 0; }
+   virtual Bool_t      GetBinary(Int_t, void* &, Long_t&) { return kFALSE; }
+
+   virtual Bool_t      GetDate(Int_t, Int_t&, Int_t&, Int_t&) { return kFALSE; }
+   virtual Bool_t      GetTime(Int_t, Int_t&, Int_t&, Int_t&) { return kFALSE; }
+   virtual Bool_t      GetDatime(Int_t, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&) { return kFALSE; }
+           TDatime     GetDatime(Int_t);
+           Int_t       GetYear(Int_t);
+           Int_t       GetMonth(Int_t);
+           Int_t       GetDay(Int_t);
+           Int_t       GetHour(Int_t);
+           Int_t       GetMinute(Int_t);
+           Int_t       GetSecond(Int_t);
+   virtual Bool_t      GetTimestamp(Int_t, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&, Int_t&) { return kFALSE; }
+           TDatime     GetTimestamp(Int_t);
 
    virtual Bool_t      IsError() const { return GetErrorCode()!=0; }
    virtual Int_t       GetErrorCode() const;
diff --git a/net/src/TSQLStatement.cxx b/net/src/TSQLStatement.cxx
index 396f8fe5f05..599d5bb04fd 100644
--- a/net/src/TSQLStatement.cxx
+++ b/net/src/TSQLStatement.cxx
@@ -1,4 +1,4 @@
-// @(#)root/net:$Name:  $:$Id: TSQLStatement.cxx,v 1.3 2006/06/02 14:02:03 brun Exp $
+// @(#)root/net:$Name:  $:$Id: TSQLStatement.cxx,v 1.4 2006/06/25 18:43:24 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -162,6 +162,40 @@
 //       }
 //    }    
 //
+// 4. Working with date/time parameters
+// ====================================
+// Current implementation supports date, time, date&time and timestamp 
+// data (all time intervals not supported yet). To set or get date/time values,
+// following methods should be used:
+//   SetTime()/GetTime() - only time (hour:min:sec), 
+//   SetDate()/GetDate() - only date (year-month-day), 
+//   SetDatime()/GetDatime() - date and time 
+//   SetTimestamp()/GetTimestamp() - timestamp with seconds fraction
+// For some of these methods TDatime type can be used as parameter / return value.
+// Be aware, that TDatime supports only dates after 1995-01-01.
+// There are also methods to get separately year, month, day, hour, minutes and seconds.
+//
+// Different SQL databases has different treatement of date/time types.
+// For instance, MySQL has all correspondent types (TIME, DATE, DATETIME and TIMESTAMP),
+// Oracle native driver supports only DATE (which is actually date and time) and TIMESTAMP
+// ODBC interface provides access for time, date and timestamps.
+// Therefore, one should use correct methods to access such data.
+// For instance, in MySQL SQL type 'DATE' is only date (one should use GetDate() to 
+// access such data), while in Oracle it is date and time. Therefore, 
+// to get complete data from 'DATE' column in Oracle, one should use GetDatime() method.
+//
+// The only difference of timestamp from date/time, that it has fractional
+// seconds part. Be aware, that fractional part can has different meaning 
+// (actual value) in different SQL plugins.
+//
+// 5. Binary data
+// ==============
+// Most of modern data bases support just binary data, which is
+// typically has SQL type name 'BLOB'. To access data in such
+// columns, GetBinary()/SetBinary() methods should be used. 
+// Current implementation supposed, that complete content of the 
+// column must be retrieved at once. Therefore very big data of 
+// gigabytes size may cause a problem.
 //
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -209,3 +243,142 @@ void TSQLStatement::SetError(Int_t code, const char* msg, const char* method)
    if ((method!=0) && fErrorOut)
       Error(method,"Code: %d  Msg: %s", code, (msg ? msg : "No message"));
 }
+
+//______________________________________________________________________________
+Bool_t TSQLStatement::SetDate(Int_t npar, const TDatime& tm)
+{
+   // set only date value for specified parameter from TDatime object
+   
+   return SetDate(npar, tm.GetYear(), tm.GetMonth(), tm.GetDay());
+}
+
+//______________________________________________________________________________
+Bool_t TSQLStatement::SetTime(Int_t npar, const TDatime& tm)
+{
+   // set only time value for specified parameter from TDatime object
+   
+   return SetTime(npar, tm.GetHour(), tm.GetMinute(), tm.GetSecond());
+}
+
+//______________________________________________________________________________
+Bool_t TSQLStatement::SetDatime(Int_t npar, const TDatime& tm)
+{
+   // set date & time value for specified parameter from TDatime object
+   
+   return SetDatime(npar, tm.GetYear(), tm.GetMonth(), tm.GetDay(),
+                          tm.GetHour(), tm.GetMinute(), tm.GetSecond());
+}
+
+//______________________________________________________________________________
+Bool_t TSQLStatement::SetTimestamp(Int_t npar, const TDatime& tm)
+{
+   // set timestamp value for specified parameter from TDatime object
+   
+   return SetTimestamp(npar, tm.GetYear(), tm.GetMonth(), tm.GetDay(),
+                             tm.GetHour(), tm.GetMinute(), tm.GetSecond(), 0);
+}
+
+//______________________________________________________________________________
+TDatime TSQLStatement::GetDatime(Int_t npar)
+{
+   // return value of parameter in form of TDatime
+   // Be aware, that TDatime does not allow dates before 1995-01-01 
+   
+   Int_t year, month, day, hour, min, sec;
+   
+   if (!GetDatime(npar, year, month, day, hour, min, sec))
+     return TDatime();
+   
+   if (year<1995) {
+      SetError(-1, "Date before year 1995 does not supported by TDatime type", "GetDatime");
+      return TDatime();
+   }
+   
+   return TDatime(year, month, day, hour, min, sec);
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetYear(Int_t npar)
+{
+   // return year value for parameter (if applicable) 
+   
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetDate(npar, year, month, day)) return year;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return year;
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetMonth(Int_t npar)
+{
+   // return month value for parameter (if applicable) 
+
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetDate(npar, year, month, day)) return month;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return month;
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetDay(Int_t npar)
+{
+   // return day value for parameter (if applicable) 
+
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetDate(npar, year, month, day)) return day;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return day;
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetHour(Int_t npar)
+{
+   // return hours value for parameter (if applicable) 
+
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetTime(npar, hour, min, sec)) return hour;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return hour;
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetMinute(Int_t npar)
+{
+   // return minutes value for parameter (if applicable) 
+
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetTime(npar, hour, min, sec)) return min;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return min;
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLStatement::GetSecond(Int_t npar)
+{
+   // return seconds value for parameter (if applicable) 
+
+   Int_t year, month, day, hour, min, sec, frac;
+   if (GetTime(npar, hour, min, sec)) return sec;
+   if (GetTimestamp(npar, year, month, day, hour, min, sec, frac)) return sec;
+   return 0;
+}
+
+//______________________________________________________________________________
+TDatime TSQLStatement::GetTimestamp(Int_t npar)
+{
+   // return value of parameter in form of TDatime
+   // Be aware, that TDatime does not allow dates before 1995-01-01 
+   
+   Int_t year, month, day, hour, min, sec, frac;
+   
+   if (!GetTimestamp(npar, year, month, day, hour, min, sec, frac))
+     return TDatime();
+   
+   if (year<1995) {
+      SetError(-1, "Date before year 1995 does not supported by TDatime type", "GetTimestamp");
+      return TDatime();
+   }
+   
+   return TDatime(year, month, day, hour, min, sec);
+}
+
diff --git a/odbc/inc/TODBCStatement.h b/odbc/inc/TODBCStatement.h
index a2bf2b556e2..29ce32a2eeb 100644
--- a/odbc/inc/TODBCStatement.h
+++ b/odbc/inc/TODBCStatement.h
@@ -1,4 +1,4 @@
-// @(#)root/odbc:$Name:  $:$Id: TODBCStatement.h,v 1.6 2006/06/02 14:02:03 brun Exp $
+// @(#)root/odbc:$Name:  $:$Id: TODBCStatement.h,v 1.7 2006/06/25 18:43:24 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -92,6 +92,11 @@ public:
    virtual Bool_t      SetULong64(Int_t npar, ULong64_t value);
    virtual Bool_t      SetDouble(Int_t npar, Double_t value);
    virtual Bool_t      SetString(Int_t npar, const char* value, Int_t maxsize = 256);
+   virtual Bool_t      SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize = 0x1000);
+   virtual Bool_t      SetDate(Int_t npar, Int_t year, Int_t month, Int_t day);
+   virtual Bool_t      SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      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 = 0);
 
    virtual Bool_t      NextIteration();
 
@@ -111,6 +116,11 @@ public:
    virtual ULong64_t   GetULong64(Int_t npar);
    virtual Double_t    GetDouble(Int_t npar);
    virtual const char *GetString(Int_t npar);
+   virtual Bool_t      GetBinary(Int_t npar, void* &mem, Long_t& size);
+   virtual Bool_t      GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day);
+   virtual Bool_t      GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t&);
 
    ClassDef(TODBCStatement, 0); //ODBC implementation of TSQLStatement
 };
diff --git a/oracle/inc/TOracleStatement.h b/oracle/inc/TOracleStatement.h
index dc9a6ea4fbc..55134212dcd 100644
--- a/oracle/inc/TOracleStatement.h
+++ b/oracle/inc/TOracleStatement.h
@@ -1,4 +1,4 @@
-// @(#)root/oracle:$Name:  $:$Id: TOracleStatement.h,v 1.3 2006/06/02 14:02:03 brun Exp $
+// @(#)root/oracle:$Name:  $:$Id: TOracleStatement.h,v 1.4 2006/06/25 18:43:24 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 /*************************************************************************
@@ -20,6 +20,7 @@
 #include <occi.h>
 using namespace oracle::occi;
 #else
+class Environment;
 class Connection;
 class Statement;
 class ResultSet;
@@ -32,9 +33,11 @@ protected:
 
    struct TBufferRec {
       char* strbuf;
+      Long_t strbufsize;
       char* namebuf;
    };
 
+   Environment           *fEnv;         // enviroment 
    Connection            *fConn;        // connection to Oracle
    Statement             *fStmt;        // executed statement
    ResultSet             *fResult;      // query result (rows)
@@ -44,6 +47,7 @@ protected:
    Int_t                  fNumIterations;  // size of internal statement buffer
    Int_t                  fIterCounter; //counts nextiteration calls and process iterations, if required
    Int_t                  fWorkingMode; // 1 - settingpars, 2 - getting results
+   TString                fTimeFmt;     // format for date to string conversion, default "MM/DD/YYYY, HH24:MI:SS" 
 
    Bool_t      IsParSettMode() const { return fWorkingMode==1; }
    Bool_t      IsResultSet() const { return (fWorkingMode==2) && (fResult!=0); }
@@ -52,7 +56,7 @@ protected:
    void        CloseBuffer();
    
 public:
-   TOracleStatement(Connection* conn, Statement* stmt, Int_t niter, Bool_t errout = kTRUE);
+   TOracleStatement(Environment* env, Connection* conn, Statement* stmt, Int_t niter, Bool_t errout = kTRUE);
    virtual ~TOracleStatement();
 
    virtual void        Close(Option_t * = "");
@@ -68,6 +72,12 @@ public:
    virtual Bool_t      SetULong64(Int_t npar, ULong64_t value);
    virtual Bool_t      SetDouble(Int_t npar, Double_t value);
    virtual Bool_t      SetString(Int_t npar, const char* value, Int_t maxsize = 256);
+   virtual Bool_t      SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize = 0x1000);
+   virtual Bool_t      SetDate(Int_t npar, Int_t year, Int_t month, Int_t day);
+   virtual Bool_t      SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec);
+   virtual Bool_t      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 = 0);
+   virtual void        SetTimeFormating(const char* fmt) { fTimeFmt = fmt; }
 
    virtual Bool_t      NextIteration();
 
@@ -87,8 +97,13 @@ public:
    virtual ULong64_t   GetULong64(Int_t npar);
    virtual Double_t    GetDouble(Int_t npar);
    virtual const char *GetString(Int_t npar);
+   virtual Bool_t      GetBinary(Int_t npar, void* &mem, Long_t& size);
+   virtual Bool_t      GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day);
+   virtual Bool_t      GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec);
+   virtual Bool_t      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);
 
-   ClassDef(TOracleStatement, 0); // Statement class for Oracle
+   ClassDef(TOracleStatement, 0); // SQL statement class for Oracle
 };
 
 #endif
diff --git a/oracle/src/TOracleRow.cxx b/oracle/src/TOracleRow.cxx
index d29a32ccea7..6b14de2b6e6 100644
--- a/oracle/src/TOracleRow.cxx
+++ b/oracle/src/TOracleRow.cxx
@@ -1,4 +1,4 @@
-// @(#)root/oracle:$Name:  $:$Id: TOracleRow.cxx,v 1.4 2006/04/12 20:53:45 rdm Exp $
+// @(#)root/oracle:$Name:  $:$Id: TOracleRow.cxx,v 1.5 2006/04/12 21:21:20 rdm Exp $
 // Author: Yan Liu and Shaowen Wang   23/11/04
 
 /*************************************************************************
@@ -119,7 +119,7 @@ void TOracleRow::GetRowData()
       fDataType = (*fFieldInfo)[field].getInt(MetaData::ATTR_DATA_TYPE);
 
       switch (fDataType) {
-        case 2: //NUMBER
+        case SQLT_NUM: //NUMBER
            fPrecision = (*fFieldInfo)[field].getInt(MetaData::ATTR_PRECISION);
            fScale = (*fFieldInfo)[field].getInt(MetaData::ATTR_SCALE);
 
@@ -132,14 +132,18 @@ void TOracleRow::GetRowData()
            }
            break;
         
-        case 1:  // VARCHAR2
-        case 12: // DATE
-        case 96:  // CHAR
+        case SQLT_CHR:  // character string
+        case SQLT_VCS:  // variable character string
+        case SQLT_AFC: // ansi fixed char
+        case SQLT_AVC: // ansi var char
            res = fResult->getString(field+1);
            break;
-        case 187: // TIMESTAMP
-        case 188: // TIMESTAMP WITH TIMEZONE
-        case 232: // TIMESTAMP WITH LOCAL TIMEZONE
+        case SQLT_DAT:  // Oracle native DATE type
+           res = (fResult->getDate(field+1)).toText("MM/DD/YYYY, HH24:MI:SS");
+           break;
+        case SQLT_TIMESTAMP:     // TIMESTAMP
+        case SQLT_TIMESTAMP_TZ:  // TIMESTAMP WITH TIMEZONE
+        case SQLT_TIMESTAMP_LTZ: // TIMESTAMP WITH LOCAL TIMEZONE
            res = (fResult->getTimestamp(field+1)).toText("MM/DD/YYYY, HH24:MI:SS",0);
            break;
         default:
diff --git a/oracle/src/TOracleServer.cxx b/oracle/src/TOracleServer.cxx
index b438707b391..4e4c8b2957c 100644
--- a/oracle/src/TOracleServer.cxx
+++ b/oracle/src/TOracleServer.cxx
@@ -1,4 +1,4 @@
-// @(#)root/oracle:$Name:  $:$Id: TOracleServer.cxx,v 1.12 2006/06/22 08:18:57 brun Exp $
+// @(#)root/oracle:$Name:  $:$Id: TOracleServer.cxx,v 1.13 2006/06/25 18:43:24 brun Exp $
 // Author: Yan Liu and Shaowen Wang   23/11/04
 
 /*************************************************************************
@@ -120,8 +120,10 @@ TSQLStatement *TOracleServer::Statement(const char *sql, Int_t niter)
 
    try {
       oracle::occi::Statement *stmt = fConn->createStatement(sql);
-
-      return new TOracleStatement(fConn, stmt, niter, fErrorOut);
+      
+      Blob parblob(fConn);
+      
+      return new TOracleStatement(fEnv, fConn, stmt, niter, fErrorOut);
 
    } CatchError("Statement")
 
diff --git a/oracle/src/TOracleStatement.cxx b/oracle/src/TOracleStatement.cxx
index 484fcad05dd..ea747841d32 100644
--- a/oracle/src/TOracleStatement.cxx
+++ b/oracle/src/TOracleStatement.cxx
@@ -1,4 +1,4 @@
-// @(#)root/oracle:$Name:  $:$Id: TOracleStatement.cxx,v 1.4 2006/06/22 08:18:57 brun Exp $
+// @(#)root/oracle:$Name:  $:$Id: TOracleStatement.cxx,v 1.5 2006/06/25 18:43:24 brun Exp $
 // Author: Sergey Linev   6/02/2006
 
 
@@ -24,8 +24,9 @@
 ClassImp(TOracleStatement)
 
 //______________________________________________________________________________
-TOracleStatement::TOracleStatement(Connection* conn, Statement* stmt, Int_t niter, Bool_t errout) :
+TOracleStatement::TOracleStatement(Environment* env, Connection* conn, Statement* stmt, Int_t niter, Bool_t errout) :
    TSQLStatement(errout),
+   fEnv(env),
    fConn(conn),
    fStmt(stmt),
    fResult(0),
@@ -34,7 +35,8 @@ TOracleStatement::TOracleStatement(Connection* conn, Statement* stmt, Int_t nite
    fBufferSize(0),
    fNumIterations(niter),
    fIterCounter(0),
-   fWorkingMode(0)
+   fWorkingMode(0),
+   fTimeFmt("MM/DD/YYYY, HH24:MI:SS")
 {
    // Normal constructor of TOracleStatement class
    // On creation time specifies buffer length, which should be
@@ -106,18 +108,18 @@ void TOracleStatement::Close(Option_t *)
       }                                                 \
    }
 
-#define CheckGetField(method)                             \
+#define CheckGetField(method, defres)                   \
    {                                                    \
       ClearError();                                     \
       if (!IsResultSet()) {                             \
          SetError(-1,"There is no result set for statement", method); \
-         return 0;                                      \
+         return defres;                                 \
       }                                                 \
       if ((npar<0) || (npar>=fBufferSize)) {                                     \
          TString errmsg("Invalid parameter number ");   \
          errmsg+= npar;                                 \
          SetError(-1,errmsg.Data(),method);             \
-         return 0;                                      \
+         return defres;                                 \
       }                                                 \
    }
 
@@ -133,6 +135,7 @@ void TOracleStatement::SetBufferSize(Int_t size)
     fBuffer = new TBufferRec[size];
     for (Int_t n=0;n<fBufferSize;n++) {
        fBuffer[n].strbuf = 0;
+       fBuffer[n].strbufsize = -1;
        fBuffer[n].namebuf = 0;
     }
 }
@@ -349,6 +352,111 @@ Bool_t TOracleStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
    return kFALSE;
 }
 
+//______________________________________________________________________________
+Bool_t TOracleStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize)
+{
+   // set parameter value as binary data
+   
+   CheckSetPar("SetBinary");
+
+   try {
+
+      // this is when NextIteration is called first time
+      if (fIterCounter==1) 
+         fStmt->setMaxParamSize(npar+1, maxsize);
+         
+      Bytes buf((unsigned char*) mem, size);
+
+      fStmt->setBytes(npar+1, buf);
+      
+      return kTRUE;
+
+   } catch (SQLException &oraex)  {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "SetBinary");
+   }
+   return kFALSE;
+}   
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::SetDate(Int_t npar, Int_t year, Int_t month, Int_t day)
+{
+   // Set date value for parameter npar
+
+   CheckSetPar("SetDate");
+
+   try {
+      Date tm = fStmt->getDate(npar+1);
+      int o_year;
+      unsigned int o_month, o_day, o_hour, o_minute, o_second; 
+      tm.getDate(o_year, o_month, o_day, o_hour, o_minute, o_second);
+      tm.setDate(year, month, day, o_hour, o_minute, o_second);
+      fStmt->setDate(npar+1, tm);
+      return kTRUE;
+   } catch (SQLException &oraex)  {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "SetDate");
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec)
+{
+   // Set time value for parameter npar
+
+   CheckSetPar("SetTime");
+   
+   try {
+      Date tm = fStmt->getDate(npar+1);
+      int o_year;
+      unsigned int o_month, o_day, o_hour, o_minute, o_second; 
+      tm.getDate(o_year, o_month, o_day, o_hour, o_minute, o_second);
+      tm.setDate(o_year, o_month, o_day, hour, min, sec);
+      fStmt->setDate(npar+1, tm);
+      return kTRUE;
+   } catch (SQLException &oraex)  {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "SetTime");
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
+{
+   // Set date & time value for parameter npar
+
+   CheckSetPar("SetDatime");
+
+   try {
+      Date tm(fEnv, year, month, day, hour, min, sec);
+      fStmt->setDate(npar+1, tm);
+      return kTRUE;
+   } catch (SQLException &oraex)  {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "SetDatime");
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::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)
+{
+   // Set date & time value for parameter npar
+
+   CheckSetPar("SetTimestamp");
+
+   try {
+      Timestamp tm(fEnv, year, month, day, hour, min, sec, frac);
+      fStmt->setTimestamp(npar+1, tm);
+      return kTRUE;
+   } catch (SQLException &oraex)  {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "SetTimestamp");
+   }
+
+   return kFALSE;
+}
+
 //______________________________________________________________________________
 Bool_t TOracleStatement::NextIteration()
 {
@@ -413,7 +521,7 @@ const char* TOracleStatement::GetFieldName(Int_t npar)
 {
    // Return field name in result set 
     
-   CheckGetField("GetFieldName");
+   CheckGetField("GetFieldName", 0);
 
    if (!IsResultSet() || (npar<0) || (npar>=fBufferSize)) return 0;
 
@@ -446,11 +554,12 @@ Bool_t TOracleStatement::NextResultRow()
    if (fResult==0) return kFALSE;
 
    try {
-      for (int n=0;n<fBufferSize;n++)
-        if (fBuffer[n].strbuf) {
+      for (int n=0;n<fBufferSize;n++) {
+        if (fBuffer[n].strbuf) 
            delete[] fBuffer[n].strbuf;
-           fBuffer[n].strbuf = 0;
-        }
+        fBuffer[n].strbuf = 0;
+        fBuffer[n].strbufsize = -1;
+      }
       if (!fResult->next()) {
          fWorkingMode = 0;
          CloseBuffer();
@@ -469,7 +578,7 @@ Bool_t TOracleStatement::IsNull(Int_t npar)
 {
    // Checks if fieled value in result set is NULL  
     
-   CheckGetField("IsNull");
+   CheckGetField("IsNull", kFALSE);
 
    try {
       return fResult->isNull(npar+1);
@@ -485,7 +594,7 @@ Int_t TOracleStatement::GetInt(Int_t npar)
 {
    // return field value as integer
     
-   CheckGetField("GetInt");
+   CheckGetField("GetInt", 0);
 
    Int_t res = 0;
 
@@ -504,7 +613,7 @@ UInt_t TOracleStatement::GetUInt(Int_t npar)
 {
    // return field value as unsigned integer
 
-   CheckGetField("GetUInt");
+   CheckGetField("GetUInt", 0);
 
    UInt_t res = 0;
 
@@ -524,7 +633,7 @@ Long_t TOracleStatement::GetLong(Int_t npar)
 {
    // return field value as long integer
 
-   CheckGetField("GetLong");
+   CheckGetField("GetLong", 0);
 
    Long_t res = 0;
 
@@ -543,7 +652,7 @@ Long64_t TOracleStatement::GetLong64(Int_t npar)
 {
    // return field value as 64-bit integer
 
-   CheckGetField("GetLong64");
+   CheckGetField("GetLong64", 0);
 
    Long64_t res = 0;
 
@@ -562,7 +671,7 @@ ULong64_t TOracleStatement::GetULong64(Int_t npar)
 {
    // return field value as unsigned 64-bit integer
 
-   CheckGetField("GetULong64");
+   CheckGetField("GetULong64", 0);
 
    ULong64_t res = 0;
 
@@ -581,7 +690,7 @@ Double_t TOracleStatement::GetDouble(Int_t npar)
 {
    // return field value as double
 
-   CheckGetField("GetDouble");
+   CheckGetField("GetDouble", 0.);
 
    Double_t res = 0;
 
@@ -600,7 +709,7 @@ const char* TOracleStatement::GetString(Int_t npar)
 {
    // return field value as string
 
-   CheckGetField("GetString");
+   CheckGetField("GetString", 0);
 
    if (fBuffer[npar].strbuf!=0) return fBuffer[npar].strbuf;
 
@@ -612,7 +721,7 @@ const char* TOracleStatement::GetString(Int_t npar)
       std::string res;
 
       switch (datatype) {
-        case 2: { //NUMBER
+        case SQLT_NUM: { // oracle numeric NUMBER
            int prec = (*fFieldInfo)[npar].getInt(MetaData::ATTR_PRECISION);
            int scale = (*fFieldInfo)[npar].getInt(MetaData::ATTR_SCALE);
 
@@ -626,25 +735,30 @@ const char* TOracleStatement::GetString(Int_t npar)
            }
            break;
         }
-        case 1:  // VARCHAR2
-        case 12: // DATE
-        case 96:  // CHAR
+        case SQLT_CHR:  // character string
+        case SQLT_VCS:  // variable character string
+        case SQLT_AFC: // ansi fixed char
+        case SQLT_AVC: // ansi var char
            res = fResult->getString(npar+1);
            break;
-        case 187: // TIMESTAMP
-        case 188: // TIMESTAMP WITH TIMEZONE
-        case 232: // TIMESTAMP WITH LOCAL TIMEZONE
-           res = (fResult->getTimestamp(npar+1)).toText("MM/DD/YYYY, HH24:MI:SS",0);
+        case SQLT_DAT:  // Oracle native DATE type
+           res = (fResult->getDate(npar+1)).toText(fTimeFmt.Data());
+           break;
+        case SQLT_TIMESTAMP:     // TIMESTAMP
+        case SQLT_TIMESTAMP_TZ:  // TIMESTAMP WITH TIMEZONE
+        case SQLT_TIMESTAMP_LTZ: // TIMESTAMP WITH LOCAL TIMEZONE
+           res = (fResult->getTimestamp(npar+1)).toText(fTimeFmt.Data(), 0);
            break;
         default:
            res = fResult->getString(npar+1);
-           Info("getString","Type %d may not be supported");
+           Info("getString","Type %d may not be supported", datatype);
       }
 
       int len = res.length();
 
       if (len>0) {
           fBuffer[npar].strbuf = new char[len+1];
+          fBuffer[npar].strbufsize = len+1;
           strcpy(fBuffer[npar].strbuf, res.c_str());
       }
 
@@ -656,3 +770,143 @@ const char* TOracleStatement::GetString(Int_t npar)
 
    return 0;
 }
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
+{
+   // Return field value as binary array 
+
+   mem = 0;
+   size = 0;
+
+   CheckGetField("GetBinary", kFALSE);
+
+   if (fBuffer[npar].strbufsize>=0) {
+      mem = fBuffer[npar].strbuf; 
+      size = fBuffer[npar].strbufsize;
+      return kTRUE;
+   }
+
+   try {
+      if (fResult->isNull(npar+1)) return kTRUE;
+      
+      Blob parblob = fResult->getBlob(npar+1);
+      
+      parblob.open(OCCI_LOB_READONLY);
+      
+      size = parblob.length();
+      
+      fBuffer[npar].strbufsize = size;
+      
+      if (size>0) {
+         mem = malloc(size); 
+         
+         fBuffer[npar].strbuf = (char*) mem;
+      
+         Stream* parstream = parblob.getStream();
+         
+         char* buf = (char*) mem;
+         
+         /*int len = */ parstream->readBuffer(buf, size);
+         
+         parblob.closeStream(parstream);
+      }
+      
+      parblob.close();
+      
+      return kTRUE;
+         
+   } catch (SQLException &oraex) {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "GetBinary");
+   }
+   
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
+{
+   // return field value as date
+   
+   Int_t hour, min, sec;
+   
+   return GetDatime(npar, year, month, day, hour, min, sec);
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // return field value as time
+    
+   Int_t year, month, day;
+
+   return GetDatime(npar, year, month, day, hour, min, sec);
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // return field value as date & time
+    
+   CheckGetField("GetDatime", kFALSE);
+
+   try {
+      if (!fResult->isNull(npar+1)) {
+         int datatype = (*fFieldInfo)[npar].getInt(MetaData::ATTR_DATA_TYPE);
+         
+         if (datatype!=SQLT_DAT) return kFALSE;
+          
+         Date tm = fResult->getDate(npar+1);
+         int o_year;
+         unsigned int o_month, o_day, o_hour, o_minute, o_second; 
+         tm.getDate(o_year, o_month, o_day, o_hour, o_minute, o_second);
+         year = (Int_t) o_year;
+         month = (Int_t) o_month;
+         day = (Int_t) o_day;
+         hour = (Int_t) o_hour;
+         min = (Int_t) o_minute;
+         sec = (Int_t) o_second;
+         return kTRUE;
+      }
+   } catch (SQLException &oraex) {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "GetDatime");
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TOracleStatement::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)
+{
+   // return field value as date & time
+    
+   CheckGetField("GetTimestamp", kFALSE);
+
+   try {
+      if (!fResult->isNull(npar+1)) {
+         int datatype = (*fFieldInfo)[npar].getInt(MetaData::ATTR_DATA_TYPE);
+
+         if ((datatype!=SQLT_TIMESTAMP) && 
+             (datatype!=SQLT_TIMESTAMP_TZ) && 
+             (datatype!=SQLT_TIMESTAMP_LTZ)) return kFALSE;
+
+         Timestamp tm = fResult->getTimestamp(npar+1);
+         int o_year;
+         unsigned int o_month, o_day, o_hour, o_minute, o_second, o_frac; 
+         tm.getDate(o_year, o_month, o_day);
+         tm.getTime(o_hour, o_minute, o_second, o_frac);
+         year = (Int_t) o_year;
+         month = (Int_t) o_month;
+         day = (Int_t) o_day;
+         hour = (Int_t) o_hour;
+         min = (Int_t) o_minute;
+         sec = (Int_t) o_second;
+         frac = (Int_t) o_frac;
+         return kTRUE;  
+      }
+   } catch (SQLException &oraex) {
+      SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), "GetTimestamp");
+   }
+
+   return kFALSE;
+}
-- 
GitLab