我想要做的是在日期超出支持范围的情况下提高超出范围的错误,例如类型转换.
我在CentOS上使用PostgreSQL-9.1.6.问题如下......
postgres=# select to_date('20130229','yyyymmdd');
to_date
------------
2013-03-01
(1 row)
Run Code Online (Sandbox Code Playgroud)
但我想看到的输出是:
postgres=# select '20130229'::date;
ERROR: date/time field value out of range: "20130229"
Run Code Online (Sandbox Code Playgroud)
浏览网页我找到了一个信息丰富的页面.所以我添加IS_VALID_JULIAN
了函数体to_date
,将+
下面标记的四行添加到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);
}
Run Code Online (Sandbox Code Playgroud)
然后我重建了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
Run Code Online (Sandbox Code Playgroud)
我的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
Run Code Online (Sandbox Code Playgroud)
但经过to_date
再次检查,结果保持不变.
postgres=# select to_date('20130229','yyyymmdd');
to_date
------------
2013-03-01
(1 row)
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?
您可以编写自己的 to_date() 函数,但必须使用其模式限定名称来调用它。(我使用了“public”模式,但没有什么特别的。)
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
Run Code Online (Sandbox Code Playgroud)
使用裸函数名称执行本机 to_date() 函数。
select to_date('20130229', 'yyyymmdd');
2013-03-01
Run Code Online (Sandbox Code Playgroud)
使用模式限定名称执行用户定义的函数。
select public.to_date('20130229', 'yyyymmdd');
ERROR: date/time field value out of range: "20130229"
SQL state: 22008
Run Code Online (Sandbox Code Playgroud)
我知道这不完全是您想要的。但 。。。
不过,新的 SQL 和 PLPGSQL 需要进行审查。我不希望开发人员每次都记得编写 public.to_date() 。如果您使用版本控制,您也许可以编写一个预提交挂钩来确保仅使用 public.to_date() 。
本机 to_date() 函数具有我没有看到记录的行为。你不仅可以用二月 29 号来称呼它,还可以用二月 345 来称呼它,或者二月 9999 来称呼它。
select to_date('201302345', 'yyyymmdd');
2014-01-11
select to_date('2013029999', 'yyyymmdd');
2040-06-17
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1711 次 |
最近记录: |