簡単なデバッグの例 - Advanced SQL Engine - Teradata Database

Teradata Vantage™ - SQL外部ルーチン プログラミング

Product
Advanced SQL Engine
Teradata Database
Release Number
17.05
17.00
Published
2020年6月
Language
日本語
Last Update
2021-03-30
dita:mapPath
ja-JP/qwr1571437338192.ditamap
dita:ditavalPath
ja-JP/qwr1571437338192.ditaval
dita:id
B035-1147
Product Category
Software
Teradata Vantage

このセクションのトピックでは、2つの整数の合計を計算する単純なスカラーUDFを作成し、保護モードで実行してデバッグする方法について説明します。同じ基本プロセスを使って、デバッガでサポートされるどのような外部ルーチンでもデバッグできます。

システムのセットアップ

実際にUDFをデバッグする前に、セットアップが一部必要です。まず、十分な権限を持つデータベース ユーザーがUDFをデバッグできるように、UDFデバッグを有効にする必要があります。このオプションは、実働システムでの悪用を防ぐために、デフォルトで無効になっています。ctlユーティリティのデバッグ画面のUDFデバッグ オプションを使用すると有効になります。

  1. ターゲット システム上のコマンド シェルからctlを起動して、デバッグ画面に移動します。
    # ctl
    > screen debug
    
    (0) Start DBS:         On            (1) Break Stop:        Off
    (2) Start With Logons: All           (3) Start With Debug:  Off
    (4) Save Dumps:        Off           (5) Snapshot Crash:    Off
    (6) Maximum Dumps:     -1            (7) Start PrgTraces:   Off
    (8) Restart Dump Type: System        (9) UDF Debugging:     Off
  2. UDFデバッグがまだオンになっていない場合は有効にして、ctlを終了します。
    > 9=on
    > quit
    CTL: Write Control GDO Changes? y
    CTL: Control GDO successfully written.
    Warning: A change has been made to one or more fields
             that has a deferred effect.
             TPA reset must be performed so that those changes can
             take effect.
  3. ctlのメッセージにあるように、新しい設定を有効にするには、Teradataを再始動する必要があります。それには、シェル プロンプトでtparesetコマンドを実行します。
    # tpareset –y Enable UDF Debugging

データベース ユーザーの作成

デバッグにはデバッガ ユーザーに特別な権限が付与されていることが必要です。この例では、UDFの作成と実行を行なう権限があるデバッガ ユーザーを作成します。DBSユーザーは誰でもUDFをデバッグできますが、どのユーザーもデバッグするには権限を持つ必要があります。

  1. dbcユーザーとしてbteqにログインします。この例ではターゲット システムのコマンド シェルからログインすることを想定していますが、bteqはTeradataシステムにアクセスできるどのマシンからでも実行できます。

    シェル コマンド プロンプトからbteqにログオンします。

    # bteq .logon localhost/dbc,dbc_password
  2. bteqによってコマンド プロンプトが表示されたら、"debugger"というユーザー名を作成します。
    create user debugger
    as permanent=50e6,
    spool=100e6,
    temporary=50e6,
    password=debugger;
  3. 次のコマンドを実行依頼して、このユーザーに必要な権限を付与します。
    grant create function on debugger to debugger with grant option;
    grant execute function on debugger to debugger with grant option;
  4. ログアウトして終了します。

C UDFソース ファイルの作成

デバッガ ユーザーのセットアップ後、このユーザー アカウントを使って単純なスカラーUDFを作成してデータベースにインストールすることができます。以下に、plusudf.cという名前のソース ファイルの作成に使用できるCソース コードのサンプルを示します。この関数は、2つの整数の合計を計算します。

  1. この例では、plusudf.cファイルを/tmpディレクトリ内に作成します。
    /*
     * plusudf.c
     *
     * Sample UDF for debugging
     */
    
    #define SQL_TEXT Latin_Text
    #include "sqltypes_td.h"
    
    void plusudf(INTEGER *a, INTEGER *b, INTEGER *result, char sqlstate[5])
    {
        *result = *a + *b;
    }

