2013-07-08 7 views
5

Was ich versuche zu tun, ist außerhalb der Reichweite Bereich außerhalb der unterstützten Bereich zu erhöhen, wie was Typcasting tut.Raise error, wenn das Datum nicht gültig ist

Ich benutze PostgreSQL-9.1.6 auf CentOS. Das Problem ist unten ...

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

Aber der Ausgang ich sehen will, ist:

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

Websurfen I an informative page gefunden. So habe ich IS_VALID_JULIAN an den Funktionskörper von to_date Hinzufügen Hinzufügen der vier Linien markiert + unten an 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); 
} 

Dann habe ich wieder aufgebaut 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 

Mein bin-Verzeichnis Informationen ist unten.

[/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 

Aber auf to_date wieder blieb das Ergebnis das gleiche Prüfung.

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

Gibt es etwas, das ich vermisst habe?

+0

Bei einer Schätzung ist der Server, den Sie ausführen, nicht mit der von Ihnen gestarteten Binärdatei identisch. –

+0

Der Ansatz hat nichts falsch, oder? – KIM

+0

Er ... Wenn Sie den Code patch und kompilieren, müssen Sie die Binärdateien ausführen, die Sie kompiliert haben. Das Ausführen einer anderen nicht verwandten Binärdatei funktioniert nicht. –

Antwort

1

Sie können Ihre eigene to_date() - Funktion schreiben, aber Sie müssen sie mit ihrem schemafähigen Namen aufrufen. (Ich habe das Schema „public“, aber es ist nichts Besonderes darüber.)

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 

die bloßen Funktionsnamen verwenden führt die nativen to_date() Funktion.

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

Die Verwendung des schemaqualifizierten Namens führt die benutzerdefinierte Funktion aus.

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

Ich weiß, das ist nicht ganz das, wonach Sie suchen. Aber . . .

  • Es ist einfacher als PostgreSQL aus der Quelle neu erstellen.
  • Das Reparieren Ihres vorhandenen SQL- und PLPGSQL-Quellcodes ist ein einfaches Suchen und Ersetzen durch einen Streaming-Editor. Ich bin mir ziemlich sicher, dass das nicht schief gehen kann, solange man wirklich will jede Verwendung des nativen to_date() zu public.to_date().
  • Die native Funktion to_date() funktioniert immer noch wie vorgesehen. Erweiterungen und anderer Code könnten sich auf sein etwas eigenartiges Verhalten stützen. Denken Sie gründlich und lange nach, bevor Sie das Verhalten nativer Funktionen ändern.

Neue SQL und PLPGSQL müssten jedoch überprüft werden. Ich würde nicht erwarten, dass Entwickler sich jedes Mal daran erinnern, public.to_date() zu schreiben. Wenn Sie die Versionskontrolle verwenden, können Sie möglicherweise einen Precommit-Hook schreiben, um sicherzustellen, dass nur public.to_date() verwendet wird.

Die native Funktion to_date() hat Verhalten, das ich nicht dokumentiert sehe. Sie können es nicht nur mit dem 29. Februar anrufen, sondern auch mit dem Februar 345 oder dem Februar 9999.

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

select to_date('2013029999', 'yyyymmdd'); 
2040-06-17 
Verwandte Themen