/*
_____       _    _    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
*/
static char rcsid[] = "$Id: prepare.cpp 4.0 1998/10/27 16:20:43 picoSoft Exp $";
# ifdef WIN32
# include <windows.h>
# include <sql.h>
# include <sqlext.h>
# else
extern "C" {
# include "sqltype.h"
}
# endif
# include "sqlhndls.h"
# include "dberror.h"
# include <stdio.h>
# ifdef MSDOS
# define strlen lstrlen
# define strncpy lstrcpyn
# endif
extern "C" {
//  Allocate a SQL statement

RETCODE SQL_API SQLAllocStmt(
    HDBC       hdbc,
    HSTMT FAR *phstmt)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt;
   ClntHdbc *myHdbc = (ClntHdbc *) hdbc;
   void *argv[3];

   if (!myHdbc || !myHdbc->IsA(ClntHdbc::Class))
      return SQL_INVALID_HANDLE;
   DelError (0, myHdbc, 0);

   myHstmt = new ClntHstmt(myHdbc);
   myHstmt->hdbc = myHdbc;
   argv[0] = &Return;
   argv[1] = (void *) &myHdbc->srvHdbc;
   argv[2] = &myHstmt->srvHstmt;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHdbc->call, ex, "SQLAllocStmt", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, myHdbc, 0, stat, ex->code, ex->description);
      Exception_log(ex);
   } else {
      if (Return == SQL_SUCCESS) {
         *phstmt =  (HSTMT) myHstmt;
      } else
         delete myHstmt;
   }
   Exception_delete (ex);
   return Return;
}

RETCODE SQL_API SQLFreeStmt(
    HSTMT   hstmt,
    UWORD   fOption)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[3];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;
   DelError (0,0,myHstmt);

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = &fOption;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLFreeStmt", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   } else {
      if (Return == SQL_SUCCESS)
         if (fOption == SQL_DROP)
            delete myHstmt;
         else if (fOption == SQL_UNBIND) {
            BindCol *bc;
            for (int i = 0; i < myHstmt->cols.size(); i++)
               if ((bc = myHstmt->cols.getAt(i)) != 0) {
                  delete bc;
                  myHstmt->cols.setAt (i, (BindCol *) 0);
               }
         } else if (fOption == SQL_RESET_PARAMS) {
            Parameter *p;
            for (int i = 0; i < myHstmt->param.size(); i++)
               if ((p = myHstmt->param.getAt(i)) != 0) {
                  delete p;
                  myHstmt->param.setAt (i, (Parameter *) 0);
               }
         }
   }
   Exception_delete (ex);
   return Return;
}

//  Perform a Prepare on the SQL statement

RETCODE SQL_API SQLPrepare(
    HSTMT      hstmt,
    UCHAR FAR *szSqlStr,
    SDWORD     cbSqlStr)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[4];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;
   else if (notOk (szSqlStr, cbSqlStr)) {
      AddError (0, 0, myHstmt, "S1090", 0, "Invalid string or buffer length");
      return SQL_ERROR;
   }
   DelError (0,0,myHstmt);

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = toCorbaString (szSqlStr, cbSqlStr);
   argv[3] = &cbSqlStr;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLPrepare", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   if (argv[2] != szSqlStr)
      delete (char *) argv[2];
   return Return;
}

//  Return the cursor name for a statement handle

RETCODE SQL_API SQLGetCursorName(
    HSTMT      hstmt,
    UCHAR FAR *szCursor,
    SWORD      cbCursorMax,
    SWORD FAR *pcbCursor)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[5];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;

   DelError (0,0,myHstmt);

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = szCursor;
   argv[3] = &cbCursorMax;
   argv[4] = pcbCursor;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLGetCursorName", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   return Return;
}

//  Set the cursor name on a statement handle

RETCODE SQL_API SQLSetCursorName(
    HSTMT       hstmt,
    UCHAR FAR  *szCursor,
    SWORD       cbCursor)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[4];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;

   DelError (0,0,myHstmt);

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = toCorbaString (szCursor, cbCursor);
   argv[3] = &cbCursor;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLSetCursorName", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   if (argv[2] != szCursor)
      delete (char *) argv[2];
   return Return;
}

//  Set parameters on a statement handle

RETCODE SQL_API SQLBindParameter(
    HSTMT       hstmt,
    UWORD       ipar,
    SWORD       fParamType,
    SWORD       fCType,
    SWORD       fSqlType,
    UDWORD      cbColDef,
    SWORD       ibScale,
    PTR         rgbValue,
    SDWORD      cbValueMax,
    SDWORD FAR *pcbValue)
{
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   Parameter *p;
   CORBA_TCKindDesc *kdesc = 0;
   int SqlToCDefault(int);
   CORBA_TCKindDesc * anyType (HSTMT, unsigned short, short *);

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;
   if (ipar == 0) {
      AddError (0, 0, myHstmt, "S1C00", 0, "Driver not capable");
      return SQL_ERROR;
   }
   DelError (0,0,myHstmt);
   if (fCType == SQL_C_DEFAULT) 
      fCType = SqlToCDefault (fSqlType);
   kdesc = anyType (0, 0, &fCType);
   if ((p = myHstmt->param.getAt (ipar)))
      delete p;

   myHstmt->param.setAt (ipar, new Parameter (fParamType, fCType,
                                              fSqlType, cbColDef, ibScale,
                                              rgbValue, cbValueMax, pcbValue, kdesc));
   return SQL_SUCCESS;
}


//  Returns the number of parameter markers.

RETCODE SQL_API SQLNumParams(
    HSTMT   hstmt,
    SWORD FAR *pcpar)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[3];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;

   DelError (0,0,myHstmt);

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = pcpar;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLNumParams", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   return Return;
}

//  Returns the description of a parameter marker.

RETCODE SQL_API SQLDescribeParam(
    HSTMT   hstmt,
    UWORD   ipar,
    SWORD FAR *pfSqlType,
    UDWORD FAR *pcbColDef,
    SWORD FAR *pibScale,
    SWORD FAR *pfNullable)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;

   DelError (0,0,myHstmt);

   void *argv[7];

   argv[0] = &Return;
   argv[1] = &myHstmt->srvHstmt;
   argv[2] = &ipar;
   argv[3] = pfSqlType;
   argv[4] = pcbColDef;
   argv[5] = pibScale;
   argv[6] = pfNullable;

   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLDescribeParam", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   return Return;
}

/*
//  Sets multiple values (arrays) for the set of parameter markers.

RETCODE SQL_API SQLParamOptions(
    HSTMT   hstmt,
    UDWORD  crow,
    UDWORD FAR *pirow)
{
       
   if (Trace.isSet)
      Trace.Write ("SQLParamOptions\n"); 
    return SQL_SUCCESS;
}

//  -   -   -   -   -   -   -   -   -

//  Sets options that control the behavior of cursors.

RETCODE SQL_API SQLSetScrollOptions(
    HSTMT   hstmt,
    UWORD   fConcurrency,
    SDWORD  crowKeyset,
    UWORD   crowRowset)
{
       
   if (Trace.isSet)
      Trace.Write ("SQLSetScrollOptions\n");
    return SQL_SUCCESS;
}
*/
};
