/* Klaus Thiele (kth@oblib.teuto.de) - June '95 */
/*
INTERFACE TO
  mSQL
REVISION HISTORY
  07/10/95 API release 1.00
DESCRIPTION
  mSQLBase function implementation
*/

extern "C" {
#include <sql.h>
}
#include <sql_priv.h>
#include <errsql.h>

// =======================================================================
// the Instance
// =======================================================================
mSqlBase msqlbase;

// =======================================================================
// SQLBase Functions
// =======================================================================

// CoNnect Cursor
SQLTAPI sqlcnc(SQLTCUR *curp, SQLTDAP dbnamp, SQLTDAL dbnaml, SQLTDAP host) {

int newCursor;
int rc;

   if( (newCursor = msqlbase.createCursor( (char *)host,
                                           (char *)dbnamp, (int)dbnaml,
                                           &rc )) < 0 )
      return( rc );

   *curp = (SQLTCUR)newCursor;

   return( 0 );
}

// Connect with No Recovery
SQLTAPI sqlcnr(SQLTCUR *curp, SQLTDAP dbnamp, SQLTDAL dbnaml, SQLTDAP host) {
   return( sqlcnc(curp,dbnamp,dbnaml,host) );
}

// DISconnect from cursor
SQLTAPI sqldis(SQLTCUR cur) {

   if( msqlbase[cur] ) {

      msqlbase.deleteCursor( (int)cur );

   } else return( SQLEICN );

   return( 0 );
}

// FETch next row from result
SQLTAPI sqlfet(SQLTCUR cur) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->Fetch() );
   else return( SQLEICN );
}

// Position in Result Set
SQLTAPI sqlprs(SQLTCUR cur, SQLTROW row) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->SetRowPos(row) );
   else return( SQLEICN );
}

// COMpile a SQL command
SQLTAPI sqlcom(SQLTCUR cur, SQLTDAP cmdp, SQLTDAL cmdl) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->Compile((char *)cmdp, (int)cmdl) );
   else return( SQLEICN );
}

// Clear Bind Variables
SQLTAPI sqlcbv(SQLTCUR cur) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->ClearBindVars() );
   else return( SQLEICN );
}

// BiNd Data by name
SQLTAPI sqlbnd(SQLTCUR cur, SQLTBNP bnp, SQLTBNL bnl,
               SQLTDAP dap, SQLTDAL dal, SQLTSCA /*sca*/,
               SQLTPDT pdt) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->BindName((char *)bnp, (int)bnl, (void *)dap, (int)dal, (int)pdt ) );
   else return( SQLEICN );
}

// BiNd data by Number
SQLTAPI sqlbnn(SQLTCUR cur, SQLTBNN bnn, SQLTDAP dap,
               SQLTDAL dal, SQLTSCA /*sca*/, SQLTPDT pdt) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->BindNum((int)bnn, (void *)dap, (int)dal, (int)pdt ) );
   else return( SQLEICN );
}

// Set SELECT Buffer
SQLTAPI sqlssb(SQLTCUR cur, SQLTSLC slc, SQLTPDT pdt, SQLTDAP pbp,
                    SQLTPDL pdl, SQLTSCA /*sca*/, SQLTCDL PTR cvl,
                    SQLTFSC PTR pfc) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->SetSelectBuf((int)slc, (int)pdt, (void *)pbp, (int)pdl,
                                             (unsigned char *)cvl, (unsigned char *)pfc ) );
   else return( SQLEICN );
}

// EXEcute a SQL command
SQLTAPI sqlexe(SQLTCUR cur) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->Execute() );
   else return( SQLEICN );
}

// Compile and EXecute
SQLTAPI sqlcex(SQLTCUR cur, SQLTDAP dap, SQLTDAL dal ) {

SQLTRCD rcd;

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) {

      if( (rcd = cursor->Compile((char *)dap, (int)dal)) != 0 )
         return( rcd );

      return( cursor->Execute() );

   } else return( SQLEICN );
}

// Return CoDe
SQLTAPI sqlrcd( SQLTCUR cur, SQLTRCD PTR rcd ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) {
      cursor->RetCode(rcd);
      return( 0 );
   } else return( SQLEICN );
}

