/*----------------------------------------------------------------------------*/
//  概要
//    ADOのデータ操作クラスのヘッダー ファイル
//  作成者
//    ぺがらぼ
//  ファイル名
//    AdoOperation.h
/*----------------------------------------------------------------------------*/

//  作成日:2002.3.28

#ifndef __ADOOPERATION__
#define __ADOOPERATION__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning (disable : 4146)

// ADOのタイプライブラリ情報
#define INITGUID_ADO  // これはADOを定義するための定数(GUID)の初期化
//#import "msado15.dll" rename_namespace("ADOCG") rename("EOF", "EndOfFile")
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename_namespace("ADOCG") rename("EOF", "EndOfFile")
using namespace ADOCG;  // 名前空間
#include "icrsint.h"    // ADOを使って取得したフィールドのデータを変換するマクロなどが定義されたヘッダー

class CAdoOperation
{
private:
  // --- メンバ変数
  _ConnectionPtr  m_pConnect;   // Connectionオブジェクト
    _CommandPtr     m_pCommand;   // Commandオブジェクト
    _RecordsetPtr   m_pRecordset; // Recordsetオブジェクト
  _bstr_t         m_strProvider;// プロバイダー情報
public:
    BOOL f_dClose();                            // レコードセットを閉じるだけ
    BOOL f_dOpen(const CString TableName);        // レコードセットを開くだけ
    BOOL f_dCancel();                            // DBの変更をキャンセル
    BOOL f_dImageSet(const CString FieldName,const _variant_t &VarData);    // 指定フィールドにイメージを設定
    BOOL f_dDataSet(const CString FieldName,const CString Value);    // 指定フィールドに文字列を設定
    BOOL f_dUpdate();                            // DBをアップデート
    BOOL f_dAddNew();                            // 空行の追加
  int  f_ExistTable(const _bstr_t &TableName);  // 指定したテーブルがあるか調べる
  // --- メンバ関数
  void    f_SetProvider(const CString GetProvider); // プロバイダー情報設定
  BOOL    f_ConnectOpen();                      // DBのコネクトを開く
  void    f_ConnectClose();                     // DBのコネクトを閉じる

  BOOL    f_rOpen(const _bstr_t &GetSqlScript); // DBのレコードセットを開く
  BOOL    f_rDel( const CString GetTableName, 
                  const CString GetFieldName, 
                  const CString GetCode); // レコード削除
  void    f_rClose();                           // DBのレコードセットを閉じる
  BOOL    f_rEOF();                             // EOF処理
  void    f_rMoveFirst();                       // 先頭のレコードへ
  void    f_rMoveNext();                        // 次のレコードへ
  LONG    f_rCount();                           // レコード数を取得
  BOOL    f_Execute(const _bstr_t &GetSqlScript); // DBのSQLスクリプト実行

  BOOL    f_BeginTran();                        // DB前処理
  void    f_EndTran(const BOOL &TranFlag);      // DB後処理
  
  CString f_GetDataSource();                    // データソース取得
  
  CString f_GetFieldData(const CString GetFieldName);           // レコードデータ取得(フィールド名指定)
  BOOL    f_AppendChunk(const CString &GetFieldName, const _variant_t &GetVarData);
  _variant_t f_GetChunk(const CString &GetFieldName, long &lChunkSize);
};

#endif // __ADOOPERATION__AdoOperation.h
****************************************************************************************************
↓AdoOperation.cpp


/*----------------------------------------------------------------------------*/
//    概要
//      ADOのデータ操作クラスのソース ファイル
//    作成者
//      ぺがらぼ
//  ファイル名
//    AdoOperation.cpp
/*----------------------------------------------------------------------------*/

//    作成日:2002.3.28

