Skip to content

Commit aabd2d6

Browse files
authored
fix(bigquery): parse timestamp query parameter with RFC3339 (#6653)
1 parent 5de75dd commit aabd2d6

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

bigquery/integration_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"github.com/google/go-cmp/cmp"
4141
"github.com/google/go-cmp/cmp/cmpopts"
4242
gax "github.com/googleapis/gax-go/v2"
43+
bq "google.golang.org/api/bigquery/v2"
4344
"google.golang.org/api/googleapi"
4445
"google.golang.org/api/iterator"
4546
"google.golang.org/api/option"
@@ -1944,6 +1945,102 @@ func TestIntegration_QueryParameters(t *testing.T) {
19441945
}
19451946
}
19461947

1948+
// This test can be merged with the TestIntegration_QueryParameters as soon as support for explicit typed query parameter lands.
1949+
// To test timestamps with different formats, we need to be able to specify the type explicitly.
1950+
func TestIntegration_TimestampFormat(t *testing.T) {
1951+
if client == nil {
1952+
t.Skip("Integration tests skipped")
1953+
}
1954+
ctx := context.Background()
1955+
ts := time.Date(2020, 10, 15, 15, 04, 05, 0, time.UTC)
1956+
1957+
testCases := []struct {
1958+
query string
1959+
parameters []*bq.QueryParameter
1960+
wantRow []Value
1961+
wantConfig interface{}
1962+
}{
1963+
{
1964+
"SELECT @val",
1965+
[]*bq.QueryParameter{
1966+
{
1967+
Name: "val",
1968+
ParameterType: &bq.QueryParameterType{
1969+
Type: "TIMESTAMP",
1970+
},
1971+
ParameterValue: &bq.QueryParameterValue{
1972+
Value: ts.Format(timestampFormat),
1973+
},
1974+
},
1975+
},
1976+
[]Value{ts},
1977+
ts,
1978+
},
1979+
{
1980+
"SELECT @val",
1981+
[]*bq.QueryParameter{
1982+
{
1983+
Name: "val",
1984+
ParameterType: &bq.QueryParameterType{
1985+
Type: "TIMESTAMP",
1986+
},
1987+
ParameterValue: &bq.QueryParameterValue{
1988+
Value: ts.Format(time.RFC3339Nano),
1989+
},
1990+
},
1991+
},
1992+
[]Value{ts},
1993+
ts,
1994+
},
1995+
{
1996+
"SELECT @val",
1997+
[]*bq.QueryParameter{
1998+
{
1999+
Name: "val",
2000+
ParameterType: &bq.QueryParameterType{
2001+
Type: "TIMESTAMP",
2002+
},
2003+
ParameterValue: &bq.QueryParameterValue{
2004+
Value: ts.Format(time.RFC3339),
2005+
},
2006+
},
2007+
},
2008+
[]Value{ts},
2009+
ts,
2010+
},
2011+
}
2012+
for _, c := range testCases {
2013+
q := client.Query(c.query)
2014+
bqJob, err := q.newJob()
2015+
if err != nil {
2016+
t.Fatal(err)
2017+
}
2018+
bqJob.Configuration.Query.QueryParameters = c.parameters
2019+
2020+
job, err := q.client.insertJob(ctx, bqJob, nil)
2021+
if err != nil {
2022+
t.Fatal(err)
2023+
}
2024+
if job.LastStatus() == nil {
2025+
t.Error("no LastStatus")
2026+
}
2027+
it, err := job.Read(ctx)
2028+
if err != nil {
2029+
t.Fatal(err)
2030+
}
2031+
checkRead(t, "QueryParameters", it, [][]Value{c.wantRow})
2032+
config, err := job.Config()
2033+
if err != nil {
2034+
t.Fatal(err)
2035+
}
2036+
got := config.(*QueryConfig).Parameters[0].Value
2037+
if !testutil.Equal(got, c.wantConfig) {
2038+
t.Errorf("param %[1]v (%[1]T): config:\ngot %[2]v (%[2]T)\nwant %[3]v (%[3]T)",
2039+
c.parameters[0].ParameterValue.Value, got, c.wantConfig)
2040+
}
2041+
}
2042+
}
2043+
19472044
func TestIntegration_QueryDryRun(t *testing.T) {
19482045
if client == nil {
19492046
t.Skip("Integration tests skipped")

bigquery/params.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,15 @@ func convertParamValue(qval *bq.QueryParameterValue, qtype *bq.QueryParameterTyp
416416
if isNullScalar(qval) {
417417
return NullTimestamp{Valid: false}, nil
418418
}
419-
return time.Parse(timestampFormat, qval.Value)
419+
t, err := time.Parse(timestampFormat, qval.Value)
420+
if err != nil {
421+
t, err = time.Parse(time.RFC3339Nano, qval.Value)
422+
if err != nil {
423+
return nil, err
424+
}
425+
}
426+
return t, nil
427+
420428
case "DATETIME":
421429
if isNullScalar(qval) {
422430
return NullDateTime{Valid: false}, nil

0 commit comments

Comments
 (0)