1
1
/* -----------------------------------------------------------------------
2
2
* formatting.c
3
3
*
4
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.100 2005/10/15 02:49:28 momjian Exp $
4
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.101 2005/10/20 15:59:46 tgl Exp $
5
5
*
6
6
*
7
7
* Portions Copyright (c) 1999-2005, PostgreSQL Global Development Group
@@ -2724,15 +2724,12 @@ static text *
2724
2724
datetime_to_char_body (TmToChar * tmtc ,text * fmt ,bool is_interval )
2725
2725
{
2726
2726
FormatNode * format ;
2727
- struct pg_tm * tm = NULL ;
2728
2727
char * fmt_str ,
2729
2728
* result ;
2730
2729
bool incache ;
2731
2730
int fmt_len = VARSIZE (fmt )- VARHDRSZ ;
2732
-
2733
- tm = tmtcTm (tmtc );
2734
- tm -> tm_wday = (date2j (tm -> tm_year ,tm -> tm_mon ,tm -> tm_mday )+ 1 ) %7 ;
2735
- tm -> tm_yday = date2j (tm -> tm_year ,tm -> tm_mon ,tm -> tm_mday )- date2j (tm -> tm_year ,1 ,1 )+ 1 ;
2731
+ int reslen ;
2732
+ text * res ;
2736
2733
2737
2734
/*
2738
2735
* Convert fmt to C string
@@ -2742,9 +2739,10 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
2742
2739
* (fmt_str + fmt_len )= '\0' ;
2743
2740
2744
2741
/*
2745
- * Allocate result
2742
+ * Allocateworkspace for result as C string
2746
2743
*/
2747
2744
result = palloc ((fmt_len * DCH_MAX_ITEM_SIZ )+ 1 );
2745
+ * result = '\0' ;
2748
2746
2749
2747
/*
2750
2748
* Allocate new memory if format picture is bigger than static cache and
@@ -2790,33 +2788,22 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval)
2790
2788
format = ent -> format ;
2791
2789
}
2792
2790
2791
+ /* The real work is here */
2793
2792
DCH_processor (format ,result , true,is_interval , (void * )tmtc );
2794
2793
2795
2794
if (!incache )
2796
2795
pfree (format );
2797
2796
2798
2797
pfree (fmt_str );
2799
2798
2800
- /*
2801
- * for result is allocated max memory, which current format-picture needs,
2802
- * now it allocate result with real size
2803
- */
2804
- if (result && * result )
2805
- {
2806
- int len = strlen (result );
2807
-
2808
- if (len )
2809
- {
2810
- text * res = (text * )palloc (len + 1 + VARHDRSZ );
2799
+ /* convert C-string result to TEXT format */
2800
+ reslen = strlen (result );
2801
+ res = (text * )palloc (reslen + VARHDRSZ );
2802
+ memcpy (VARDATA (res ),result ,reslen );
2803
+ VARATT_SIZEP (res )= reslen + VARHDRSZ ;
2811
2804
2812
- memcpy (VARDATA (res ),result ,len );
2813
- VARATT_SIZEP (res )= len + VARHDRSZ ;
2814
- pfree (result );
2815
- return res ;
2816
- }
2817
- }
2818
2805
pfree (result );
2819
- return NULL ;
2806
+ return res ;
2820
2807
}
2821
2808
2822
2809
/****************************************************************************
@@ -2834,17 +2821,24 @@ timestamp_to_char(PG_FUNCTION_ARGS)
2834
2821
text * fmt = PG_GETARG_TEXT_P (1 ),
2835
2822
* res ;
2836
2823
TmToChar tmtc ;
2824
+ struct pg_tm * tm ;
2825
+ int thisdate ;
2837
2826
2838
2827
if ((VARSIZE (fmt )- VARHDRSZ ) <=0 || TIMESTAMP_NOT_FINITE (dt ))
2839
2828
PG_RETURN_NULL ();
2840
2829
2841
2830
ZERO_tmtc (& tmtc );
2831
+ tm = tmtcTm (& tmtc );
2842
2832
2843
- if (timestamp2tm (dt ,NULL ,tmtcTm ( & tmtc ) ,& tmtcFsec (& tmtc ),NULL ,NULL )!= 0 )
2833
+ if (timestamp2tm (dt ,NULL ,tm ,& tmtcFsec (& tmtc ),NULL ,NULL )!= 0 )
2844
2834
ereport (ERROR ,
2845
2835
(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
2846
2836
errmsg ("timestamp out of range" )));
2847
2837
2838
+ thisdate = date2j (tm -> tm_year ,tm -> tm_mon ,tm -> tm_mday );
2839
+ tm -> tm_wday = (thisdate + 1 ) %7 ;
2840
+ tm -> tm_yday = thisdate - date2j (tm -> tm_year ,1 ,1 )+ 1 ;
2841
+
2848
2842
if (!(res = datetime_to_char_body (& tmtc ,fmt , false)))
2849
2843
PG_RETURN_NULL ();
2850
2844
@@ -2859,17 +2853,24 @@ timestamptz_to_char(PG_FUNCTION_ARGS)
2859
2853
* res ;
2860
2854
TmToChar tmtc ;
2861
2855
int tz ;
2856
+ struct pg_tm * tm ;
2857
+ int thisdate ;
2862
2858
2863
2859
if ((VARSIZE (fmt )- VARHDRSZ ) <=0 || TIMESTAMP_NOT_FINITE (dt ))
2864
2860
PG_RETURN_NULL ();
2865
2861
2866
2862
ZERO_tmtc (& tmtc );
2863
+ tm = tmtcTm (& tmtc );
2867
2864
2868
- if (timestamp2tm (dt ,& tz ,tmtcTm ( & tmtc ) ,& tmtcFsec (& tmtc ),& tmtcTzn (& tmtc ),NULL )!= 0 )
2865
+ if (timestamp2tm (dt ,& tz ,tm ,& tmtcFsec (& tmtc ),& tmtcTzn (& tmtc ),NULL )!= 0 )
2869
2866
ereport (ERROR ,
2870
2867
(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
2871
2868
errmsg ("timestamp out of range" )));
2872
2869
2870
+ thisdate = date2j (tm -> tm_year ,tm -> tm_mon ,tm -> tm_mday );
2871
+ tm -> tm_wday = (thisdate + 1 ) %7 ;
2872
+ tm -> tm_yday = thisdate - date2j (tm -> tm_year ,1 ,1 )+ 1 ;
2873
+
2873
2874
if (!(res = datetime_to_char_body (& tmtc ,fmt , false)))
2874
2875
PG_RETURN_NULL ();
2875
2876
@@ -2888,15 +2889,20 @@ interval_to_char(PG_FUNCTION_ARGS)
2888
2889
text * fmt = PG_GETARG_TEXT_P (1 ),
2889
2890
* res ;
2890
2891
TmToChar tmtc ;
2892
+ struct pg_tm * tm ;
2891
2893
2892
2894
if ((VARSIZE (fmt )- VARHDRSZ ) <=0 )
2893
2895
PG_RETURN_NULL ();
2894
2896
2895
2897
ZERO_tmtc (& tmtc );
2898
+ tm = tmtcTm (& tmtc );
2896
2899
2897
- if (interval2tm (* it ,tmtcTm ( & tmtc ) ,& tmtcFsec (& tmtc ))!= 0 )
2900
+ if (interval2tm (* it ,tm ,& tmtcFsec (& tmtc ))!= 0 )
2898
2901
PG_RETURN_NULL ();
2899
2902
2903
+ /* wday is meaningless, yday approximates the total span in days */
2904
+ tm -> tm_yday = (tm -> tm_year * MONTHS_PER_YEAR + tm -> tm_mon )* DAYS_PER_MONTH + tm -> tm_mday ;
2905
+
2900
2906
if (!(res = datetime_to_char_body (& tmtc ,fmt , true)))
2901
2907
PG_RETURN_NULL ();
2902
2908