2016-08-09 2 views
-1

PostgreSQL 9.5の使用。ここで plpgsql関数のOUTパラメータは関数内でNULLですが、ユニットテスト時に表示されます

はjob_parameters()から、問題のコードです:

 SELECT 
      j.controller_id 
      , j.model_id 
      , (
       SELECT cp.parameters 
       FROM commit_schema.controller_parameters cp 
       WHERE cp.parameters_id = j.controller_parameters_id 
       AND cp.controller_id = j.controller_id 
      ) AS _ctrl_par 
      , (
       SELECT mp.parameters 
       FROM commit_schema.model_parameters mp 
       WHERE mp.parameters_id = j.model_parameters_id 
       AND mp.model_id = j.model_id 
      ) AS _mod_par 
      , j.initial_glucose_id 
     INTO 
      controller_id 
      , model_id 
      , controller_parameters 
      , model_parameters 
      , initial_glucose_id 
     FROM 
       commit_schema.job j 
--   INNER JOIN 
--     commit_schema.model_parameters mp 
--     ON j.model_parameters_id = mp.parameters_id 
--   INNER JOIN 
--     commit_schema.controller_parameters cp 
--     ON j.controller_parameters_id = cp.parameters_id 
     WHERE j.sim_id = sim_id; 

別のウィンドウで(最後のWHERE句で使用される)は、固定sim_idでこのクエリを実行している、私はすべての行を取得するI返されることを期待する。 SELECT INTOは、この照会の結果をこのplpgsql関数のパラメーターOUTに直接移動しますが、この関数を実行すると、sim_id以外のすべての列はNULLです。これはファンクションで先にsim_idが選択されているためです。

最初は、内部結合のために使用していたキーが原因で、行にNULLが表示されるため、サブクエリを選択しました。これは、このクエリを単独で実行するときに機能しますが、残りの関数に統合すると失敗します。

RAISE NOTICE '%'の後ろに個別のパラメータを使用してトラブルシューティングを試みましたが、コンソールには印刷されません。

関連するすべての機能の完全なコードはここにある:

DROP DOMAIN IF EXISTS computer_name CASCADE; 
CREATE DOMAIN computer_name AS varchar(50); 

DROP TYPE IF EXISTS error_cluster CASCADE; 
CREATE TYPE error_cluster AS (
    error_code integer 
    , error_msg varchar(100) 
); 

DROP FUNCTION IF EXISTS select_client_id(computer_name); 
CREATE FUNCTION select_client_id (
    IN clean_name computer_name DEFAULT 'none' 
    , OUT client_id integer 
    ) 
    AS $$ 
    BEGIN 
     SELECT c.client_id INTO client_id 
     FROM commit_schema.client c 
     WHERE c.client_name = $1 
     LIMIT 1; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS get_client_id(computer_name, error_cluster); 
