Skip to content

Commit

Permalink
fix(bigquery): parse timestamp query parameter with RFC3339 (#6653)
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarowolfx committed Sep 12, 2022
1 parent 5de75dd commit aabd2d6
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 1 deletion.
97 changes: 97 additions & 0 deletions bigquery/integration_test.go
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
gax "github.com/googleapis/gax-go/v2"
bq "google.golang.org/api/bigquery/v2"
"google.golang.org/api/googleapi"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
Expand Down Expand Up @@ -1944,6 +1945,102 @@ func TestIntegration_QueryParameters(t *testing.T) {
}
}

// This test can be merged with the TestIntegration_QueryParameters as soon as support for explicit typed query parameter lands.
// To test timestamps with different formats, we need to be able to specify the type explicitly.
func TestIntegration_TimestampFormat(t *testing.T) {
if client == nil {
t.Skip("Integration tests skipped")
}
ctx := context.Background()
ts := time.Date(2020, 10, 15, 15, 04, 05, 0, time.UTC)

testCases := []struct {
query string
parameters []*bq.QueryParameter
wantRow []Value
wantConfig interface{}
}{
{
"SELECT @val",
[]*bq.QueryParameter{
{
Name: "val",
ParameterType: &bq.QueryParameterType{
Type: "TIMESTAMP",
},
ParameterValue: &bq.QueryParameterValue{
Value: ts.Format(timestampFormat),
},
},
},
[]Value{ts},
ts,
},
{
"SELECT @val",
[]*bq.QueryParameter{
{
Name: "val",
ParameterType: &bq.QueryParameterType{
Type: "TIMESTAMP",
},
ParameterValue: &bq.QueryParameterValue{
Value: ts.Format(time.RFC3339Nano),
},
},
},
[]Value{ts},
ts,
},
{
"SELECT @val",
[]*bq.QueryParameter{
{
Name: "val",
ParameterType: &bq.QueryParameterType{
Type: "TIMESTAMP",
},
ParameterValue: &bq.QueryParameterValue{
Value: ts.Format(time.RFC3339),
},
},
},
[]Value{ts},
ts,
},
}
for _, c := range testCases {
q := client.Query(c.query)
bqJob, err := q.newJob()
if err != nil {
t.Fatal(err)
}
bqJob.Configuration.Query.QueryParameters = c.parameters

job, err := q.client.insertJob(ctx, bqJob, nil)
if err != nil {
t.Fatal(err)
}
if job.LastStatus() == nil {
t.Error("no LastStatus")
}
it, err := job.Read(ctx)
if err != nil {
t.Fatal(err)
}
checkRead(t, "QueryParameters", it, [][]Value{c.wantRow})
config, err := job.Config()
if err != nil {
t.Fatal(err)
}
got := config.(*QueryConfig).Parameters[0].Value
if !testutil.Equal(got, c.wantConfig) {
t.Errorf("param %[1]v (%[1]T): config:\ngot %[2]v (%[2]T)\nwant %[3]v (%[3]T)",
c.parameters[0].ParameterValue.Value, got, c.wantConfig)
}
}
}

func TestIntegration_QueryDryRun(t *testing.T) {
if client == nil {
t.Skip("Integration tests skipped")
Expand Down
10 changes: 9 additions & 1 deletion bigquery/params.go
Expand Up @@ -416,7 +416,15 @@ func convertParamValue(qval *bq.QueryParameterValue, qtype *bq.QueryParameterTyp
if isNullScalar(qval) {
return NullTimestamp{Valid: false}, nil
}
return time.Parse(timestampFormat, qval.Value)
t, err := time.Parse(timestampFormat, qval.Value)
if err != nil {
t, err = time.Parse(time.RFC3339Nano, qval.Value)
if err != nil {
return nil, err
}
}
return t, nil

case "DATETIME":
if isNullScalar(qval) {
return NullDateTime{Valid: false}, nil
Expand Down

0 comments on commit aabd2d6

Please sign in to comment.