このセクションのトピックでは、2つの整数の合計を計算する単純なスカラーUDFを作成し、保護モードで実行してデバッグする方法について説明します。同じ基本プロセスを使って、デバッガでサポートされるどのような外部ルーチンでもデバッグできます。
システムのセットアップ
実際にUDFをデバッグする前に、セットアップが一部必要です。まず、十分な権限を持つデータベース ユーザーがUDFをデバッグできるように、UDFデバッグを有効にする必要があります。このオプションは、実働システムでの悪用を防ぐために、デフォルトで無効になっています。ctlユーティリティのデバッグ画面のUDFデバッグ オプションを使用すると有効になります。
- ターゲット システム上のコマンド シェルから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
- 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.
- ctlのメッセージにあるように、新しい設定を有効にするには、Teradataを再始動する必要があります。それには、シェル プロンプトでtparesetコマンドを実行します。
# tpareset –y Enable UDF Debugging
データベース ユーザーの作成
デバッグにはデバッガ ユーザーに特別な権限が付与されていることが必要です。この例では、UDFの作成と実行を行なう権限があるデバッガ ユーザーを作成します。DBSユーザーは誰でもUDFをデバッグできますが、どのユーザーもデバッグするには権限を持つ必要があります。
- dbcユーザーとしてbteqにログインします。この例ではターゲット システムのコマンド シェルからログインすることを想定していますが、bteqはTeradataシステムにアクセスできるどのマシンからでも実行できます。
シェル コマンド プロンプトからbteqにログオンします。
# bteq .logon localhost/dbc,dbc_password
- bteqによってコマンド プロンプトが表示されたら、"debugger"というユーザー名を作成します。
create user debugger as permanent=50e6, spool=100e6, temporary=50e6, password=debugger;
- 次のコマンドを実行依頼して、このユーザーに必要な権限を付与します。
grant create function on debugger to debugger with grant option; grant execute function on debugger to debugger with grant option;
- ログアウトして終了します。
C UDFソース ファイルの作成
デバッガ ユーザーのセットアップ後、このユーザー アカウントを使って単純なスカラーUDFを作成してデータベースにインストールすることができます。以下に、plusudf.cという名前のソース ファイルの作成に使用できるCソース コードのサンプルを示します。この関数は、2つの整数の合計を計算します。
- この例では、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へのログイン
- デバッガ ユーザーとしてbteqにログインします。
# bteq .logon localhost/debugger,debugger
ログオンしているデータベースにUDFがインストールされます。このユーザー アカウントで作成されたすべてのUDFのコードを含むライブラリに関数が保存されます。この例では、DBSはローカル マシン上で稼働しています。
新しいUDFの作成
- 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の確認
- 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を作成して検証したら、デバッグ用に実行できます。
- 通常のSQLセッションにログインします。
# bteq .logon localhost/debugger,debugger
- UDF(この例では"plusudf"という名前)を呼び出す、SQLセッションの後続のSQL文がTeradata C/C++ UDF Debuggerで実行されるように要求します。
set session debug function plusudf on;
- plusudfを実行するSQL文を発行します。
select plusudf(5,10);
UDFは問合わせの実行を停止し、デバッガがセッションに加わるのを待ちます。問合わせは、デバッガによって関数の続行が許可されるまで完了しません。問合わせによってUDFの複数のインスタンスが実行されると、デバッガによりすべてのUDFの実行が完了するまで、問合わせは完了しません。
UDFをTeradata C/C++ UDF Debuggerセッションに参加させる
デバッガはUDFを要求し、制御します。
- ターゲット システムの別のウィンドウでデバッガを起動します。シェル プロンプトからtdgdbまたは/usr/pde/bin/gdbのいずれかを使用します。
# tdgdb
- デバッグ セッションを開始するには、attachコマンドとudfオプション、デバッガ アカウント名とパスワードを使用します。
(gdb) attach udf localhost/debugger,debugger Attaching to UDF server via localhost/debugger,debugger
UDFサーバーにより、データベースで実行中のUDFをGDBでデバッグすることが可能になります(Teradata C/C++ UDF Debuggerの拡張機能を使用)。 - このデバッガ アカウントで結合できる、デバッグを待機中の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セッションにデバッガが加わったかどうかを示します。
- 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コマンドを使用してデバッグを行ない、ブレークポイントの設定、変数の表示、ステップ実行の実施、または実行の続行を行なうことが可能になりました。
- 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>を参照してください。 - ファイルの12行目にブレークポイントを設定します。
(gdb) br plusudf.c:12 Breakpoint 1 at 0x2aaaac25f714: file plusudf.c, line 12.
UDFのコードを含んだライブラリがデバッガに表示されたら、UDFが現在実行中かどうかに関係なく、そのライブラリにブレークポイントを設定できます。追加のブレークポイントは、UDFの新しいインスタンスに含まれます(インスタンスの起動時)。 - Cと入力して、問合わせをブレークポイントに達するまで実行します。
(gdb) c Continuing. Breakpoint 1, plusudf (a=0x2aaaac21e940, b=0x2aaaac21e950, result=0x2aaaac21e964, sqlstate=0x2aaaac21e96c "00000") at plusudf.c:12 12 *result = *a + *b;
- 変数の現在の値を出力します。
(gdb) print *a $1 = 5 (gdb) print *b $2 = 10
- cと入力して続行します。この例では、問合わせがbteqウィンドウで最後まで実行されます。
gdb) c Continuing.
問合わせの完了時、デバッガを終了するまで、セッションはデバッガが参加したままの状態になります。SQLセッションでBTEQを使って同じリクエストを再発行する場合、UDFがブレークポイントに到達すると、新しいUDFインスタンスがデバッガ ウィンドウに表示されます。
- Ctrl+cを押して、実行中のデバッガ コマンドを終了し、GDBコマンド プロンプトに戻ります。次に、quitと入力して、問合わせを最後まで実行し、デバッガを終了します。
<Ctrl-c> Debug Server stopped without any debug processes! (gdb) quit Ending debugging session.
デバッグにより、UDFに変更を加える必要があることがわかった場合は、ベスト プラクティスとして、UDFを再コンパイルした後、デバッガを終了してから再起動し、必要なブレークポイントすべてを新しいデバッグ セッションで再確立します。これは、スタンドアロン プログラムをデバッグする場合に実行する手順とほぼ同じです。
ソース コードのデバッグに使用した同じbteqセッションで、ソース コードを更新し、REPLACE FUNCTION文で再コンパイルできます。ただし、関数を置き換えると、ライブラリが再構築されるため、最初のUDFに設定したブレークポイントはいずれも保持されなくなります。