5

私がやろうとしているのは、型キャストのように、サポートされている範囲外の日付の場合に範囲外エラーを発生させることです。

CentOS で PostgreSQL-9.1.6 を使用しています。問題は以下...

postgres=# select to_date('20130229','yyyymmdd');
  to_date   
------------
 2013-03-01
(1 row)

しかし、私が見たい出力は次のとおりです。

postgres=# select '20130229'::date;
ERROR:  date/time field value out of range: "20130229"

ウェブをサーフィンしていると、有益なページが見つかりました。だから私はIS_VALID_JULIANの関数本体に追加し、以下にto_dateマークされた4行をformatting.cに追加しました:+

Datum
to_date(PG_FUNCTION_ARGS)
{
    text       *date_txt = PG_GETARG_TEXT_P(0);
    text       *fmt = PG_GETARG_TEXT_P(1);
    DateADT         result;
    struct pg_tm tm;
    fsec_t          fsec;

    do_to_timestamp(date_txt, fmt, &tm, &fsec);

+       if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
+       ereport(ERROR,
+               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                errmsg("date out of range: \"%s\"",text_to_cstring(date_txt))));

   result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;

   PG_RETURN_DATEADT(result);
}

次に、PostgreSQL を再構築しました。

pg_ctl -m fast stop                       # 1. stopping pgsql
vi src/backend/utils/adt/formatting.c     # 2. using the version above
rm -rf /usr/local/pgsql/*                 # 3. getting rid of all bin files
./configure --prefix=/usr/local/pgsql 
  --enable-nls --with-perl --with-libxml
  --with-pam --with-openssl
make && make install                      # 4. rebuilding source    
pg_ctl start                              # 5. starting the engine

私のbinディレクトリ情報は以下です。

[/home/postgres]echo $PATH
/usr/lib64/qt-3.3/bin:
/usr/local/bin:
/bin:
/usr/bin:
/usr/local/sbin:
/usr/sbin:
/sbin:
/home/postgres/bin:
/usr/bin:
/usr/local/pgsql/bin:
/usr/local/pgpool/bin:
/usr/local/pgtop/bin/pg_top:

[/home/postgres]which pg_ctl
/usr/local/pgsql/bin/pg_ctl

[/home/postgres]which postgres
/usr/local/pgsql/bin/postgres

[/usr/local/bin]which psql
/usr/local/pgsql/bin/psql

しかし、to_date再度確認しても結果は同じでした。

postgres=# select to_date('20130229','yyyymmdd');
  to_date   
------------
 2013-03-01
(1 row)

見逃したものはありますか?

4

1 に答える 1

2

独自の to_date() 関数を作成できますが、スキーマ修飾名で呼び出す必要があります。(スキーマ「パブリック」を使用しましたが、それについて特別なことは何もありません。)

create or replace function public.to_date(any_date text, format_string text)
returns date as
$$
select to_date((any_date::date)::text, format_string);
$$
language sql

そのままの関数名を使用すると、ネイティブの to_date() 関数が実行されます。

select to_date('20130229', 'yyyymmdd');
2013-03-01

スキーマ修飾名を使用すると、ユーザー定義関数が実行されます。

select public.to_date('20130229', 'yyyymmdd');
ERROR: date/time field value out of range: "20130229"
SQL state: 22008

私はそれがあなたが探しているものではないことを知っています. しかし 。. .

  • PostgreSQL をソースから再構築するよりも簡単です。
  • 既存の SQL および PLPGSQL ソース コードの修正は、ストリーミング エディターを使用した単純な検索と置換です。ネイティブの to_date() のすべての使用を public.to_date() にしたい限り、間違いはないと確信しています。
  • ネイティブの to_date() 関数は引き続き設計どおりに機能します。拡張機能やその他のコードは、そのやや特殊な動作に依存している可能性があります。ネイティブ関数の動作を変更する前に、よく考えてください。

ただし、新しい SQL と PLPGSQL を確認する必要があります。開発者が毎回 public.to_date() を書くことを覚えているとは思いません。バージョン管理を使用している場合は、precommit フックを記述して public.to_date() のみが使用されるようにすることができます。

ネイティブの to_date() 関数には、文書化されていない動作があります。2月29日だけでなく、2月345日、2月9999日でもコールできます。

select to_date('201302345', 'yyyymmdd');
2014-01-11

select to_date('2013029999', 'yyyymmdd');
2040-06-17
于 2013-08-11T01:13:02.253 に答える