bteqへのログイン

  1. デバッガ ユーザーとしてbteqにログインします。
    # bteq .logon localhost/debugger,debugger

    ログオンしているデータベースにUDFがインストールされます。このユーザー アカウントで作成されたすべてのUDFのコードを含むライブラリに関数が保存されます。この例では、DBSはローカル マシン上で稼働しています。

新しいUDFの作成

  1. CREATE FUNCTIONを使用し、EXTERNAL NAME句に"d"オプションを指定して、Cファイルから"plusudf"という名前の新しいUDFを作成します。
    create function plusudf( 
    a integer, 
    b integer
    ) returns integer
    language c 
    no sql 
    parameter style td_general 
    external name 'd!cs!plusudf!/tmp/plusudf.c';

    UDFがデバッグ記号でコンパイルされるように、"d"オプションを使用する必要があります。UDFを作成または交換する度に、ライブラリが再構築されます。CREATE FUNCTIONの詳細は、<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>を参照してください。

UDFの確認

  1. UDFを実行して、適切に機能するか確認します。
    select plusudf(5,10);

    結果は以下のようになります。

    *** Query completed. One row found. Onlne column returned.
     *** Total elapsed time was 2 seconds.
    
    plusudf(5,10)
     15

デバッグするUDFの実行

UDFを作成して検証したら、デバッグ用に実行できます。

  1. 通常のSQLセッションにログインします。
    # bteq .logon localhost/debugger,debugger
  2. UDF(この例では"plusudf"という名前)を呼び出す、SQLセッションの後続のSQL文がTeradata C/C++ UDF Debuggerで実行されるように要求します。
    set session debug function plusudf on;
  3. plusudfを実行するSQL文を発行します。
    select plusudf(5,10);

    UDFは問合わせの実行を停止し、デバッガがセッションに加わるのを待ちます。問合わせは、デバッガによって関数の続行が許可されるまで完了しません。問合わせによってUDFの複数のインスタンスが実行されると、デバッガによりすべてのUDFの実行が完了するまで、問合わせは完了しません。

UDFをTeradata C/C++ UDF Debuggerセッションに参加させる

デバッガはUDFを要求し、制御します。

  1. ターゲット システムの別のウィンドウでデバッガを起動します。シェル プロンプトからtdgdbまたは/usr/pde/bin/gdbのいずれかを使用します。
    # tdgdb
  2. デバッグ セッションを開始するには、attachコマンドとudfオプション、デバッガ アカウント名とパスワードを使用します。
    (gdb) attach udf localhost/debugger,debugger
    Attaching to UDF server via localhost/debugger,debugger
    UDFサーバーにより、データベースで実行中のUDFをGDBでデバッグすることが可能になります(Teradata C/C++ UDF Debuggerの拡張機能を使用)。
  3. このデバッガ アカウントで結合できる、デバッグを待機中のUDFを表示するには、info udfコマンドを使用します。このコマンドにより、次のような出力が表示されます。
    (gdb) info udf
    Sessno  Name     Type  Language  Count  Joined
      1001  plusudf  UDF   C             1  No
    説明
    • Sessnoはセッション番号です。
    • NameはUDFの名前です。
    • Typeは常にUDFになります。
    • Languageは、関数のソースが記述されたプログラミング言語です。
    • Countは、現在デバッグされているUDFのインスタンスの数です。
    • Joinedは、UDFが実行されているSQLセッションにデバッガが加わったかどうかを示します。
  4. info udfの表示にあるセッション番号を使って、デバッグ セッションと関連付けるUDFを選択します。タイプ:
    join <session number>

    セッション1001については、コマンドによって次のような出力が生成されます。

    (gdb) join 1001
    Reading symbols for task udfsectsk... (libudf.so, 0x7ffff7bb7000)
       (libudf1.so, 0x7ffff79b4000) (libstdc++.so.6, 0x7ffff76a9000)
       (libjil.so, 0x7ffff748b000) (libnetpde.so, 0x7ffff723f000)
       (libpde.so, 0x7ffff6f80000) (libemf.so, 0x7ffff6d72000)
       (libpdesym.so, 0x7ffff6b5b000) (libpthread.so.0, 0x7ffff693e000)
       (libelf.so.1, 0x7ffff672a000) (libnsl.so.1, 0x7ffff6512000)
       (libm.so.6, 0x7ffff62bc000) (libc.so.6, 0x7ffff5f5a000)
       (libdl.so.2, 0x7ffff5d56000) (ld-linux-x86-64.so.2, 0x7ffff7dde000)
       (libgcc_s.so.1, 0x7ffff5b3f000) (libacl.so.1, 0x7ffff5937000)
       (libcrypto.so.0.9.8, 0x7ffff5598000)
       (libthread_db.so.1, 0x7ffff5390000) (libattr.so.1, 0x7ffff518b000) 
    
       (libz.so.1, 0x7ffff4f75000) (libudf_1026_17.so, 0x7ffff355b000)
    Node    Pid     Tid    Type
    16383  7066    7066    C

    Nodeは、UDFが実行されているvproc IDを示します。

