[go: up one dir, main page]

Skip to content

Commit

Permalink
feat(bigquery): add preview support for default values (#6464)
Browse files Browse the repository at this point in the history
* feat(bigquery): add preview support for default values
  • Loading branch information
shollyman committed Aug 18, 2022
1 parent 5e6e99e commit edc3be5
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 16 deletions.
54 changes: 38 additions & 16 deletions bigquery/schema.go
Expand Up @@ -121,17 +121,38 @@ type FieldSchema struct {
//
// See the Precision field for additional guidance about valid values.
Scale int64

// DefaultValueExpression is used to specify the default value of a field
// using a SQL expression. It can only be set for top level fields (columns).
//
// You can use struct or array expression to specify default value for the
// entire struct or array. The valid SQL expressions are:
//
// - Literals for all data types, including STRUCT and ARRAY.
// - The following functions:
// - CURRENT_TIMESTAMP
// - CURRENT_TIME
// - CURRENT_DATE
// - CURRENT_DATETIME
// - GENERATE_UUID
// - RAND
// - SESSION_USER
// - ST_GEOGPOINT
// - Struct or array composed with the above allowed functions, for example:
// [CURRENT_DATE(), DATE '2020-01-01']"
DefaultValueExpression string
}

func (fs *FieldSchema) toBQ() *bq.TableFieldSchema {
tfs := &bq.TableFieldSchema{
Description: fs.Description,
Name: fs.Name,
Type: string(fs.Type),
PolicyTags: fs.PolicyTags.toBQ(),
MaxLength: fs.MaxLength,
Precision: fs.Precision,
Scale: fs.Scale,
Description: fs.Description,
Name: fs.Name,
Type: string(fs.Type),
PolicyTags: fs.PolicyTags.toBQ(),
MaxLength: fs.MaxLength,
Precision: fs.Precision,
Scale: fs.Scale,
DefaultValueExpression: fs.DefaultValueExpression,
}

if fs.Repeated {
Expand Down Expand Up @@ -181,15 +202,16 @@ func (s Schema) toBQ() *bq.TableSchema {

func bqToFieldSchema(tfs *bq.TableFieldSchema) *FieldSchema {
fs := &FieldSchema{
Description: tfs.Description,
Name: tfs.Name,
Repeated: tfs.Mode == "REPEATED",
Required: tfs.Mode == "REQUIRED",
Type: FieldType(tfs.Type),
PolicyTags: bqToPolicyTagList(tfs.PolicyTags),
MaxLength: tfs.MaxLength,
Precision: tfs.Precision,
Scale: tfs.Scale,
Description: tfs.Description,
Name: tfs.Name,
Repeated: tfs.Mode == "REPEATED",
Required: tfs.Mode == "REQUIRED",
Type: FieldType(tfs.Type),
PolicyTags: bqToPolicyTagList(tfs.PolicyTags),
MaxLength: tfs.MaxLength,
Precision: tfs.Precision,
Scale: tfs.Scale,
DefaultValueExpression: tfs.DefaultValueExpression,
}

for _, f := range tfs.Fields {
Expand Down
28 changes: 28 additions & 0 deletions bigquery/schema_test.go
Expand Up @@ -320,6 +320,34 @@ func TestSchemaConversion(t *testing.T) {
},
},
},
{
// default values
bqSchema: &bq.TableSchema{
Fields: []*bq.TableFieldSchema{
{
Name: "foo",
Type: "STRING",
DefaultValueExpression: "I_LOVE_FOO",
},
{
Name: "bar",
Type: "TIMESTAMP",
DefaultValueExpression: "CURRENT_TIMESTAMP()",
},
}},
schema: Schema{
{
Name: "foo",
Type: StringFieldType,
DefaultValueExpression: "I_LOVE_FOO",
},
{
Name: "bar",
Type: TimestampFieldType,
DefaultValueExpression: "CURRENT_TIMESTAMP()",
},
},
},
{
// policy tags
bqSchema: &bq.TableSchema{
Expand Down
47 changes: 47 additions & 0 deletions bigquery/table_integration_test.go
Expand Up @@ -78,7 +78,54 @@ func TestIntegration_TableCreateWithConstraints(t *testing.T) {
if diff := testutil.Diff(meta.Schema, schema); diff != "" {
t.Fatalf("got=-, want=+:\n%s", diff)
}
}

func TestIntegration_TableCreateWithDefaultValues(t *testing.T) {
if client == nil {
t.Skip("Integration tests skipped")
}
ctx := context.Background()
table := dataset.Table("defaultvalues")
schema := Schema{
{Name: "str_col", Type: StringFieldType, DefaultValueExpression: "'FOO'"},
{Name: "timestamp_col", Type: TimestampFieldType, DefaultValueExpression: "CURRENT_TIMESTAMP()"},
}
err := table.Create(ctx, &TableMetadata{
Schema: schema,
ExpirationTime: testTableExpiration.Add(5 * time.Minute),
})
if err != nil {
t.Fatalf("table create error: %v", err)
}

meta, err := table.Metadata(ctx)
if err != nil {
t.Fatalf("couldn't get metadata: %v", err)
}

if diff := testutil.Diff(meta.Schema, schema); diff != "" {
t.Fatalf("got=-, want=+:\n%s", diff)
}

// SQL creation
id, _ := table.Identifier(StandardSQLID)
sql := fmt.Sprintf(`
CREATE OR REPLACE TABLE %s (
str_col STRING DEFAULT 'FOO',
timestamp_col TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
)`, id)
_, _, err = runQuerySQL(ctx, sql)
if err != nil {
t.Fatal(err)
}
meta, err = table.Metadata(ctx)
if err != nil {
t.Fatalf("couldn't get metadata after sql: %v", err)
}

if diff := testutil.Diff(meta.Schema, schema); diff != "" {
t.Fatalf("sql create: got=-, want=+:\n%s", diff)
}
}

func TestIntegration_TableCreateView(t *testing.T) {
Expand Down

0 comments on commit edc3be5

Please sign in to comment.