// ERRor message
SQLTAPI sqlerr(SQLTRCD error, SQLTDAP msg) {

   switch( error ) {

     case 0:
        strcpy( (char *)msg, "No error :-)" );
        break;
     case FETEEOF:
        strcpy( (char *)msg, "End of fetch" );
        break;
     case SQLECNC:
        strcpy( (char *)msg, msqlErrMsg ); /* msqlConnect error */
        break;
     case SQLECCS:
        strcpy( (char *)msg, "Out of memory at the client workstation" );
        break;
     case SQLESTS:
        strcpy( (char *)msg, "Select buffer is too small" );
        break;
     case SQLEDNN:
        strcpy( (char *)msg, "Attempt to fetch non-numeric data into numeric column" );
        break;
     case SQLENOF:
        strcpy( (char *)msg, "Attempt to fetch into numeric column that is too small" );
        break;
     case SQLEDTN:
        strcpy( (char *)msg, "Data type not supported" );
        break;
     case SQLEIRN:
        strcpy( (char *)msg, "Invalid row number" );
        break;
     case SQLERNA:
        strcpy( (char *)msg, "Result sets not active" );
        break;
     case SQLEICN:
        strcpy( (char *)msg, "Invalid cursor number" );
        break;
     case SQLEMSC:
        strcpy( (char *)msg, "Must follow a successful compile of a SELECT statement" );
        break;
     case SQLE058:
        strcpy( (char *)msg, msqlErrMsg ); /* msqlQuery error */
        break;
     case SQLE065:
        strcpy( (char *)msg, "No Field list" );
        break;
     case SQLE071:
        strcpy( (char *)msg, "Field not found" );
        break;
     case SQLETMB:
        strcpy( (char *)msg, "To many bind variables" );
        break;
     case SQLE073:
        strcpy( (char *)msg, "Bind data ptr is NULL" );
        break;
     case SQLEIVC:
        strcpy( (char *)msg, "Invalid bind name or bind number" );
        break;

     case DBAECOD:
        strcpy( (char *)msg, msqlErrMsg ); /* msqlSelectDB error */
        break;
     case DBOENEX:
        strcpy( (char *)msg, "Command has not been executed" );
        break;

     case PRSEISC:
        strcpy( (char *)msg, "Invalid SQL statement" );
        break;
     case PRSEMIK:
        strcpy( (char *)msg, "Missing INTO keyword" );
        break;
     case PRSEMFC:
        strcpy( (char *)msg, "Missing FROM clause" );
        break;

     case TLKETND:
        strcpy( (char *)msg, "Table not found in dictionary" ); /* msqld only writes to logfile */
        break;

     default:
        strcpy( (char *)msg, "Unknown errornumber" );
        break;
   }

   return( 0 );
}

// get Number of Select Items
SQLTAPI sqlnsi(SQLTCUR cur, SQLTNSI PTR nsi ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->getNumSelItems(nsi) );
   else return( SQLEICN );
}

// get Number of Bind Variables
SQLTAPI sqlnbv(SQLTCUR cur, SQLTNBV PTR nbv ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->getNumBndVars(nbv) );
   else return( SQLEICN );
}

// get Number of Rows in Result set
SQLTAPI sqlnrr(SQLTCUR cur, SQLTROW PTR rcountp ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->getNumRows(rcountp) );
   else return( SQLEICN );
}

// DeSCribe item in a SELECT
SQLTAPI sqldsc(SQLTCUR cur, SQLTSLC slc, SQLTDDT PTR edt,
               SQLTDDL PTR edl, SQLTCHP chp, SQLTCHL PTR chlp,
               SQLTPRE PTR /*prep*/, SQLTSCA PTR /*scap*/ ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->describeItem(slc, edt, edl, chp, chlp) );
   else return( SQLEICN );
}

// DEScribe item in a SELECT
SQLTAPI sqldes(SQLTCUR cur, SQLTSLC slc, SQLTDDT PTR ddt,
               SQLTDDL PTR ddl, SQLTCHP chp, SQLTCHL PTR chlp,
               SQLTPRE PTR /*prep*/, SQLTSCA PTR /*scap*/ ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->describeItem(slc, ddt, ddl, chp, chlp, NULL) );
   else return( SQLEICN );
}

// Command TYpe
SQLTAPI sqlcty(SQLTCUR cur, SQLTCTY PTR cty) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->getCmdType(cty) );
   else return( SQLEICN );
}

// =======================================================================
// Functions not really supported
// =======================================================================

// DONe
SQLTAPI sqldon( ) {

   for( int i = 0; i < MAX_CURSORS; i++ ) {

      if( msqlbase[i] ) {
         sqlrbk( (SQLTCUR)i );
         sqldis( (SQLTCUR)i );
      }

   }

   return( 0 );
}

// SET parameter
SQLTAPI sqlset(SQLTCUR cur, SQLTPTY parm, SQLTDAP p, SQLTDAL /*l*/) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->SetParm(parm, p) );
   else return( SQLEICN );
}

// GET parameter
SQLTAPI sqlget(SQLTCUR cur, SQLTPTY parm, SQLTDAP p, SQLTDAL PTR /*l*/) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->GetParm(parm, p) );
   else return( SQLEICN );
}

// Start Restriction Set and Result Set modes
SQLTAPI sqlsrs(SQLTCUR cur ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->SetParm(START_SRS, NULL) );
   else return( SQLEICN );
}

// Close ReStriction Set and Result Set modes
SQLTAPI sqlcrs(SQLTCUR cur, SQLTDAP /*rsp*/, SQLTDAL /*rsl*/ ) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->SetParm(END_SRS, NULL) );
   else return( SQLEICN );
}