UDFのデバッグ

標準GDBコマンドを使用してデバッグを行ない、ブレークポイントの設定、変数の表示、ステップ実行の実施、または実行の続行を行なうことが可能になりました。

  1. dirコマンドを使って、ソース ファイルの場所をTeradata C/C++ UDF Debuggerに伝えます。
    (gdb) dir /tmp
    Source directories searched: /tmp:$cdir:$cwd
    ソース ファイルを使用できない場合、十分な権限を持つユーザーは、BTEQでSHOW FUNCTIONを使ってUDFのCソース コードを表示できます。出力はファイルに保存して、デバッグで使用できます。詳細は、<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>を参照してください。
  2. ファイルの12行目にブレークポイントを設定します。
    (gdb) br plusudf.c:12
    Breakpoint 1 at 0x2aaaac25f714: file plusudf.c, line 12.
    UDFのコードを含んだライブラリがデバッガに表示されたら、UDFが現在実行中かどうかに関係なく、そのライブラリにブレークポイントを設定できます。追加のブレークポイントは、UDFの新しいインスタンスに含まれます(インスタンスの起動時)。
  3. Cと入力して、問合わせをブレークポイントに達するまで実行します。
    (gdb) c
    Continuing.
    Breakpoint 1, plusudf (a=0x2aaaac21e940, b=0x2aaaac21e950,
        result=0x2aaaac21e964, sqlstate=0x2aaaac21e96c "00000") at plusudf.c:12
    12              *result = *a + *b;
  4. 変数の現在の値を出力します。
    (gdb) print *a
    $1 = 5
    (gdb) print *b
    $2 = 10
  5. cと入力して続行します。
    この例では、問合わせがbteqウィンドウで最後まで実行されます。
    gdb) c
    Continuing.

    問合わせの完了時、デバッガを終了するまで、セッションはデバッガが参加したままの状態になります。SQLセッションでBTEQを使って同じリクエストを再発行する場合、UDFがブレークポイントに到達すると、新しいUDFインスタンスがデバッガ ウィンドウに表示されます。

  6. Ctrl+cを押して、実行中のデバッガ コマンドを終了し、GDBコマンド プロンプトに戻ります。次に、quitと入力して、問合わせを最後まで実行し、デバッガを終了します。
    <Ctrl-c>
    Debug Server stopped without any debug processes!
    (gdb) quit
    Ending debugging session.

    デバッグにより、UDFに変更を加える必要があることがわかった場合は、ベスト プラクティスとして、UDFを再コンパイルした後、デバッガを終了してから再起動し、必要なブレークポイントすべてを新しいデバッグ セッションで再確立します。これは、スタンドアロン プログラムをデバッグする場合に実行する手順とほぼ同じです。

    ソース コードのデバッグに使用した同じbteqセッションで、ソース コードを更新し、REPLACE FUNCTION文で再コンパイルできます。ただし、関数を置き換えると、ライブラリが再構築されるため、最初のUDFに設定したブレークポイントはいずれも保持されなくなります。