Skip to content

Commit df60464

Browse files
authored
feat(bigtable): support update column family's value type to non-aggregate type (#10410)
* feat(bigtable): support update column family's value type to non-aggregate type * Fix public method doc. * Add integration test. * Add nil check for type. * Add gcpolicy nil check.
1 parent 82f661d commit df60464

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

bigtable/admin.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,9 @@ func IgnoreWarnings() GCPolicyOption {
686686
}
687687

688688
func (ac *AdminClient) setGCPolicy(ctx context.Context, table, family string, policy GCPolicy, opts ...GCPolicyOption) error {
689+
if policy == nil {
690+
return fmt.Errorf("policy cannot be nil")
691+
}
689692
ctx = mergeOutgoingMetadata(ctx, ac.md)
690693
prefix := ac.instancePrefix()
691694

@@ -707,13 +710,41 @@ func (ac *AdminClient) setGCPolicy(ctx context.Context, table, family string, po
707710
return err
708711
}
709712

713+
func (ac *AdminClient) setValueTypeImpl(ctx context.Context, table, family string, valueType Type) error {
714+
if valueType == nil {
715+
return fmt.Errorf("value type must be non nil")
716+
}
717+
if _, ok := valueType.proto().GetKind().(*btapb.Type_AggregateType); ok {
718+
return fmt.Errorf("update family value type to aggregate type is unsupported")
719+
}
720+
721+
ctx = mergeOutgoingMetadata(ctx, ac.md)
722+
prefix := ac.instancePrefix()
723+
724+
req := &btapb.ModifyColumnFamiliesRequest{
725+
Name: prefix + "/tables/" + table,
726+
Modifications: []*btapb.ModifyColumnFamiliesRequest_Modification{{
727+
Id: family,
728+
Mod: &btapb.ModifyColumnFamiliesRequest_Modification_Update{Update: &btapb.ColumnFamily{ValueType: valueType.proto()}},
729+
}},
730+
}
731+
_, err := ac.tClient.ModifyColumnFamilies(ctx, req)
732+
return err
733+
}
734+
710735
// SetGCPolicy specifies which cells in a column family should be garbage collected.
711736
// GC executes opportunistically in the background; table reads may return data
712737
// matching the GC policy.
713738
func (ac *AdminClient) SetGCPolicy(ctx context.Context, table, family string, policy GCPolicy) error {
714739
return ac.SetGCPolicyWithOptions(ctx, table, family, policy)
715740
}
716741

742+
// SetValueType specifies the type of all values in a column family. Currently,
743+
// only non-aggregate type is supported.
744+
func (ac *AdminClient) SetValueType(ctx context.Context, table, family string, valueType Type) error {
745+
return ac.setValueTypeImpl(ctx, table, family, valueType)
746+
}
747+
717748
// SetGCPolicyWithOptions is similar to SetGCPolicy but allows passing options
718749
func (ac *AdminClient) SetGCPolicyWithOptions(ctx context.Context, table, family string, policy GCPolicy, opts ...GCPolicyOption) error {
719750
return ac.setGCPolicy(ctx, table, family, policy, opts...)

bigtable/admin_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,38 @@ func TestTableAdmin_SetGcPolicy(t *testing.T) {
410410
}
411411
}
412412

413+
func TestTableAdmin_SetType(t *testing.T) {
414+
for _, test := range []struct {
415+
desc string
416+
familyType Type
417+
hasError bool
418+
}{
419+
{
420+
desc: "Update with aggregate type failed",
421+
familyType: AggregateType{Input: Int64Type{Encoding: BigEndianBytesEncoding{}}, Aggregator: SumAggregator{}},
422+
hasError: true,
423+
},
424+
{
425+
desc: "Update with string type",
426+
familyType: StringType{Encoding: StringUtf8Encoding{}},
427+
hasError: false,
428+
},
429+
{
430+
desc: "Update with nil type",
431+
familyType: nil,
432+
hasError: true,
433+
},
434+
} {
435+
mock := &mockTableAdminClock{}
436+
c := setupTableClient(t, mock)
437+
438+
err := c.SetValueType(context.Background(), "My-table", "cf1", test.familyType)
439+
if err != nil && !test.hasError {
440+
t.Fatalf("Unexpected error when setting type: %v", err)
441+
}
442+
}
443+
}
444+
413445
func TestTableAdmin_CreateAuthorizedView_DeletionProtection_Protected(t *testing.T) {
414446
mock := &mockTableAdminClock{}
415447
c := setupTableClient(t, mock)

bigtable/integration_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3962,6 +3962,58 @@ func TestIntegration_DataAuthorizedView(t *testing.T) {
39623962
}
39633963
}
39643964

3965+
func TestIntegration_TestUpdateColumnFamilyValueType(t *testing.T) {
3966+
testEnv, err := NewIntegrationEnv()
3967+
if err != nil {
3968+
t.Fatalf("IntegrationEnv: %v", err)
3969+
}
3970+
defer testEnv.Close()
3971+
3972+
if !testEnv.Config().UseProd {
3973+
t.Skip("emulator doesn't support update column family operation")
3974+
}
3975+
3976+
timeout := 15 * time.Minute
3977+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
3978+
defer cancel()
3979+
3980+
adminClient, err := testEnv.NewAdminClient()
3981+
if err != nil {
3982+
t.Fatalf("NewAdminClient: %v", err)
3983+
}
3984+
defer adminClient.Close()
3985+
3986+
tblConf := TableConf{
3987+
TableID: testEnv.Config().Table,
3988+
ColumnFamilies: map[string]Family{
3989+
"cf": {
3990+
GCPolicy: MaxVersionsPolicy(1),
3991+
},
3992+
},
3993+
}
3994+
if err := adminClient.CreateTableFromConf(ctx, &tblConf); err != nil {
3995+
t.Fatalf("Create table from TableConf error: %v", err)
3996+
}
3997+
// Clean-up
3998+
defer deleteTable(ctx, t, adminClient, tblConf.TableID)
3999+
4000+
// Update column family type to aggregate type should not be successful
4001+
err = adminClient.SetValueType(ctx, tblConf.TableID, "cf", AggregateType{
4002+
Input: Int64Type{}, Aggregator: SumAggregator{},
4003+
})
4004+
if err == nil {
4005+
t.Fatalf("Update family type to aggregate type should not be successful")
4006+
}
4007+
4008+
// Update column family type to string type should be successful
4009+
err = adminClient.SetValueType(ctx, tblConf.TableID, "cf", StringType{
4010+
Encoding: StringUtf8Encoding{},
4011+
})
4012+
if err != nil {
4013+
t.Fatalf("Failed to update value type of family: %v", err)
4014+
}
4015+
}
4016+
39654017
// TestIntegration_DirectPathFallback tests the CFE fallback when the directpath net is blackholed.
39664018
func TestIntegration_DirectPathFallback(t *testing.T) {
39674019
ctx := context.Background()

0 commit comments

Comments
 (0)