-
+
Data Types
|
- interval [ (p) ]
+ interval [ fields ] [ (p) ]
time span
1 microsecond / 14 digits
|
- interval [ (p) ]
+ interval [ fields ] [ (p) ]
12 bytes
time intervals
-178000000 years
storage is used, or from 0 to 10 when floating-point storage is used.
+ The interval type has an additional option, which is
+ to restrict the set of stored fields by writing one of these phrases:
+ YEAR
+ MONTH
+ DAY
+ HOUR
+ MINUTE
+ SECOND
+ YEAR TO MONTH
+ DAY TO HOUR
+ DAY TO MINUTE
+ DAY TO SECOND
+ HOUR TO MINUTE
+ MINUTE TO SECOND
+
+ Input falling outside the specified set of fields is silently discarded.
+ Note that if both fields and
+ precision are specified, the
+ fields must include SECOND>,
+ since the precision applies only to the seconds.
+
+
The type time with time zone is defined by the SQL
standard, but the definition exhibits properties which lead to
direction> can be ago or
empty. The at sign (@>) is optional noise. The amounts
of different units are implicitly added up with appropriate
- sign accounting.
+ sign accounting. ago negates all the fields.
Quantities of days, hours, minutes, and seconds can be specified without
explicit unit markings. For example, '1 12:59:10'> is read
- the same as '1 day 12 hours 59 min 10 sec'>.
+ the same as '1 day 12 hours 59 min 10 sec'>. Also,
+ a combination of years and months can be specified with a dash;
+ for example '200-10'> is read the same as '200 years
+ 10 months'>. (These shorter forms are in fact the only ones allowed
+ by the SQL standard.)
- The optional subsecond precision p should
- be between 0 and 6, and defaults to the precision of the input literal.
+ When writing an interval constant with a fields>
+ specification, or when assigning to an interval column that was defined
+ with a fields> specification, the interpretation of
+ unmarked quantities depends on the fields>. For
+ example INTERVAL '1' YEAR> is read as 1 year, whereas
+ INTERVAL '1'> means 1 second.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.622 2008/09/02 20:37:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.623 2008/09/11 15:27:30 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
%type extract_list overlay_list position_list
%type substr_list trim_list
-%type <ival> opt_interval
+%type <list> opt_interval interval_second
%type overlay_placing substr_from substr_for
%type opt_instead opt_analyze
| ConstInterval Sconst opt_interval
{
TypeName *t = $1;
- if ($3 != INTERVAL_FULL_RANGE)
+ if ($3 != NIL)
{
- if (($3 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
+ A_Const *n = (A_Const *) linitial($3);
+ if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
scanner_errposition(@3)));
- t->typmods = list_make1(makeIntConst($3, @3));
}
+ t->typmods = $3;
$$ = makeStringConstCast($2, @2, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
TypeName *t = $1;
- if (($6 != INTERVAL_FULL_RANGE)
- && (($6 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
- scanner_errposition(@6)));
- t->typmods = list_make2(makeIntConst($6, @6),
- makeIntConst($3, @3));
+ if ($6 != NIL)
+ {
+ A_Const *n = (A_Const *) linitial($6);
+ if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
+ scanner_errposition(@6)));
+ if (list_length($6) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("interval precision specified twice"),
+ scanner_errposition(@1)));
+ t->typmods = lappend($6, makeIntConst($3, @3));
+ }
+ else
+ t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
+ makeIntConst($3, @3));
$$ = makeStringConstCast($5, @5, t);
}
| NumericOnly { $$ = makeAConst($1, @1); }
| ConstInterval opt_interval
{
$$ = $1;
- if ($2 != INTERVAL_FULL_RANGE)
- $$->typmods = list_make1(makeIntConst($2, @2));
+ $$->typmods = $2;
}
| ConstInterval '(' Iconst ')' opt_interval
{
$$ = $1;
- $$->typmods = list_make2(makeIntConst($5, @5),
- makeIntConst($3, @3));
+ if ($5 != NIL)
+ {
+ if (list_length($5) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("interval precision specified twice"),
+ scanner_errposition(@1)));
+ $$->typmods = lappend($5, makeIntConst($3, @3));
+ }
+ else
+ $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
+ makeIntConst($3, @3));
}
;
;
opt_interval:
- YEAR_P { $$ = INTERVAL_MASK(YEAR); }
- | MONTH_P { $$ = INTERVAL_MASK(MONTH); }
- | DAY_P { $$ = INTERVAL_MASK(DAY); }
- | HOUR_P { $$ = INTERVAL_MASK(HOUR); }
- | MINUTE_P { $$ = INTERVAL_MASK(MINUTE); }
- | SECOND_P { $$ = INTERVAL_MASK(SECOND); }
+ YEAR_P
+ { $$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR), @1)); }
+ | MONTH_P
+ { $$ = list_make1(makeIntConst(INTERVAL_MASK(MONTH), @1)); }
+ | DAY_P
+ { $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY), @1)); }
+ | HOUR_P
+ { $$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR), @1)); }
+ | MINUTE_P
+ { $$ = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), @1)); }
+ | interval_second
+ { $$ = $1; }
| YEAR_P TO MONTH_P
- { $$ = INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH); }
+ {
+ $$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR) |
+ INTERVAL_MASK(MONTH), @1));
+ }
| DAY_P TO HOUR_P
- { $$ = INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR); }
+ {
+ $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
+ INTERVAL_MASK(HOUR), @1));
+ }
| DAY_P TO MINUTE_P
- { $$ = INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR)
- | INTERVAL_MASK(MINUTE); }
- | DAY_P TO SECOND_P
- { $$ = INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR)
- | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND); }
+ {
+ $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY) |
+ INTERVAL_MASK(HOUR) |
+ INTERVAL_MASK(MINUTE), @1));
+ }
+ | DAY_P TO interval_second
+ {
+ $$ = $3;
+ linitial($$) = makeIntConst(INTERVAL_MASK(DAY) |
+ INTERVAL_MASK(HOUR) |
+ INTERVAL_MASK(MINUTE) |
+ INTERVAL_MASK(SECOND), @1);
+ }
| HOUR_P TO MINUTE_P
- { $$ = INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE); }
- | HOUR_P TO SECOND_P
- { $$ = INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE)
- | INTERVAL_MASK(SECOND); }
- | MINUTE_P TO SECOND_P
- { $$ = INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND); }
- | /*EMPTY*/ { $$ = INTERVAL_FULL_RANGE; }
+ {
+ $$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR) |
+ INTERVAL_MASK(MINUTE), @1));
+ }
+ | HOUR_P TO interval_second
+ {
+ $$ = $3;
+ linitial($$) = makeIntConst(INTERVAL_MASK(HOUR) |
+ INTERVAL_MASK(MINUTE) |
+ INTERVAL_MASK(SECOND), @1);
+ }
+ | MINUTE_P TO interval_second
+ {
+ $$ = $3;
+ linitial($$) = makeIntConst(INTERVAL_MASK(MINUTE) |
+ INTERVAL_MASK(SECOND), @1);
+ }
+ | /*EMPTY*/
+ { $$ = NIL; }
+ ;
+
+interval_second:
+ SECOND_P
+ {
+ $$ = list_make1(makeIntConst(INTERVAL_MASK(SECOND), @1));
+ }
+ | SECOND_P '(' Iconst ')'
+ {
+ $$ = list_make2(makeIntConst(INTERVAL_MASK(SECOND), @1),
+ makeIntConst($3, @3));
+ }
;
| ConstInterval Sconst opt_interval
{
TypeName *t = $1;
- /* precision is not specified, but fields may be... */
- if ($3 != INTERVAL_FULL_RANGE)
- t->typmods = list_make1(makeIntConst($3, @3));
+ t->typmods = $3;
$$ = makeStringConstCast($2, @2, t);
}
| ConstInterval '(' Iconst ')' Sconst opt_interval
{
TypeName *t = $1;
- t->typmods = list_make2(makeIntConst($6, @6),
- makeIntConst($3, @3));
+ if ($6 != NIL)
+ {
+ if (list_length($6) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("interval precision specified twice"),
+ scanner_errposition(@1)));
+ t->typmods = lappend($6, makeIntConst($3, @3));
+ }
+ else
+ t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
+ makeIntConst($3, @3));
$$ = makeStringConstCast($5, @5, t);
}
| TRUE_P