CREATE FUNCTION get_client_id (
    IN clean_name computer_name DEFAULT 'none' 
    , IN error_in error_cluster DEFAULT (0,'') 
    , OUT _client_id integer 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     SELECT client_id INTO _client_id 
     FROM select_client_id(clean_name); 
     IF _client_id IS NULL THEN 
      INSERT INTO commit_schema.client (client_name) VALUES (clean_name); 
      SELECT client_id INTO _client_id 
      FROM select_client_id(clean_name); 
     END IF; 
     IF _client_id IS NULL THEN 
      SELECT 
       -10000 
       , 'No Client ID found after Client Name insert.' 
      INTO 
       error_out.error_code 
       , error_out.error_msg; 
     ELSE 
      SELECT 
       error_in.error_code 
       , error_in.error_msg 
      INTO 
       error_out.error_code 
       , error_out.error_msg; 
     END IF; 
    END; 
    $$ LANGUAGE plpgsql; 

/* 
    Get a simulation ID 
*/ 

DROP FUNCTION IF EXISTS get_sim_id(error_cluster); 
CREATE FUNCTION get_sim_id(
    IN error_in error_cluster 
    , OUT _sim_id integer 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     -- SELECT 
--    MIN(j.sim_id) 
--   INTO 
--    _sim_id 
--   FROM commit_schema.job j 
--   WHERE j.job_status_id = 0; 
     UPDATE commit_schema.job j 
     SET job_status_id = 1 
     FROM (
       SELECT sim_id 
       FROM commit_schema.job 
       WHERE job_status_id = 0 
       ORDER BY sim_id 
       LIMIT 1 
       FOR UPDATE SKIP LOCKED 
     ) sub 
     WHERE j.sim_id = sub.sim_id 
     RETURNING j.sim_id INTO _sim_id; 
     IF NOT FOUND THEN 
      SELECT 
       -10000 
       , 'No more jobs left to run!' 
       , -1 
      INTO 
       error_out.error_code 
       , error_out.error_msg 
       , _sim_id; 
     ELSE 
      SELECT 
       error_in.error_code 
       , error_in.error_msg 
      INTO 
       error_out.error_code 
       , error_out.error_msg; 
     END IF; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS set_job_status(integer, smallint, error_cluster); 
CREATE FUNCTION set_job_status(
    IN sim_id integer 
    , IN status smallint 
    , IN error_in error_cluster 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     UPDATE commit_schema.job j 
     SET j.job_status_id = $2 
     WHERE j.sim_id = $1; 
     IF NOT FOUND THEN 
      SELECT 
       -10000 
       , 'No job with sim_id='||$1 
      INTO 
       error_out.error_code 
       , error_out.error_msg; 
     ELSE 
      SELECT 
       error_in.error_code 
       , error_in.error_msg 
      INTO 
       error_out.error_code 
       , error_out.error_msg; 
     END IF; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS set_job_status_to_pending(integer, error_cluster); 
CREATE FUNCTION set_job_status_to_pending(
    IN sim_id integer 
    , IN error_in error_cluster 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     SELECT 
      sj.error_out.error_code 
      , sj.error_out.error_msg 
     INTO 
      error_out.error_code 
      , error_out.error_msg 
     FROM set_job_status($1, 1, error_in.*) sj; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS set_job_status_to_running(integer, error_cluster); 
CREATE FUNCTION set_job_status_to_running(
    IN sim_id integer 
    , IN error_in error_cluster 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     SELECT 
      sj.error_out.error_code 
      , sj.error_out.error_msg 
     INTO 
      error_out.error_code 
      , error_out.error_msg 
     FROM set_job_status($1, 2, error_in.*) sj; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS reset_job_status(integer, error_cluster); 
CREATE FUNCTION reset_job_status(
    IN sim_id integer 
    , IN error_in error_cluster 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     SELECT 
      sj.error_out.error_code 
      , sj.error_out.error_msg 
     INTO 
      error_out.error_code 
      , error_out.error_msg 
     FROM set_job_status($1, 0, error_in.*) sj; 
    END; 
    $$ LANGUAGE plpgsql; 

DROP FUNCTION IF EXISTS job_parameters(computer_name); 
CREATE FUNCTION job_parameters (
    IN computer_id computer_name DEFAULT 'none' 
    , OUT controller_id integer 
    , OUT sim_id integer 
    , OUT controller_parameters integer ARRAY 
    , OUT model_id integer 
    , OUT model_parameters integer ARRAY 
    , OUT initial_glucose_id integer 
    , OUT final_error_code integer 
    , OUT final_error_msg varchar(100)) 
    AS $$ 
    DECLARE 
     -- get rid of garbage in the name we receive 
     clean_name computer_name := lower(regexp_replace(computer_id, '\W+', '', 'g')); 
     current_error error_cluster; 
     error_out error_cluster; 
    BEGIN 
     SELECT 
      0 
      , '' 
     INTO 
      current_error.error_code 
      , current_error.error_msg; 
     -- -- See if the incoming client already has a client_id 
     -- -- If it does, use that. Else give it a new one. 
     SELECT 
      error_out.error_msg 
      , error_out.error_code 
     INTO 
      current_error.error_msg 
      , current_error.error_code 
     FROM get_client_id(clean_name, current_error.*); 

     -- Get a simulation ID 
     SELECT 
      _sim_id 
      , error_out.error_msg 
      , error_out.error_code 
     INTO 
      sim_id 
      , current_error.error_msg 
      , current_error.error_code 
     FROM get_sim_id(current_error.*); 

     IF current_error <> (0,'') THEN 
      SELECT 
       current_error.error_code 
       , current_error.error_msg 
      INTO 
       final_error_code 
       , final_error_msg; 
      RETURN; 
     END IF; 

--   -- Set the job to pending 
--   SELECT 
--    error_out.error_code 
--    , error_out.error_msg 
--   INTO 
--    current_error.error_code 
--    , current_error.error_msg 
--   FROM set_job_status_to_pending(sim_id, current_error.*); 

--   IF current_error <> (0,'') THEN 
--    SELECT 
--     current_error.error_code 
--     , current_error.error_msg 
--    INTO 
--     final_error_code 
--     , final_error_msg; 
--    RETURN; 
--   END IF; 

     -- Get the parameters 
     SELECT 
      j.controller_id 
      , j.model_id 
      , (
       SELECT cp.parameters 
       FROM commit_schema.controller_parameters cp 
       WHERE cp.parameters_id = j.controller_parameters_id 
       AND cp.controller_id = j.controller_id 
      ) AS _ctrl_par 
      , (
       SELECT mp.parameters 
       FROM commit_schema.model_parameters mp 
       WHERE mp.parameters_id = j.model_parameters_id 
       AND mp.model_id = j.model_id 
      ) AS _mod_par 
      , j.initial_glucose_id 
     INTO 
      controller_id 
      , model_id 
      , controller_parameters 
      , model_parameters 
      , initial_glucose_id 
     FROM 
       commit_schema.job j 
--   INNER JOIN 
--     commit_schema.model_parameters mp 
--     ON j.model_parameters_id = mp.parameters_id 
--   INNER JOIN 
--     commit_schema.controller_parameters cp 
--     ON j.controller_parameters_id = cp.parameters_id 
     WHERE j.sim_id = sim_id; 
     RAISE NOTICE 'mp: % cp: % simid: %', model_parameters, controller_parameters, sim_id; 

     IF NOT FOUND THEN 
      SELECT 
       current_error.error_msg || 'No row found for sim_id ' || sim_id ||'. ' 
       , -10000 
      INTO 
       final_error_msg 
       , final_error_code; 
      RETURN; 
     END IF; 

     IF controller_id IS NULL THEN 
      SELECT 
       current_error.error_msg || 'No Controller ID found for this sim_id. ' 
       , -10000 
      INTO 
       current_error.error_msg 
       , current_error.error_code; 
     END IF; 

     IF model_id IS NULL THEN 
      SELECT 
       current_error.error_msg || 'No Model ID found for this sim_id. ' 
       , -10000 
      INTO 
       current_error.error_msg 
       , current_error.error_code; 
     END IF; 

     IF controller_parameters IS NULL THEN 
      SELECT 
       current_error.error_msg || 'No Controller Parameters found for this sim_id. ' 
       , -10000 
      INTO 
       current_error.error_msg 
       , current_error.error_code; 
     END IF; 

     IF model_parameters IS NULL THEN 
      SELECT 
       current_error.error_msg || 'No Model Parameters found for this sim_id. ' 
       , -10000 
      INTO 
       current_error.error_msg 
       , current_error.error_code; 
     END IF; 

     IF current_error = (0,'') THEN 
     -- If everything went well, set job to running 
      SELECT 
       error_out.error_code 
       , error_out.error_msg 
      INTO 
       current_error.error_code 
       , current_error.error_msg 
      FROM set_job_status_to_running(sim_id, current_error.*); 
     ELSE 
     -- Otherwise we reset the simid 
      SELECT 
       error_out.error_code 
      INTO current_error 
      FROM reset_job_status(sim_id, current_error.*); 
     END IF; 

     SELECT 
      current_error.error_msg 
      , current_error.error_code 
     INTO 
      final_error_msg 
      , final_error_code; 

    END; 
    $$ LANGUAGE plpgsql; 
+0

誰もが問題と解決策が何であるかを正しく理解するためには、関数全体を実際に投稿する必要があります。 – Patrick

+0

完全な関数作成スクリプトでOPを更新しました。警告:それほど美しいものではありません。 – ijustlovemath

+0

質問に多すぎる(無関係かもしれない)コードがあります。 SOはコードレビューではなく、Q/Aサイトです。 –

答えて

1

機能set_job_status(...)に構文エラーがあります:

CREATE FUNCTION set_job_status(
    IN sim_id integer 
    , IN status smallint 
    , IN error_in error_cluster 
    , OUT error_out error_cluster) 
    AS $$ 
    BEGIN 
     UPDATE commit_schema.job j 
     SET j.job_status_id = $2 -- invalid!! 
     WHERE j.sim_id = $1; 

あなたはUPDATESET句でカラム名をテーブル修飾することができません。次のいずれかである必要があります。

 SET job_status_id = $2 

わかりましたか?

関連する問題