CodeGym /コース /SQL SELF /PL/pgSQLデバッグ入門

PL/pgSQLデバッグ入門

SQL SELF
レベル 55, レッスン 0
使用可能

さて、例えば君が複雑な関数やプロシージャを作ったとしよう。データベースがめっちゃイケてる動きをしてるのが見えてきた…と思ったら、バン!って感じで、データが変だったり、クエリが遅かったり、上司がイライラし始めたりする。そんな時に登場するのがデバッグだよ。

PL/pgSQLでデバッグする理由はこんな感じ:

  • ロジックのバグを見つけるため。例えば、関数が期待した値を返さない時とか。
  • 変な入力データを調べるため。だって、DBユーザーは時々データだけじゃなくて…なんか全然意味不明なものも入れてくるからね!
  • パフォーマンス問題を直すため。急いで書いたコードは、サハラ砂漠でWi-Fi探してるカメみたいに遅くなることもあるし。

まあ真面目な話、デバッグは単なるバグ探しじゃない。コードをもっと速く、効率的に、読みやすくするための手段なんだ。

PL/pgSQLデバッグの基本アプローチ

PL/pgSQLのデバッグにはいくつかやり方がある。順番に見ていこう。

  1. PostgreSQLの組み込みツールを使う

PostgreSQLには診断用の組み込み機能がいくつかあるよ。ログ出力用のRAISE NOTICEやRAISE EXCEPTION、それからクエリ実行プランを分析するEXPLAIN ANALYZEとか。これらを使えば、関数の中で何が起きてるか分かる。

  1. RAISE NOTICEでログを出す

RAISE NOTICEは、関数内でどんなデータが流れてるか、どこで何かおかしくなったか、変数の値をチェックしたい時の相棒だよ。RAISE EXCEPTIONと違って、関数の実行を止めないのがポイント。例えば、各ステップで変数の中身を出力できる。

DO $$
DECLARE
    counter INT := 0;
BEGIN
    FOR counter IN 1..5 LOOP
        RAISE NOTICE 'カウンターの現在値: %', counter;
    END LOOP;
END $$;

このコードはcounterの値を1から5まで出してくれる。シンプルだけど、デバッグには超便利!

  1. サードパーティーツールを使う

PL/pgSQLのデバッグは、pgAdmin(GUI付き)みたいなツールでもできる。ブレークポイントを置いたり、リアルタイムで変数の値を見たりできるから、ビジュアル派の人にはpgAdminが最高の相棒になるよ。

デバッグのステップ

関数やプロシージャのデバッグを始める時は、ちゃんとした順番でやるのが大事。それぞれのステップを詳しく見てみよう:

  1. 入力データの分析

まず最初にやるべきは、入力データの確認。関数が受け取るデータにミスや予想外の値がないかチェックしよう。例えば、全部の入力パラメータをRAISE NOTICEで出してみる:

CREATE FUNCTION check_input(x INTEGER) RETURNS VOID AS $$
BEGIN
    IF x IS NULL THEN
        RAISE EXCEPTION '入力値はNULLにしちゃダメだよ!';
    END IF;
    RAISE NOTICE '入力値: %', x;
END;
$$ LANGUAGE plpgsql;

この例は、入力データに問題があった時にユーザーに警告するやり方を示してる。

  1. 各ステップの実行チェック

関数をロジックごとに分けて、要所要所でRAISE NOTICEを入れよう。どこで何かおかしくなったか分かりやすくなるよ。

CREATE FUNCTION calculate_discount(price NUMERIC, discount NUMERIC) RETURNS NUMERIC AS $$
BEGIN
    RAISE NOTICE '関数開始: 価格 %, 割引 %', price, discount;

    IF price <= 0 THEN
        RAISE EXCEPTION '価格は0以下にできないよ!';
    END IF;

    IF discount < 0 OR discount > 100 THEN
        RAISE EXCEPTION '割引は0から100の間じゃないとダメ!';
    END IF;

    RETURN price - (price * discount / 100);
END;
$$ LANGUAGE plpgsql;

こんな感じで、各ステップで役立つメッセージを出してデバッグしやすくしてる。

  1. 最適化と問題解決
  2. バグを見つけたら直そう。パフォーマンスの問題なら、EXPLAIN ANALYZEみたいな分析ツールでクエリを最適化しよう。

デバッグスキルの実践

実際の課題を見てみよう。例えば、テーブルにレコードを追加して生成されたIDを返す関数があるとする。一見シンプルだけど、時々エラーで落ちることがある。なんでか知りたいよね。

元の関数:

CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
    new_id INTEGER;
BEGIN
    INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;
    RETURN new_id;
END;
$$ LANGUAGE plpgsql;

この関数を変なデータ、例えばage < 0で呼ぶとエラーになる。デバッグ用の仕掛けを入れて改善しよう。

ログ付きの改善版関数:

CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
    new_id INTEGER;
BEGIN
    -- 入力データをログ出力
    RAISE NOTICE '学生追加: 名前 %, 年齢 %', name, age;

    -- 年齢の正しさをチェック
    IF age < 0 THEN
        RAISE EXCEPTION '年齢はマイナスにできないよ!';
    END IF;

    -- 学生を追加してIDを返す
    INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;

    -- 成功したらログ出力
    RAISE NOTICE '学生がID %で追加されたよ', new_id;

    RETURN new_id;
END;
$$ LANGUAGE plpgsql;

これでエラーが起きた時も、RAISE NOTICEで何が起きたかちゃんと分かるようになる。

最後に役立つアドバイス

  1. 本番コードでは不要なログは消そう。 RAISE NOTICEはデバッグには最高だけど、ずっと使いっぱなしだと本番環境のログがごちゃごちゃになるよ。
  2. 小さいコード単位で作業しよう。 関数が複雑すぎるなら、いくつかに分けて書こう。その方がデバッグしやすい。
  3. 定期的に練習しよう。 コードを書いてデバッグするほど、バグ探しと修正がどんどん速くなるよ。

デバッグは探偵ゲームみたいなもんで、虫眼鏡の代わりにSQLクエリとPL/pgSQLのロジックを使う感じ。経験を積めば積むほど上手くなるし、バグを直すたびにちょっとずつレベルアップできるよ!

2
タスク
SQL SELF, レベル 55, レッスン 0
ロック未解除
RAISE EXCEPTIONとRAISE NOTICEを使った入力データのチェック
RAISE EXCEPTIONとRAISE NOTICEを使った入力データのチェック
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION