[pgsql-jp: 26752] Error occurred while executing PL/pgSQL function

electricnude @ geocities.co.jp electricnude @ geocities.co.jp
2002年 7月 18日 (木) 19:41:11 JST


はじめまして。池村と申します。いつもROMさせて頂いておりました。


pl/pgsql関数についてですが、PostgreSQLバージョンアップ後、
動作しない状況に陥りました。
何とか打破したく、皆様のお知恵を拝借させて頂きたく存じます。
長文になりますこと、お許しくださいませ。


サーバ環境:
  Operating System ..... Red Hat Linux release 7.2 (Enigma)
  Architecture ......... Intel Pentium III
  PostgreSQL version ... 7.1.3  ==>>  7.2.1
  Compiler used ........ 2.96
     PostgreSQLは、Ver7.1.3、Ver7.2.1いずれも、
     tarballからのインストールです。


問題の関数は、3つからなるものなのですが、
書き方に問題があるのか、ハタマタ別の問題なのか、
私なりに調べたのですが、原因を突き止められずにおります。

最下段にその関数群を記します。
(各関数群の先頭4文字の空白は、説明用にインデントしたものです。)
3番目の関数[ arwz_ext_down2day ]を動作させると、以下のような現象が起きます。

=== お題 ==> 今日の(月の)、第3日曜日の日付を求めたい。
a) Ver7.1.3の場合
    # SELECT arwz_ext_down2day( date( now() ) , '3:sun' ) ;
       arwz_ext_down2day
    ------------------------
     2002-07-21 00:00:00+09
    (1 row)
   >>> 正常に意図したreturn値が取得できる。

b) Ver7.2.1の場合
    # SELECT arwz_ext_down2day( date( now() ) , '3:sun' ) ;
    NOTICE:  Error occurred while executing PL/pgSQL function arwz_ext_down2day
    NOTICE:  line 25 at assignment
    ERROR:  parser: parse error at or near "("
   >>> 正常に動作せず。文法エラーとも言われる・・・


