[BlueLeaf1336]> PROGRAM>

ODBCのドライバとデータソースの一覧を取得する

historyTOP

2007/01/01:作成

はじめにTOP

昔ダウンロードしたサンプルを何気なく眺めていると、

'********************************************************************************
'ODBC登録クラス
'
'動作確認環境
' Win2000 SP3 + VB6/SP5
' Win98 + Plus!98 + VB6/SP5
'
'使用条件
'  このサンプルコードはフリーウェアです。
'  著作権は「ざこぴ」が保有しますが、自由にプロジェクトに組み込んでも構いません。
'  再配布も可能ですが、事前にメールをお願いします。
'  バグ、動作確認環境などについてもメールをいただけると幸いです。
'  ※ご自由に改造、複写、譲渡されても構いませんが、作者は一切の責任を負いません。
'
'                                              Copyright 2003 Programed By ZAKOP.
'********************************************************************************

というコメントの入った4つのファイルを見つけました。

「ODBC」フォルダに保存してあり、VBのソースを見てみると主な内容は次のようなAPIを呼び出しているもののようです。

フォルダの作成日時が2006年1月7日になっていて、コレまで一度も使ったことがないサンプルなのでこれからも使わないこと必至ですが、Delphiでやってみることにしました。そしえ、このサンプルをハードディスクから整理しようと。

といっても、「DSNを追加、修正、削除」するのはやめて、データソースの一覧取得だけをいただくことにします。同時にPlatform SDKで見つけたドライバ一覧取得のAPIも試してみることにしました。

ダウンロードTOP

odbclist20070101.zip(167,630Bytes) ソースコードと実行ファイルです。

実行結果のスクリーンショットTOP

まずはドライバ一覧

次がデータソース一覧

こうやって見てみるとまったくフォームを持っている意味がないことに気づきます。資源を有効に使うためにもこれからは、こういう何かをテキストで出力するだけのサンプルはコンソールアプリケーションにするべきだなぁと思いました。

主なAPIと翻訳元ヘッダTOP

主なAPI

主な翻訳元ヘッダファイル(PlatformSDK)

ソースコードTOP

Delphi6 Personal では多分翻訳されてないようなAPIを使っているので implementation をまたいでいます。それから引数の翻訳は相変わらず確信なしですので、動いているという事実だけがこのソースの存在意義です。

type
    USHORT          = Word;

    //  ODBC用型宣言
    SQLSMALLINT     = SHORT;
    SQLRETURN       = SQLSMALLINT;
    SQLINTEGER      = Longint;
    SQLHANDLE       = SQLINTEGER;
    SQLHENV         = SQLHANDLE;
    SQLUSMALLINT    = USHORT;
    SQLPCHAR        = PChar;

const
    //  DLL名
    odbc32 = 'odbc32.dll';

    //  return values from functions
    SQL_SUCCESS             = 0;
    SQL_SUCCESS_WITH_INFO   = 1;
    SQL_INVALID_HANDLE      = -2;
    SQL_ERROR               = -1;
    SQL_NO_DATA             = 100;
    SQL_NO_DATA_FOUND       = SQL_NO_DATA;

    //  全てのリソースをフェッチ
    SQL_FETCH_NEXT          = 1;
    //  ユーザーリソースのみをフェッチ
    SQL_FETCH_FIRST_USER    = 31;
    //  システムリソースのみをフェッチ
    SQL_FETCH_FIRST_SYSTEM  = 32;
    //  次を検索
    SQL_FETCH_FIRST         = 2;

    //  SQLDataSources() の BufferLength1 には SQL_MAX_DSN_LENGTH+1 で十分
    SQL_MAX_DSN_LENGTH      = 32;

//  環境ハンドルを設定する
//  戻値:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_INVALID_HANDLE, SQL_ERROR
function SQLAllocEnv(var EnvironmentHandle: SQLHENV): SQLRETURN;
    stdcall; external odbc32 name 'SQLAllocEnv';

//  環境ハンドルを開放する
function SQLFreeEnv(EnvironmentHandle: SQLHENV): SQLRETURN;
    stdcall; external odbc32 name 'SQLFreeEnv';

//  ドライバ名を取得する
//  戻値:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA, SQL_ERROR, SQL_INVALID_HANDLE.
function SQLDrivers(
     EnvironmentHandle: SQLHENV;
     Direction: SQLUSMALLINT;
     DriverDescription: SQLPCHAR;
     BufferLength1: SQLSMALLINT;
     var DescriptionLengthPtr: SQLSMALLINT;
     DriverAttributes: SQLPCHAR;
     BufferLength2: SQLSMALLINT;
     var AttributesLengthPtr: SQLSMALLINT): SQLRETURN;
     stdcall; external odbc32 name 'SQLDrivers';

//  データソース名を取得する
//  戻値:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA, SQL_ERROR, SQL_INVALID_HANDLE.
function SQLDataSources(
     EnvironmentHandle: SQLHENV;
     Direction: SQLUSMALLINT;
     ServerName: SQLPCHAR;
     BufferLength1: SQLSMALLINT;
     var NameLength1Ptr: SQLSMALLINT;
     Description: SQLPCHAR;
     BufferLength2: SQLSMALLINT;
     var NameLength2Ptr: SQLSMALLINT): SQLRETURN;
     stdcall; external odbc32 name 'SQLDataSources';

implementation

{$R *.dfm}

