/////////////////////////////////////////////////////////////////////////////
// Name:        MyODBC classes
// Purpose:     
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/07/27
// RCS-ID:      $Id: myodbc.h,v 1.2 2001/05/10 11:25:38 georgetasker Exp $
// Copyright:   (c) 2000 PM-Soft
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#ifndef __MYODBC_G__
#define __MYODBC_G__

#include "wx/object.h"
#include "wx/datetime.h"
#include "wx/dynarray.h"

class MyDriverManager;
class MyConnection;
class MyStatement;
class MyResultSet;
class MyResultSetMetaData;

// define our own replacements for SQL-types to avoid
// poluting header-space with sql.h and windows.h

typedef int MYODBC_HENV;
typedef int MYODBC_HDBC;
typedef int MYODBC_HSTMT;

// classes available

class MyDriverManager;
class MyConnection;
class MyStatement;
class MyResultSet;
class MyResultSetMetaData;
class MyColumnInfo;

class MyDriverManager : public wxObject
{
public:
  static MyConnection* GetConnection( const wxString& dsn, 
                      const wxString& user, 
                    const wxString& password);
  static void ShutDown();

  static void SetDateTimeFormat( const wxString& fmt );
  static void SetFloatFormat( const wxString& fmt );
  static const char* GetDateTimeFormat();
  static const char* GetFloatFormat();

  static MYODBC_HENV GetHEnv();

protected:
  static void CheckStarted();
  static void Init();

protected:
    static MYODBC_HENV mHEnv;
  static char mDateTimeFormat[100];
  static char mFloatFormat[100];
};

class MyColumnInfo : public wxObject
{
public:
  wxString mName;
  
  int    mSqlType;
  int      mCType;

  int    mSize;  // size of C-type in bytes

  bool   mIsNulable;
  int    mScale;
  int    mPrecision;

  char     mStrSqlType[20]; // to ease debugging
  char   mStrCType[20];   // -/-
};

class MyColumnData : public wxObject
{
public:
  MyColumnData();
  ~MyColumnData();

public:
  MyColumnInfo* mpInfo;

  char*     mSetValues;
  unsigned long*  mSetSizes;

  char*       mCachedValues;
  unsigned long*  mCachedSizes;
};

WX_DEFINE_ARRAY( MyColumnInfo*, MyColumnInfoArrayT );

class MyResultSetMetaData
{
public:
  MyResultSetMetaData();
  virtual ~MyResultSetMetaData();

  virtual void SetResultSet( MyResultSet* pSet );

  virtual int GetColumnCount();
  virtual int GetColumnSqlType( int col );
  virtual int GetColumnCType( int col );
  virtual const wxString& GetColumnName( int col );

protected:
  friend class MyResultSet;

  MyColumnInfoArrayT mColumns;
  MyResultSet*     mpResultSet;
};

class MyResultSet
{
public:
  enum RESULT_SET_TYPE
  {
      RS_TYPE_FORWARD_ONLY,

      RS_TYPE_SCROLL_INSENSITIVE,
      RS_TYPE_SCROLL_SENSITIVE
  };

  MyResultSet( MYODBC_HSTMT hstmt );

  virtual ~MyResultSet();

  virtual void SetFetchSize( int fetchSize );
  virtual int GetFetchSize();

  virtual bool BeforeFirst();
  virtual bool First();
  virtual bool Last();

  virtual bool Previous();
  virtual bool Next();

  virtual bool IsBeforeFirst();
  virtual bool IsAfterLast();
  virtual bool IsEof();

  virtual int GetCurrentRowPos();
  virtual bool SetCurrentRowPos( int pos );

  // column index is 1-based

  virtual wxString GetString( int colIdx );
  virtual int GetInt( int colIdx );
  virtual double GetDouble( int colIdx );
  virtual wxDateTime GetTime( int colIdx );

  virtual MyResultSetMetaData* GetMetaData();

  virtual int GetCacheSize();
  virtual int GetCacheUsed();

  virtual void InsertCacheRows( int atPos, int nRows );
  virtual void RemoveCacheRows( int atPos, int nRows );

  virtual int FindInsertionPos( int colNo, const wxString& value, bool isAscending );
  virtual void SetCacheRowValue( int row, int col, const wxString& value );

protected:
  virtual void ExpandCache( int newSize );
  virtual void ReallocRowSetSpace();
  virtual void CacheRowsetData();
  virtual void BindColumns();
  virtual void FetchMetaData();
  virtual void* GetDataPtr( int colIdx );

  virtual void DestroyCaches();

  void DoInsertCacheRows( MyColumnData* pCol, int atPos, int nRows );
  void DoRemoveCacheRows( MyColumnData* pCol, int atPos, int nRows );

protected:
  MYODBC_HSTMT     mHStmt;
  MyResultSetMetaData  mMetaData;

  MyColumnData*    mColData;
  int          mColCount;
  int          mCacheUsed;
  int          mCacheSize;

  int          mFetchSize;

  // iteration-state
  int          mCurRow;
  int          mRowSetFirstRow;
  int          mRowSetSize;

  bool           mEOFReached;
};

// values for mCurRow

enum
{
  POS_BEFORE_FIRST = (-3),
  POS_AFTER_LAST   = (-2),
  POS_INSERT_ROW   = (-1),
  POS_UNKNOWN    = (-4)
};

class MyConnection : public wxObject
{
public:
  MyConnection( MYODBC_HDBC hdbc );

  virtual MyStatement* CreateStatement( MyResultSet::RESULT_SET_TYPE rsType = MyResultSet::RS_TYPE_FORWARD_ONLY );

  virtual bool ExecuteDirectSQL( const wxString sqlStmtStr );

  virtual bool Commit();
  virtual bool RollBack();

protected:
  MYODBC_HDBC mHdbc;
};

class MyStatement : public wxObject
{
public:
  MyStatement( MyResultSet::RESULT_SET_TYPE, MYODBC_HSTMT hstmt );
  ~MyStatement();

  virtual MyResultSet* ExecuteQuery( const wxString& queryStr );
  virtual bool ExecuteDirectSQL( const wxString& queryStr, int* pRowsAffected = NULL );

protected:
  MYODBC_HSTMT mHStmt;
};

#endif // __MYODBC_G__
