Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release-19.1: pgdate: correctly parse dates with large year parts #36555

Merged
merged 1 commit into from
Apr 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/datetime
Original file line number Diff line number Diff line change
Expand Up @@ -1229,3 +1229,24 @@ query T
SELECT '-5-12-26'::DATE
----
-0005-12-26 00:00:00 +0000 +0000

subtest regression_36146

query T
WITH
w (c) AS (VALUES (NULL), (NULL))
SELECT
'1971-03-18'::DATE + 300866802885581286
FROM
w
ORDER BY
c
----
108672393952-01-22 00:00:00 +0000 +0000
108672393952-01-22 00:00:00 +0000 +0000

query T
SELECT
'1971-03-18'::DATE + 300866802885581286
----
108672393952-01-22 00:00:00 +0000 +0000
20 changes: 14 additions & 6 deletions pkg/util/timeutil/pgdate/field_extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ func (fe *fieldExtract) Extract(s string) error {
// of which fields have already been set in order to keep picking
// out field data.
textMonth := !fe.Wants(fieldMonth)
for _, n := range numbers {
for i := range numbers {
if fe.wanted == 0 {
return inputErrorf("too many input fields")
}
if err := fe.interpretNumber(n, textMonth); err != nil {
if err := fe.interpretNumber(numbers, i, textMonth); err != nil {
return err
}
}
Expand All @@ -248,7 +248,8 @@ func (fe *fieldExtract) Get(field field) (int, bool) {

// interpretNumber applies pattern-matching rules to figure out which
// field the next chunk of input should be applied to.
func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error {
func (fe *fieldExtract) interpretNumber(numbers []numberChunk, idx int, textMonth bool) error {
chunk := numbers[idx]
switch {
case chunk.separator == '.':
// Example: 04:04:04.913231+00:00, a fractional second.
Expand Down Expand Up @@ -318,9 +319,16 @@ func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error
return fe.SetDayOfYear(chunk)

case fe.Wants(fieldYear) && fe.Wants(fieldMonth) && fe.Wants(fieldDay):
var nextSep rune
if len(numbers) > idx+1 {
nextSep = numbers[idx+1].separator
}
// Example: All date formats, we're starting from scratch.
switch {
case chunk.magnitude >= 6 && chunk.separator != '-':
// We examine the next separator to decide if this is a
// concatenated date or a really long year. If it's a - or /
// then this is one part of a date instead of the whole date.
case chunk.magnitude >= 6 && chunk.separator != '-' && nextSep != '-' && nextSep != '/':
// Example: "YYMMDD"
// ^^^^^^
// Example: "YYYYMMDD"
Expand Down Expand Up @@ -519,7 +527,7 @@ func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error
// timezone is in the middle of a timestamp.
fe.has = fe.has.AddAll(tzFields)
fe.wanted = fe.wanted.ClearAll(tzFields)
return fe.interpretNumber(chunk, textMonth)
return fe.interpretNumber(numbers, idx, textMonth)

case !fe.Wants(fieldTZHour) && !fe.Wants(fieldTZMinute) && fe.Wants(fieldTZSecond):
// Example: "<Time> +04:05:06"
Expand All @@ -536,7 +544,7 @@ func (fe *fieldExtract) interpretNumber(chunk numberChunk, textMonth bool) error
// See the case above.
fe.has = fe.has.Add(fieldTZSecond)
fe.wanted = fe.wanted.Clear(fieldTZSecond)
return fe.interpretNumber(chunk, textMonth)
return fe.interpretNumber(numbers, idx, textMonth)

case fe.Wants(fieldHour) && fe.Wants(fieldMinute) && fe.Wants(fieldSecond):
// Example: "[Date] HH:MM:SS"
Expand Down
12 changes: 12 additions & 0 deletions pkg/util/timeutil/pgdate/parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,18 @@ var dateTestData = []timeData{
exp: time.Date(2018, 10, 23, 0, 0, 0, 0, time.FixedZone("", 60*60)),
hasTimezone: true,
},
{
s: "108672393952-01-22",
exp: time.Date(108672393952, 1, 22, 0, 0, 0, 0, time.UTC),
},
{
s: "121212-01-01",
exp: time.Date(121212, 1, 1, 0, 0, 0, 0, time.UTC),
},
{
s: "121212",
exp: time.Date(2012, 12, 12, 0, 0, 0, 0, time.UTC),
},
}

var timeTestData = []timeData{
Expand Down