//-----------------------------------------------------------------------------
//  SQLDrivers() の DriverAttributes を文字列に変換
//  例) FileUsage=1\0FileExtns=*.dbf\0\0 ⇒ FileUsage=1,FileExtns=*.dbf
function BreakList(const ANullTerminateText: array of Char): String;
var
    LStart: Integer;
    LBuffer: array[0..255] of Char;
    LText: String;
begin
    LStart := 0;
    LText := ANullTerminateText;
    Result := LText; 
    Inc(LStart, Length(LText) + 1);
    while (True) do
    begin
        FillChar(LBuffer, SizeOf(LBuffer), 0);
        Move(ANullTerminateText[LStart], LBuffer, SizeOf(LBuffer));
        LText := LBuffer;
        Inc(LStart, Length(LText) + 1);
        if (LText = '') then Break;
        Result := Result + ',' + AnsiQuotedStr(LText, '"');
    end;
end;

//-----------------------------------------------------------------------------
//  ODBCのドライバリストを取得
procedure TForm1.Button1Click(Sender: TObject);
const
    BUF_MAX = 1024;
var
    LEnvironmentHandle: SQLHENV;
    LDriverDescription: array[0..BUF_MAX] of Char;
    LDescriptionLengthPtr: SQLSMALLINT;
    LDriverAttributes: array[0..BUF_MAX] of Char;
    AttributesLengthPtr: SQLSMALLINT;
    LReturn: SQLRETURN;
    LText: String;
begin
    Memo1.Clear();

    try
        //  環境ハンドル設定
        if (SQLAllocEnv(LEnvironmentHandle) = SQL_ERROR) then Exit;

        try
            //  最初のドライバを取得
            FillChar(LDriverDescription, SizeOf(LDriverDescription), 0);
            FillChar(LDriverAttributes, SizeOf(LDriverAttributes), 0);

            LReturn := SQLDrivers(LEnvironmentHandle, SQL_FETCH_FIRST,
                 LDriverDescription, BUF_MAX + 1, LDescriptionLengthPtr,
                 LDriverAttributes, BUF_MAX + 1, AttributesLengthPtr);

            //  以降のドライバを取得
            while (LReturn <> SQL_NO_DATA_FOUND) do
            begin
                //  結果出力
                //LText := String(LDriverDescription) + '/' + String(LDriverAttributes);
                LText := String(LDriverDescription) + '/' + BreakList(LDriverAttributes);
                Memo1.Lines.Add(LText);

                FillChar(LDriverDescription, SizeOf(LDriverDescription), 0);
                FillChar(LDriverAttributes, SizeOf(LDriverAttributes), 0);

                LReturn := SQLDrivers(LEnvironmentHandle, SQL_FETCH_NEXT,
                     LDriverDescription, BUF_MAX + 1, LDescriptionLengthPtr,
                     LDriverAttributes, BUF_MAX + 1, AttributesLengthPtr);
            end;

        finally
            //  環境ハンドル開放
            SQLFreeEnv(LEnvironmentHandle);
        end;
    except
        on E:Exception do Memo1.Lines.Add(E.Message);
    end;
end;

//-----------------------------------------------------------------------------
//  ODBCのデータソースリストを取得
procedure TForm1.Button2Click(Sender: TObject);
const
    BUF_MAX = 1024;
var
    LEnvironmentHandle: SQLHENV;
    LServerName: array[0..SQL_MAX_DSN_LENGTH] of Char;
    LNameLength1Ptr: SQLSMALLINT;
    LDescription: array[0..BUF_MAX] of Char;
    LNameLength2Ptr: SQLSMALLINT;
    LReturn: SQLRETURN;
    LText: String;
begin
    Memo1.Clear();

    try
        //  環境ハンドル設定
        if (SQLAllocEnv(LEnvironmentHandle) = SQL_ERROR) then Exit;

        try
            //  最初のドライバを取得
            FillChar(LServerName, SizeOf(LServerName), 0);
            FillChar(LDescription, SizeOf(LDescription), 0);

            LReturn := SQLDataSources(LEnvironmentHandle, SQL_FETCH_FIRST,
                 LServerName, SQL_MAX_DSN_LENGTH + 1, LNameLength1Ptr,
                 LDescription, BUF_MAX + 1, LNameLength2Ptr);

            //  以降のドライバを取得
            while (LReturn <> SQL_NO_DATA_FOUND) do
            begin
                //  結果出力
                //LText := String(LDriverDescription) + '/' + String(LDriverAttributes);
                LText := String(LServerName) + '/' + BreakList(LDescription);
                Memo1.Lines.Add(LText);

                FillChar(LServerName, SizeOf(LServerName), 0);
                FillChar(LDescription, SizeOf(LDescription), 0);

                LReturn := SQLDataSources(LEnvironmentHandle, SQL_FETCH_NEXT,
                     LServerName, SQL_MAX_DSN_LENGTH + 1, LNameLength1Ptr,
                     LDescription, BUF_MAX + 1, LNameLength2Ptr);
            end;

        finally
            //  環境ハンドル開放
            SQLFreeEnv(LEnvironmentHandle);
        end;
    except
        on E:Exception do Memo1.Lines.Add(E.Message);
    end;
end;

ODBCが時代遅れかどうかさえ知らない時代遅れ者が、時代遅れのソースコードを掲載してネットの検索結果を汚していく...

EOFTOP