8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.190 2008/06/09 19:34:02 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.191 2008/09/10 18:29:41 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -35,8 +35,8 @@ static int DecodeNumber(int flen, char *field, bool haveTextMonth,
35
35
static int DecodeNumberField (int len , char * str ,
36
36
int fmask , int * tmask ,
37
37
struct pg_tm * tm , fsec_t * fsec , bool * is2digits );
38
- static int DecodeTime (char * str , int fmask , int * tmask ,
39
- struct pg_tm * tm , fsec_t * fsec );
38
+ static int DecodeTime (char * str , int fmask , int range ,
39
+ int * tmask , struct pg_tm * tm , fsec_t * fsec );
40
40
static int DecodeTimezone (char * str , int * tzp );
41
41
static const datetkn * datebsearch (const char * key , const datetkn * base , int nel );
42
42
static int DecodeDate (char * str , int fmask , int * tmask , bool * is2digits ,
@@ -832,7 +832,8 @@ DecodeDateTime(char **field, int *ftype, int nf,
832
832
break ;
833
833
834
834
case DTK_TIME :
835
- dterr = DecodeTime (field [i ], fmask , & tmask , tm , fsec );
835
+ dterr = DecodeTime (field [i ], fmask , INTERVAL_FULL_RANGE ,
836
+ & tmask , tm , fsec );
836
837
if (dterr )
837
838
return dterr ;
838
839
@@ -1563,6 +1564,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
1563
1564
1564
1565
case DTK_TIME :
1565
1566
dterr = DecodeTime (field [i ], (fmask | DTK_DATE_M ),
1567
+ INTERVAL_FULL_RANGE ,
1566
1568
& tmask , tm , fsec );
1567
1569
if (dterr )
1568
1570
return dterr ;
@@ -2224,7 +2226,8 @@ ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
2224
2226
* used to represent time spans.
2225
2227
*/
2226
2228
static int
2227
- DecodeTime (char * str , int fmask , int * tmask , struct pg_tm * tm , fsec_t * fsec )
2229
+ DecodeTime (char * str , int fmask , int range ,
2230
+ int * tmask , struct pg_tm * tm , fsec_t * fsec )
2228
2231
{
2229
2232
char * cp ;
2230
2233
@@ -2245,6 +2248,13 @@ DecodeTime(char *str, int fmask, int *tmask, struct pg_tm * tm, fsec_t *fsec)
2245
2248
{
2246
2249
tm -> tm_sec = 0 ;
2247
2250
* fsec = 0 ;
2251
+ /* If it's a MINUTE TO SECOND interval, take 2 fields as being mm:ss */
2252
+ if (range == (INTERVAL_MASK (MINUTE ) | INTERVAL_MASK (SECOND )))
2253
+ {
2254
+ tm -> tm_sec = tm -> tm_min ;
2255
+ tm -> tm_min = tm -> tm_hour ;
2256
+ tm -> tm_hour = 0 ;
2257
+ }
2248
2258
}
2249
2259
else if (* cp != ':' )
2250
2260
return DTERR_BAD_FORMAT ;
@@ -2705,7 +2715,8 @@ DecodeSpecial(int field, char *lowtoken, int *val)
2705
2715
* preceding an hh:mm:ss field. - thomas 1998-04-30
2706
2716
*/
2707
2717
int
2708
- DecodeInterval (char * * field , int * ftype , int nf , int * dtype , struct pg_tm * tm , fsec_t * fsec )
2718
+ DecodeInterval (char * * field , int * ftype , int nf , int range ,
2719
+ int * dtype , struct pg_tm * tm , fsec_t * fsec )
2709
2720
{
2710
2721
bool is_before = FALSE;
2711
2722
char * cp ;
@@ -2734,7 +2745,8 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
2734
2745
switch (ftype [i ])
2735
2746
{
2736
2747
case DTK_TIME :
2737
- dterr = DecodeTime (field [i ], fmask , & tmask , tm , fsec );
2748
+ dterr = DecodeTime (field [i ], fmask , range ,
2749
+ & tmask , tm , fsec );
2738
2750
if (dterr )
2739
2751
return dterr ;
2740
2752
type = DTK_DAY ;
@@ -2757,7 +2769,8 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
2757
2769
while (* cp != '\0' && * cp != ':' && * cp != '.' )
2758
2770
cp ++ ;
2759
2771
if (* cp == ':' &&
2760
- DecodeTime (field [i ] + 1 , fmask , & tmask , tm , fsec ) == 0 )
2772
+ DecodeTime (field [i ] + 1 , fmask , INTERVAL_FULL_RANGE ,
2773
+ & tmask , tm , fsec ) == 0 )
2761
2774
{
2762
2775
if (* field [i ] == '-' )
2763
2776
{
@@ -2796,19 +2809,66 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
2796
2809
type = DTK_HOUR ;
2797
2810
}
2798
2811
}
2799
- /* DROP THROUGH */
2812
+ /* FALL THROUGH */
2800
2813
2801
2814
case DTK_DATE :
2802
2815
case DTK_NUMBER :
2816
+ if (type == IGNORE_DTF )
2817
+ {
2818
+ /* use typmod to decide what rightmost integer field is */
2819
+ switch (range )
2820
+ {
2821
+ case INTERVAL_MASK (YEAR ):
2822
+ type = DTK_YEAR ;
2823
+ break ;
2824
+ case INTERVAL_MASK (MONTH ):
2825
+ case INTERVAL_MASK (YEAR ) | INTERVAL_MASK (MONTH ):
2826
+ type = DTK_MONTH ;
2827
+ break ;
2828
+ case INTERVAL_MASK (DAY ):
2829
+ type = DTK_DAY ;
2830
+ break ;
2831
+ case INTERVAL_MASK (HOUR ):
2832
+ case INTERVAL_MASK (DAY ) | INTERVAL_MASK (HOUR ):
2833
+ case INTERVAL_MASK (DAY ) | INTERVAL_MASK (HOUR ) | INTERVAL_MASK (MINUTE ):
2834
+ case INTERVAL_MASK (DAY ) | INTERVAL_MASK (HOUR ) | INTERVAL_MASK (MINUTE ) | INTERVAL_MASK (SECOND ):
2835
+ type = DTK_HOUR ;
2836
+ break ;
2837
+ case INTERVAL_MASK (MINUTE ):
2838
+ case INTERVAL_MASK (HOUR ) | INTERVAL_MASK (MINUTE ):
2839
+ type = DTK_MINUTE ;
2840
+ break ;
2841
+ case INTERVAL_MASK (SECOND ):
2842
+ case INTERVAL_MASK (HOUR ) | INTERVAL_MASK (MINUTE ) | INTERVAL_MASK (SECOND ):
2843
+ case INTERVAL_MASK (MINUTE ) | INTERVAL_MASK (SECOND ):
2844
+ type = DTK_SECOND ;
2845
+ break ;
2846
+ default :
2847
+ type = DTK_SECOND ;
2848
+ break ;
2849
+ }
2850
+ }
2851
+
2803
2852
errno = 0 ;
2804
2853
val = strtoi (field [i ], & cp , 10 );
2805
2854
if (errno == ERANGE )
2806
2855
return DTERR_FIELD_OVERFLOW ;
2807
2856
2808
- if (type == IGNORE_DTF )
2809
- type = DTK_SECOND ;
2857
+ if (* cp == '-' )
2858
+ {
2859
+ /* SQL "years-months" syntax */
2860
+ int val2 ;
2810
2861
2811
- if (* cp == '.' )
2862
+ val2 = strtoi (cp + 1 , & cp , 10 );
2863
+ if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR )
2864
+ return DTERR_FIELD_OVERFLOW ;
2865
+ if (* cp != '\0' )
2866
+ return DTERR_BAD_FORMAT ;
2867
+ type = DTK_MONTH ;
2868
+ val = val * MONTHS_PER_YEAR + val2 ;
2869
+ fval = 0 ;
2870
+ }
2871
+ else if (* cp == '.' )
2812
2872
{
2813
2873
fval = strtod (cp , & cp );
2814
2874
if (* cp != '\0' )
@@ -2896,6 +2956,7 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
2896
2956
#endif
2897
2957
}
2898
2958
tmask = DTK_M (HOUR );
2959
+ type = DTK_DAY ;
2899
2960
break ;
2900
2961
2901
2962
case DTK_DAY :
0 commit comments