Skip to content

Commit

Permalink
pgdate: Improve handling of negative years
Browse files Browse the repository at this point in the history
The current parsing code doesn't handle negative year values and returns an
unhelpful error message. This change allows negative years to be specified, so
that negative-year datums can at least be round-tripped through the parser.

Supports #28099
Fixes #35255

Release note: None
  • Loading branch information
bobvawter committed Mar 11, 2019
1 parent a119a3a commit 53dd651
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
30 changes: 30 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/datetime
Original file line number Diff line number Diff line change
Expand Up @@ -1193,3 +1193,33 @@ query T
SELECT date_trunc('month', "date") AS date_trunc_month_created_at FROM "topics";
----
2017-12-01 00:00:00 +0000 UTC


# Test negative years to ensure they can round-trip through the parser.
# Also ensure that we don't trigger any of the "convenience" rules.
subtest regression_35255

query T
SELECT '-56325279622-12-26'::DATE
----
-56325279622-12-26 00:00:00 +0000 +0000

query T
SELECT '-5632-12-26'::DATE
----
-5632-12-26 00:00:00 +0000 +0000

query T
SELECT '-563-12-26'::DATE
----
-0563-12-26 00:00:00 +0000 +0000

query T
SELECT '-56-12-26'::DATE
----
-0056-12-26 00:00:00 +0000 +0000

query T
SELECT '-5-12-26'::DATE
----
-0005-12-26 00:00:00 +0000 +0000
9 changes: 6 additions & 3 deletions pkg/util/timeutil/pgdate/field_extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,13 @@ func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error
case fe.Wants(fieldYear) && fe.Wants(fieldMonth) && fe.Wants(fieldDay):
// Example: All date formats, we're starting from scratch.
switch {
case chunk.magnitude >= 6:
case chunk.magnitude >= 6 && chunk.separator != '-':
// Example: "YYMMDD"
// ^^^^^^
// Example: "YYYYMMDD"
// ^^^^^^^^
// We're looking at some kind of concatenated date.
// We're looking at some kind of concatenated date. We do want
// to exclude large-magnitude, negative years from this test.

// Record whether or not it's a two-digit year.
fe.tweakYear = chunk.magnitude == 6
Expand All @@ -350,7 +351,9 @@ func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error
// year-first mode, we'll accept the first chunk and possibly
// adjust a two-digit value later on. This means that
// 99 would get adjusted to 1999, but 0099 would not.
if chunk.magnitude <= 2 {
if chunk.separator == '-' {
chunk.v *= -1
} else if chunk.magnitude <= 2 {
fe.tweakYear = true
}
return fe.SetChunk(fieldYear, chunk)
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/timeutil/pgdate/parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func ParseTimestamp(now time.Time, mode ParseMode, s string) (time.Time, error)

// badFieldPrefixError constructs a CodeInvalidDatetimeFormatError pgerror.
func badFieldPrefixError(field field, prefix rune) error {
return inputErrorf("unexpected separator '%v' for field %s", prefix, field.Pretty())
return inputErrorf("unexpected separator '%s' for field %s", string(prefix), field.Pretty())
}

// inputErrorf returns a CodeInvalidDatetimeFormatError pgerror.
Expand Down

0 comments on commit 53dd651

Please sign in to comment.