/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 picoSqlNet - picoSQL client library

 Copyright (C) Picosoft s.r.l. 1994-2002

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
# ifndef sqlhndls_h
# define sqlhndls_h "$Id$"


# ifdef WIN32
# include <windows.h>
# include <sql.h>
# include <sqlext.h>
# else
# include "sqltype.h"
# endif
extern "C" {
#include <stdlib.h>
#include <string.h>
#include "invoke.h"
#include "iiopobj.h"
#include "except.h"
}
# include "pstring.h"
# include "pvector.h"

# ifdef MEM_DEBUG
extern "C" {
extern void *myMalloc(size_t);
extern void myFree(void *);
}
# else
# define myMalloc(a) malloc(a)
# define myFree(a) free(a)
# endif


class BindCol : public PObject {
   PCLASS(BindCol,PObject)
public:
   long *pcbValue;
   struct tDataIn {
      unsigned short icol;
      short fCType;
      long cbValueMax;
   } dataIn;
   struct tDataOut {
      CORBA_Any *any;
      long pcbValue;
   } dataOut;
   BindCol (unsigned short p_icol, short p_fCType, void *p_rgbValue,
            long p_cbValueMax, long *p_pcbValue) {
      dataIn.icol = p_icol;
      dataIn.fCType = p_fCType;
      dataOut.any = new CORBA_Any;
      dataOut.any->tcIn = 0;
      dataOut.any->tcOut = 0;
      dataOut.any->data = p_rgbValue;
      dataIn.cbValueMax = p_cbValueMax;
      dataOut.pcbValue = 0;
      pcbValue = p_pcbValue;
   }
   ~BindCol() {
      if (dataOut.any->tcOut)
         myFree (dataOut.any->tcOut);
      delete dataOut.any;
   }
};

PVECTOR(BindCol);

class Parameter : public PObject {
   PCLASS(Parameter,PObject)
   char *localBuffer;
   unsigned long localBufferLen;
   CORBA_Principal *intObject;
public:
   long *pcbValue;
   struct tData {
      short fParamType;
      short fCType;
      short fSqlType;
      unsigned long cbColDef;
      short ibScale;
      CORBA_Any *any;
      long cbValueMax;
      long pcbValue;
   } data;
public:
   Parameter (short p_fParamType, short p_fCType,
              short p_fSqlType, unsigned long p_cbColDef, short p_ibScale,
              void *p_rgbValue, long p_cbValueMax, long *p_pcbValue,
              CORBA_TCKindDesc *anyType) {
      intObject = 0;
      data.fParamType = p_fParamType;
      data.fCType = p_fCType;
      data.fSqlType = p_fSqlType;
      data.cbColDef = p_cbColDef;
      data.ibScale = p_ibScale;
      data.any = new CORBA_Any;
      data.any->tcIn = anyType;
      data.any->tcOut = 0;
      if (data.any->tcIn == &TCD_Principal) {
         intObject = (CORBA_Principal *) CORBA_Object_new (&TCD_Principal, 0);
         intObject->data = (unsigned char*) p_rgbValue;
         data.any->data = intObject;
      } else {
         data.any->data = p_rgbValue;
      }
      data.cbValueMax = p_cbValueMax;
      data.pcbValue = 0;
      pcbValue = p_pcbValue;
      localBuffer = 0;
      localBufferLen = 0;
   }
   ~Parameter() {
      delete data.any;
      if (localBuffer != 0)
         free (localBuffer);
      /*
      if (intObject)
         CORBA_Object_delete (intObject, &TCD_Principal);
      */
   }
   char *getData() {
      if (intObject)
         return (char*)intObject->data;
      else
         return (char*)data.any->data;
   }

   void putData(char *b, long len) {
      if (localBuffer == 0) {
         localBuffer = (char *) malloc (len);
         memcpy (localBuffer, b, len);
         localBufferLen = len;
      } else {
         localBuffer = (char *) realloc (localBuffer, localBufferLen + len);
         memcpy (&localBuffer[localBufferLen], b, len);
         localBufferLen += len;
      }
      *pcbValue += len;
      if (*pcbValue == SQL_LEN_DATA_AT_EXEC_OFFSET) {
         if (data.any->tcIn == &TCD_Principal) {
            intObject->data = (unsigned char*) localBuffer;
            intObject->size = localBufferLen;
         } else {
            data.any->data = localBuffer;
         }
         *pcbValue = localBufferLen;
      }
   }
   PBool isDataAtExec() {
      return *pcbValue == SQL_DATA_AT_EXEC ||
             *pcbValue < SQL_LEN_DATA_AT_EXEC_OFFSET;
   }
};

PVECTOR(Parameter);

class ClntHenv : public PObject {
   PCLASS(ClntHenv,PObject)
public:
   HENV srvHenv;
   ClntHenv() { srvHenv = SQL_NULL_HENV; }
};

class ClntHdbc : public PObject {
   PCLASS(ClntHdbc,PObject)
public:
   ClntHenv *henv;
   Invoke *call;
   IiopObj *obj;
   PString name;
   HDBC srvHdbc;
   ClntHdbc (ClntHenv *he) : henv(he) { }
};

class ClntHstmt : public PObject {
   PCLASS(ClntHstmt,PObject)
public:
   BindColVector cols;
   ParameterVector param;
   ClntHdbc *hdbc;
   HSTMT srvHstmt;
   ClntHstmt (ClntHdbc *hd): hdbc(hd) { }
   ~ClntHstmt ();
};

inline PBool notOk (unsigned char * sz, SDWORD cb) {
   return sz != 0 && cb < 0 && cb != SQL_NTS;
}

inline unsigned char *toCorbaString (unsigned char *str, int len) {
   unsigned char *Return = str;
   if (len > 0) {
      Return = new unsigned char[len + 1];
      memcpy (Return, str, len);
      Return[len] = '\0';
   }
   return Return;
}
# endif