// number of ROWs
SQLTAPI sqlrow( SQLTCUR cur, SQLTROW PTR row ) {

   if( msqlbase[cur] ) {
      *row = 0;
      return( 0 );
   } else return( SQLEICN );
}

// Error POsition
SQLTAPI sqlepo( SQLTCUR cur, SQLTEPO PTR epo ) {

   if( msqlbase[cur] ) {
      *epo = 0;    // currently not supported
      return( 0 );
   } else return( SQLEICN );
}

// Roll Back Flag
SQLTAPI sqlrbf( SQLTCUR cur, SQLTRBF PTR rbf ) {

   if( msqlbase[cur] ) {
      *rbf = 0;    // currently not supported
      return( 0 );
   } else return( SQLEICN );
}

// CoMmiT
SQLTAPI sqlcmt(SQLTCUR cur) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) {

      for( int i = 0; i < MAX_CURSORS; i++ ) {
         if( msqlbase[i] &&
             strcmp(cursor->getDbaseName(),msqlbase[i]->getDbaseName()) == 0 )
            msqlbase[i]->Reset();
      }
      return( 0 );

   } else  return( SQLEICN );
}

// RollBacK
SQLTAPI sqlrbk(SQLTCUR cur) {

   return( sqlcmt(cur) );
}

// Set Isolation Level
SQLTAPI sqlsil(SQLTCUR cur, SQLTILV /*isolation*/) {

   if( msqlbase[cur] == NULL )
      return( SQLEICN );

   return( 0 );
}

// StoP Restriction mode
SQLTAPI sqlspr(SQLTCUR cur ) {

   if( msqlbase[cur] == NULL )
      return( SQLEICN );

   return( 0 );
}

// tokenize errro message
SQLTAPI sqltem(SQLTCUR cur, SQLTXER PTR /*xer*/, SQLTPTY /*msgtyp*/,
               SQLTDAP bfp, SQLTDAL /*bfl*/, SQLTDAL PTR txtlen) {

SQLTRCD rcd;

   if( msqlbase[cur] ) {
      if( sqlrcd( cur, &rcd ) != 0 ) rcd = 9999;
      if(sqlerr(rcd,bfp) == 0) *txtlen = strlen((const char *)bfp);
   }else return( SQLEICN );

   return( 0 );
}

// DataBase Names
SQLTAPI sqldbn(SQLTDAP serverid, SQLTDAP buffer, SQLTDAL length) {

int	 sd;
m_result *dbResult;
m_row    dbRow;
char     *buf_end;

   memset( (void *)buffer, '\0', (size_t)length );
   buf_end = (char *)buffer + length - 2;

   if( (sd = msqlConnect( (char *)serverid )) < 0 )
      return( SQLECNC );

   dbResult = msqlListDBs( sd );

   while( (dbRow = msqlFetchRow(dbResult)) != NULL ) {

      if( (char *)buffer + strlen((char *)dbRow[0]) > buf_end )
         break;

      strcpy( (char *)buffer, (char *)dbRow[0] );
      (char *)buffer += strlen((char *)buffer) + 1;

   }

   msqlFreeResult( dbResult );
   msqlClose( sd );
   return( 0 );
}

// DataBase Tables
SQLTAPI sqldbt(SQLTCUR cur, SQLTDAP buffer, SQLTDAL length) {

   mSqlCursor *cursor = msqlbase[cur];

   if( cursor ) return( cursor->ListTables((char *)buffer, (int)length) );
   else return( SQLEICN );
}


// eXtended convert Picture to Date
SQLTAPI sqlxpd(SQLTNMP op, SQLTNML PTR olp, SQLTDAP ip,
               SQLTDAP /*pp*/, SQLTDAL /*pl*/) {

   strcpy( (char *)op, (const char *)ip );
   *olp = strlen((const char *)op);

   return( 0 );
}

// eXtended convert Date to Picture
SQLTAPI sqlxdp(SQLTDAP op, SQLTDAL ol, SQLTNMP ip, SQLTNML /*il*/,
               SQLTDAP /*pp*/, SQLTDAL /*pl*/) {

   strncpy( (char *)op, (const char *)ip, (size_t)ol );

   return( 0 );
}


#ifdef __TEST__
// =======================================================================
// dummy-code, when i edit/compile with Borland C++
// =======================================================================
char msqlErrMsg[80];

int msqlConnect(char *) {
   return 123;
}

int msqlSelectDB(int, char *) {
   return 0;
}

int msqlQuery(int, char *) {
   return 0;
}

void msqlClose(int) {
}

m_result *msqlStoreResult() {
   return NULL;
}

void msqlFreeResult( m_result * ) {
}

m_row msqlFetchRow( m_result * ) {
   return NULL;
}

m_result *msqlListDBs( int ) {
   return NULL;
}

m_result *msqlListFields( int, char * ) {
   return NULL;
}

m_field *msqlFetchField( m_result * ) {
   return NULL;
}
#endif