#include "stdafx.h"
#include "AdoOperation.h"

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      プロバイダー情報設定
//    2.パラメタ説明
//      なし。
//    3.概要
//      データベースのプロバイダー情報を取得し、内部変数に格納する
//    4.機能説明
//      (1) プロバイダー情報を取得
//      (2) 内部変数に格納
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_SetProvider(const CString GetProvider)
{
    m_strProvider = GetProvider;    // プロバイダ情報格納
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      データソース取得
//    2.パラメタ説明
//      なし。
//    3.概要
//      データソースを取得します。
//    4.機能説明
//      (1) データソース取得
//    5.戻り値
//      CString データソース
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
CString CAdoOperation::f_GetDataSource()
{
    return m_pRecordset->DataSource;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DBコネクトオープン
//    2.パラメタ説明
//      なし。
//    3.概要
//      DBのコネクトを開く
//    4.機能説明
//      (1) ADOオブジェクトの生成
//      (2) データベースへの接続
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_ConnectOpen()
{
    try {
        // COMの初期化処理
        ::CoInitialize(NULL);
        
        // ADOオブジェクトの生成
        m_pConnect.CreateInstance(__uuidof(Connection));
        m_pCommand.CreateInstance(__uuidof(Command));
        m_pRecordset.CreateInstance(__uuidof(Recordset));
        
        // データベースへの接続
        m_pConnect->Mode = adModeReadWrite;
        m_pConnect->Open(m_strProvider, L"", L"", adConnectUnspecified);
    }
    catch(_com_error &e){
        AfxMessageBox(e.Description());
        return FALSE; // 失敗
    }
    return TRUE; // 成功
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DBコネクトクローズ
//    2.パラメタ説明
//      なし。
//    3.概要
//      DBのコネクトを閉じる
//    4.機能説明
//      (1) DBのコネクトを閉じて、各変数をクリア。
//      (2) COMライブラリを閉じる。
//    5.戻り値
//      なし。
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_ConnectClose()
{
    if (m_pConnect)    {
        m_pConnect->Close();
        m_pConnect = 0;
        m_pCommand = 0;
        m_pRecordset = 0;
        ::CoUninitialize(); // COMライブラリをクローズ
    }
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DBレコードセットオープン
//    2.パラメタ説明
//      _bstr_t &GetSqlScript : SQLスクリプト文
//    3.概要
//      SQLスクリプトを実行する
//    4.機能説明
//      (1) SQLの設定
//      (2) レコードセットを取得
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_rOpen(const _bstr_t &GetSqlScript)
{
    try {
        // SQLの設定
        m_pCommand->ActiveConnection = m_pConnect;
        m_pCommand->CommandText = GetSqlScript; // 取得したSQL文をセットする
        m_pRecordset->PutRefSource(m_pCommand);
        
        // レコードセットを取得
        _variant_t vNull;  // VARIANT型のNULLとして使う
        vNull.vt = VT_ERROR;
        vNull.scode = DISP_E_PARAMNOTFOUND;
        m_pRecordset->Open(vNull, vNull, adOpenDynamic, adLockPessimistic, adCmdUnknown);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DBスクリプト実行
//    2.パラメタ説明
//      _bstr_t &GetSqlScript : SQLスクリプト文
//    3.概要
//      SQLスクリプトを実行する
//    4.機能説明
//      (1) SQLの設定
//      (2) スクリプト実行
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_Execute(const _bstr_t &GetSqlScript)
{
    try {
        // SQLの設定
        m_pCommand->ActiveConnection = m_pConnect;
        m_pCommand->CommandText = GetSqlScript; // 取得したSQL文をセットする
        m_pRecordset->PutRefSource(m_pCommand);
        
        // スクリプト実行
        _variant_t vNull;  // VARIANT型のNULLとして使う
        vNull.vt = VT_ERROR;
        vNull.scode = DISP_E_PARAMNOTFOUND;
        m_pCommand->Execute(NULL, NULL, adCmdText);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      バイナリデータ書込み
//    2.パラメタ説明
//      CString      &GetFieldName : フィールド名
//      _variant_t  &GetVarData  : バリアントデータ
//    3.概要
//      カレントレコードの指定カラムにバイナリ型のデータをセット
//    4.機能説明
//      (1) カレントレコードの指定カラムにバイナリ型のデータをセットする
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_AppendChunk(const CString &GetFieldName, const _variant_t &GetVarData)
{
    _variant_t varField;
    
    varField.SetString(GetFieldName);
    
    try{
        m_pRecordset->Fields->GetItem(varField)->AppendChunk(GetVarData);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}


/*----------------------------------------------------------------------------*/
//    1.日本語名
//      バイナリデータ取込
//    2.パラメタ説明
//      CString      &GetTableName   : テーブル名
//      CString      &GetFieldName   : フィールド名
//      CString      &GetStrWhere      : 検索条件
//      _variant_t  &GetVarData      : バイナリデータ
//    3.概要
//      登録されたレコード内のバイナリフィールドを格納し更新する
//    4.機能説明
//      (1) 登録されたレコード内のバイナリフィールドを格納し更新する
//    5.戻り値
//      BOOL : TRUE(成功),FALSE(失敗)
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
_variant_t CAdoOperation::f_GetChunk(const CString &GetFieldName, long &lChunkSize)
{
    _variant_t varFieldName;
    _variant_t varRet;
    
    varFieldName.SetString(GetFieldName);
    
    try{
        lChunkSize = m_pRecordset->Fields->GetItem(varFieldName)->ActualSize;  // データサイズ取得
        if(lChunkSize > 0){
            varRet = m_pRecordset->Fields->GetItem(varFieldName)->GetChunk(lChunkSize); // データ取得
        }
    }
    catch(...){
        // 失敗
        lChunkSize = 0;
        varRet.vt = VT_NULL; 
    }
    return varRet;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DBレコードセットクローズ
//    2.パラメタ説明
//      なし。
//    3.概要
//      DBのレコードセットを閉じる
//    4.機能説明
//      (1) DBのレコードセットを閉じる。
//    5.戻り値
//      なし。
//    6.備考
//      たった一行の処理だが、カプセル化しているので必要である。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_rClose()
{
    m_pRecordset->Close();
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      レコードデータ取得
//    2.パラメタ説明
//      CString GetFieldName : データフィールド名
//    3.概要
//      DBのレコードデータをフィールド名指定で取得
//    4.機能説明
//      (1) レコードデータを取得
//    5.戻り値
//      CString : レコードのフィールドデータ
//    6.備考
//      データはとりあえず、いかなるデータも文字列として返す。
/*----------------------------------------------------------------------------*/
CString CAdoOperation::f_GetFieldData(const CString GetFieldName)
{
    CString strRet; // 戻り値用
    
    try{
        _variant_t vString;
        vString = m_pRecordset->GetCollect(_variant_t(GetFieldName));
        if(vString.vt!=VT_NULL){
            vString.ChangeType(VT_BSTR);
            strRet = vString.bstrVal;
        }
        else{
            strRet = "";
        }
    }
    catch(...){
        // データ取得失敗
        strRet = "";
    }
    return strRet;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      EOF処理
//    2.パラメタ説明
//      なし。
//    3.概要
//      EOFのフラグを取得する。
//    4.機能説明
//      (1) EOFのフラグを取得する。
//    5.戻り値
//      BOOL : TRUE=EOF,FALSE=EOFではない。
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_rEOF()
{
    if( m_pRecordset->GetEndOfFile() )
        return TRUE;
    else
        return FALSE;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      先頭のレコード移動処理
//    2.パラメタ説明
//      なし。
//    3.概要
//      先頭のレコード移動する。
//    4.機能説明
//      (1) 先頭のレコード移動する。
//    5.戻り値
//      なし。
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_rMoveFirst()
{ 
    m_pRecordset->MoveFirst(); 
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      次のレコード移動処理
//    2.パラメタ説明
//      なし。
//    3.概要
//      次のレコード移動する。
//    4.機能説明
//      (1) 次のレコード移動する。
//    5.戻り値
//      なし。
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_rMoveNext()
{ 
    m_pRecordset->MoveNext(); 
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      データレコード件数取得
//    2.パラメタ説明
//      なし。
//    3.概要
//      データのレコード件数を取得する。
//    4.機能説明
//      (1) データレコード件数取得する。
//    5.戻り値
//      int レコード数
//    6.備考
//      サポートされていません
/*----------------------------------------------------------------------------*/
LONG CAdoOperation::f_rCount()
{ 
    LONG LRet;
    LRet = m_pRecordset->RecordCount;
    return LRet;
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DB前処理
//    2.パラメタ説明
//      なし。
//    3.概要
//      トランザクションの手順をロールバックできるようにします。
//    4.機能説明
//      (1) DBの前処理
// 5.戻り値
//     TRUE:成功,FALSE:失敗
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_BeginTran()
{
    return m_pConnect->BeginTrans();
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      DB後処理
//    2.パラメタ説明
//      BOOL &TranFlag : 処理フラグ
//    3.概要
//      処理フラグが[TRUE]であれば、データソースに対するすべての変更を受け入れ、実行し、
//      [FALSE]であれば、トランザクションで行った変更を元に戻します。
//    4.機能説明
//      (1) DBの後処理
// 5.戻り値
//     なし。
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
void CAdoOperation::f_EndTran(const BOOL &TranFlag)
{
    if( TranFlag == TRUE )
        m_pConnect->CommitTrans();
    else
        m_pConnect->RollbackTrans();
}

/*----------------------------------------------------------------------------*/
//    1.日本語名
//      レコード削除処理
//    2.パラメタ説明
//      CString GetTableName    : テーブル名
//      CString GetFieldName    : データフィールド名
//      CString GetCode        : 削除すべきレコードのコードキー
//    3.概要
//      レコードの削除処理
//    4.機能説明
//      (1) レコードの削除処理
//    5.戻り値
//      BOOL : TRUE:成功 , FALSE:失敗
//    6.備考
//      なし。
/*----------------------------------------------------------------------------*/
BOOL CAdoOperation::f_rDel(const CString GetTableName, 
                           const CString GetFieldName, 
                           const CString GetCode)
{
    _bstr_t SqlScript;  // SQLスクリプト用
    
    try{
        SqlScript = "";
        SqlScript = SqlScript + L"DELETE FROM ";
        SqlScript = SqlScript + GetTableName;
        SqlScript = SqlScript + L" WHERE ";
        SqlScript = SqlScript + GetFieldName;
        SqlScript = SqlScript + L" = '";
        SqlScript = SqlScript + GetCode;
        SqlScript = SqlScript + L"' ";
        
        // SQLの設定
        m_pCommand->ActiveConnection = m_pConnect;
        m_pCommand->CommandText = SqlScript; // 作成したSQL文をセットする
        m_pRecordset->PutRefSource(m_pCommand);
        
        // レコードを削除
        _variant_t vNull;  // VARIANT型のNULLとして使う
        vNull.vt = VT_ERROR;
        vNull.scode = DISP_E_PARAMNOTFOUND;
        m_pRecordset->Open(vNull, vNull, adOpenDynamic, adLockOptimistic, adCmdUnknown);
    }
    catch(_com_error &e){
        // データ削除失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}


// 開かれているテーブルに空行を追加
BOOL CAdoOperation::f_dAddNew()
{
    try{
        m_pRecordset->AddNew();
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// DB更新
BOOL CAdoOperation::f_dUpdate()
{
    try{
        m_pRecordset->Update();
        //        m_pRecordset->Close();
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// カレントレコードの指定カラムに値(文字列)をセット
BOOL CAdoOperation::f_dDataSet(const CString FieldName, const CString Value)
{
    _variant_t varField;
    _variant_t varValue;
    
    varField.SetString(FieldName);
    varValue.SetString(Value);
    
    try{
        m_pRecordset->Fields->GetItem(varField)->PutValue(varValue);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// カレントレコードの指定カラムにイメージをセット
BOOL CAdoOperation::f_dImageSet(const CString FieldName, const _variant_t &VarData)
{
    _variant_t varField;
    
    varField.SetString(FieldName);
    
    try{
        m_pRecordset->Fields->GetItem(varField)->AppendChunk(VarData);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// 変更のキャンセル
BOOL CAdoOperation::f_dCancel()
{
    try{
        m_pRecordset->CancelUpdate();;
        //        m_pRecordset->Close();
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// レコードセットのオープン
BOOL CAdoOperation::f_dOpen(const CString TableName)
{
    _variant_t varTableName;
    varTableName.SetString(TableName);
    
    try{
    /*******************************************************
    _variant_t vNull;  // VARIANT型のNULLとして使う
    vNull.vt = VT_ERROR;
    vNull.scode = DISP_E_PARAMNOTFOUND;
    // SQLの設定
    m_pCommand->ActiveConnection = m_pConnect;
    m_pRecordset->PutRefSource(m_pCommand);
    
      // レコードセットを取得
      _variant_t vNull;  // VARIANT型のNULLとして使う
      vNull.vt = VT_ERROR;
      vNull.scode = DISP_E_PARAMNOTFOUND;
      //        m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
      //            adOpenKeyset, adLockPessimistic, adCmdTable);
      m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
      adOpenDynamic, adLockPessimistic, adCmdUnknown);
      //        m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
      //            adOpenDynamic, adLockBatchOptimistic, adCmdUnknown);
        ********************************************************/
        // MSDN SAMPLE
        //        m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
        //            adOpenKeyset, adLockPessimistic, adCmdTable);
        m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
            adOpenDynamic, adLockPessimistic, adCmdUnknown);
        //        m_pRecordset->Open(varTableName, _variant_t((IDispatch *) m_pConnect, true),
        //            adOpenDynamic, adLockBatchOptimistic, adCmdUnknown);
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// レコードセットのクローズ
BOOL CAdoOperation::f_dClose()
{
    try{
        m_pRecordset->Close();
    }
    catch(_com_error &e){
        // データ操作失敗
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return TRUE;
}

// 指定したテーブルが存在しているか調べる
// 戻り値 0=なし
//     1=あり
//     -1=エラー
int CAdoOperation::f_ExistTable(const _bstr_t &TableName)
{
    BOOL bolRet=FALSE;
    _RecordsetPtr pRstSchema=NULL;
    
    try{
        pRstSchema=m_pConnect->OpenSchema(adSchemaTables);
        
        while(!(pRstSchema->EndOfFile)){
            _bstr_t table_name=pRstSchema->Fields->GetItem("TABLE_NAME")->Value;
            _bstr_t table_type=pRstSchema->Fields->GetItem("TABLE_TYPE")->Value; 
            if(!strcmp((LPCSTR)table_name,(LPCSTR)TableName)){
                bolRet=TRUE;
                break;
            }
            pRstSchema->MoveNext();
        }
        pRstSchema->Close();
    }
    catch(_com_error &e){
        AfxMessageBox(e.Description());
        return FALSE;
    }
    return bolRet;
}