Googleで、[ Error occurred while executing PL/pgSQL function  ]をサーチすると、
こんなのが出ましたが、状況は異なる様に思えるのですが・・・
cf: [ http://archives.postgresql.org/pgsql-bugs/2002-05/msg00160.php ]

やはり、私が記述した関数の書式がイイカゲンなのでしょうか?
どなたかご存知の方、よろしくご教授ください。お願いいたします。
あぁぁ、英語力も無い私に 愛 を く だ さ い 。




                   >>>>> 以下、問題の関数群 <<<<<

1. 該当月の最終日を算出する(つもりの)関数
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    CREATE OR REPLACE FUNCTION arwz_rtn_enddayofmonth( TIMESTAMP )
    RETURNS INT4 AS '
    DECLARE
        my_input_date TIMESTAMP ;
        my_temp_value VARCHAR ;
        my_down_separator_pos INT4 ;
        my_value_year INT4 ;
        my_value_month INT4 ;
        my_return_value INT4 ;
    BEGIN
        my_input_date := $1 ;
        
        my_temp_value := to_char( my_input_date , ''YYYY-MM'' ) ;
        my_down_separator_pos = strpos( my_temp_value , ''-'' ) ;
        
        my_value_year := ( substr( my_temp_value , 1 , ( my_down_separator_pos - 1 ) ) )::INT4 ;
        my_value_month := ( substr( my_temp_value , ( my_down_separator_pos + 1 ) ) )::INT4 ;
        
        IF my_value_month = 2 THEN
            IF ( my_value_year % 400 ) = 0 THEN
                my_return_value := 29 ;
            ELSE
                IF ( my_value_year % 100 ) = 0 THEN
                    my_return_value := 28 ;
                ELSE
                    IF ( my_value_year % 4 ) = 0 THEN
                        my_return_value := 29 ;
                    ELSE
                        my_return_value := 28 ;
                    END IF ;
                END IF ;
            END IF ;
        ELSE
            my_return_value := CASE my_value_month
                WHEN 1  THEN 31
                WHEN 3  THEN 31
                WHEN 4  THEN 30
                WHEN 5  THEN 31
                WHEN 6  THEN 30
                WHEN 7  THEN 31
                WHEN 8  THEN 31
                WHEN 9  THEN 30
                WHEN 10 THEN 31
                WHEN 11 THEN 30
                WHEN 12 THEN 31
            END ;
        END IF ;
        
        RETURN my_return_value ;
    END ;'
    LANGUAGE 'plpgsql' ;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<




2. 曜日 <--> 数値変換(のつもりの)関数
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    CREATE OR REPLACE FUNCTION arwz_exp_dow2num( VARCHAR )
    -- return ... input
    --      1 ... sun
    --      2 ... mon
    --      3 ... tue
    --      4 ... wed
    --      5 ... thu
    --      6 ... fri
    --      7 ... sat
    --      0 ... n/a
    --
    RETURNS INT4 AS '
    DECLARE
    	my_input_value ALIAS FOR $1 ;
    	my_short_dow VARCHAR ;
    	my_return_value INT4 ;
    BEGIN
    	my_short_dow := LOWER( SUBSTRING( my_input_value FROM 1 FOR 3 ) ) ;
    	my_return_value := CASE my_short_dow
    		WHEN  ''sun'' THEN 1
    		WHEN  ''mon'' THEN 2
    		WHEN  ''tue'' THEN 3
    		WHEN  ''wed'' THEN 4
    		WHEN  ''thu'' THEN 5
    		WHEN  ''fri'' THEN 6
    		WHEN  ''sat'' THEN 7
    		ELSE 0
    	END ;
    
    	RETURN my_return_value ;
    END ;'
    LANGUAGE 'plpgsql' ;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<




3. 外当月の第n m曜日を算出する(つもりの)関数
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    CREATE OR REPLACE FUNCTION arwz_ext_down2day( TIMESTAMP , VARCHAR )
    -- ----------------------------------------------------------------------------------
    -- ----------------------------------------------------------------------------------
    -- NAME: 
    --        down : Day Of the Week ( and week Number )
    -- 
    -- SYNOPSIS
    --        this.function( '2002-02-02' , '3:sun' )
    -- 
    -- DESCRIPTION
    --        this.function( timestamp , varchar )
    --          $1 : timestamp ... target date( which use only year and month ).
    --          $2 : varchar ..... certain format as [ weeknumber each month + separator < : > + <the day of the week> ]
    --               examples::'3:sun' <<== it means 3rd sunday of the weeks in that month.
    -- 
    -- AUTHOR NOTE
    --        -----
    --        -----
    -- 
    -- ----------------------------------------------------------------------------------
    -- ----------------------------------------------------------------------------------
    RETURNS TIMESTAMP AS '
    DECLARE
        my_input_date TIMESTAMP ;
        my_input_down VARCHAR ;
        my_return_value TIMESTAMP ;
        
        my_date_bad_request TIMESTAMP ;
        my_date_diff_day INT4 ;
        my_date_bom TIMESTAMP ; -- Beginning Of Month
        my_date_diff_dow INT4 ;
        
        my_down_separator_pos INT4 ;
        my_down_week INT4 ;
        my_down_dow VARCHAR ;
        
        my_temp_timestamp TIMESTAMP ;
        my_temp_varchar VARCHAR ;
        my_temp_intger INT4 ;
        
        
    --  ret TIMESTAMP ;
    BEGIN
    -- ----------------------------------------------------------------------------------
    -- -- SET::initialize parameters value
        my_input_date := $1 ;
        my_input_down := trim( $2 ) ;
        
        
    -- ----------------------------------------------------------------------------------
    -- -- CHK::input values
        IF ISFINITE( my_input_date ) = ''false''
        THEN
            RAISE EXCEPTION ''Invalid Argument $1[ % ] >> unjust timestamp'' , $1 ;
        END IF ;
        
    --  IF my_input_down !~ ''^[1-5]\:[A-Za-z]\{3\}$''
        IF my_input_down !~ ''^[0-9]*\:[A-Za-z]*$''
        THEN
            RAISE EXCEPTION ''Invalid Argument $2[ % ] SYNOPSIS::''''3:sun'''''' , $2 ;
        END IF ;
        
        
    -- ----------------------------------------------------------------------------------
    -- -- ALYZ::date
        my_temp_varchar := to_char( timestamp ( ( my_input_date )::varchar ) , ''YYYY-MM-DD'' ) ;
        my_temp_timestamp := to_timestamp( my_temp_varchar , ''YYYY-MM-DD'' ) ;
        
        my_date_diff_day := ( EXTRACT( DAY FROM my_temp_timestamp ) - 1 )::INT4 ;
        my_date_bom := DATE( my_temp_timestamp ) - my_date_diff_day ;
        my_date_diff_dow := arwz_exp_dow2num( to_char( my_date_bom , ''dy'' ) ) ;
        
        
    -- ----------------------------------------------------------------------------------
    -- -- ALYZ::down
        my_down_separator_pos = strpos( my_input_down , '':'' ) ;
        my_down_week := ( substr( my_input_down , 1 , ( my_down_separator_pos - 1 ) ) )::INT4 - 1 ;
        my_down_dow := substr( my_input_down , ( my_down_separator_pos + 1 ) ) ;
        
        my_temp_intger := arwz_exp_dow2num( my_down_dow ) ;
        IF my_temp_intger = 0
        THEN
            RAISE EXCEPTION ''Invalid Argument $2[ % ] >> no exist day of the week like ''''%'''''' , $2 , my_down_dow ;
        END IF ;
        
        my_temp_intger := 1 + my_temp_intger - my_date_diff_dow ;
        IF my_temp_intger <= 0
        THEN
            my_temp_intger := my_temp_intger + 7 ;
        END IF ;
        
        my_temp_intger := my_temp_intger + my_down_week * 7 ;
        IF my_temp_intger > arwz_rtn_enddayofmonth( my_temp_timestamp ) THEN
            RAISE EXCEPTION ''Invalid Argument $2[ % ] >> no exist day in the month such as day of the week'' , $2 ;
        END IF ;
        
        RETURN to_timestamp( ( substr( my_temp_varchar , 1 , 8 ) || ( my_temp_intger )::VARCHAR || substr( my_temp_varchar , 11 ) )   , ''YYYY-MM-DD'' ) ;
    END ;'
    LANGUAGE 'plpgsql' ;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

EOM



pgsql-jp メーリングリストの案内