Skip to content

Commit ed488b9

Browse files
authored
feat(bigtable): Add DeletionProtection support for Logical Views (#11895)
* feat(bigtable): Add DeletionProtection support for Logical Views * fix tests * fix test * update doc
1 parent 262db37 commit ed488b9

File tree

2 files changed

+62
-14
lines changed

2 files changed

+62
-14
lines changed

bigtable/admin.go

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,10 @@ func (ac *AdminClient) Tables(ctx context.Context) ([]string, error) {
275275
// disable change stream retention.
276276
type ChangeStreamRetention optional.Duration
277277

278-
// DeletionProtection indicates whether the table is protected against data loss
279-
// i.e. when set to protected, deleting the table, the column families in the table,
280-
// and the instance containing the table would be prohibited.
278+
// DeletionProtection indicates whether the table, authorized view, logical view or
279+
// materialized view is protected against data loss i.e. when set to protected,
280+
// deleting the view, the table, the column families in the table,
281+
// and the instance containing the table or view would be prohibited.
281282
type DeletionProtection int
282283

283284
// None indicates that deletion protection is unset
@@ -3123,13 +3124,25 @@ func (iac *InstanceAdminClient) CreateLogicalView(ctx context.Context, instanceI
31233124
return errors.New("LogicalViewID is required")
31243125
}
31253126

3127+
lv := &btapb.LogicalView{
3128+
Query: conf.Query,
3129+
}
3130+
if conf.DeletionProtection != None {
3131+
switch dp := conf.DeletionProtection; dp {
3132+
case Protected:
3133+
lv.DeletionProtection = true
3134+
case Unprotected:
3135+
lv.DeletionProtection = false
3136+
default:
3137+
break
3138+
}
3139+
}
3140+
31263141
ctx = mergeOutgoingMetadata(ctx, iac.md)
31273142
req := &btapb.CreateLogicalViewRequest{
31283143
Parent: instancePrefix(iac.project, instanceID),
31293144
LogicalViewId: conf.LogicalViewID,
3130-
LogicalView: &btapb.LogicalView{
3131-
Query: conf.Query,
3132-
},
3145+
LogicalView: lv,
31333146
}
31343147

31353148
op, err := iac.iClient.CreateLogicalView(ctx, req)
@@ -3144,7 +3157,8 @@ func (iac *InstanceAdminClient) CreateLogicalView(ctx context.Context, instanceI
31443157
type LogicalViewInfo struct {
31453158
LogicalViewID string
31463159

3147-
Query string
3160+
Query string
3161+
DeletionProtection DeletionProtection
31483162
}
31493163

31503164
// LogicalViewInfo retrieves information about a logical view.
@@ -3165,7 +3179,13 @@ func (iac *InstanceAdminClient) LogicalViewInfo(ctx context.Context, instanceID,
31653179
if err != nil {
31663180
return nil, err
31673181
}
3168-
return &LogicalViewInfo{LogicalViewID: strings.TrimPrefix(res.Name, prefix+"/logicalViews/"), Query: res.Query}, nil
3182+
lv := &LogicalViewInfo{LogicalViewID: strings.TrimPrefix(res.Name, prefix+"/logicalViews/"), Query: res.Query}
3183+
if res.DeletionProtection {
3184+
lv.DeletionProtection = Protected
3185+
} else {
3186+
lv.DeletionProtection = Unprotected
3187+
}
3188+
return lv, nil
31693189
}
31703190

31713191
// LogicalViews returns a list of the logical views in the instance.
@@ -3185,8 +3205,14 @@ func (iac *InstanceAdminClient) LogicalViews(ctx context.Context, instanceID str
31853205
return nil, err
31863206
}
31873207

3188-
for _, lv := range res.LogicalViews {
3189-
views = append(views, LogicalViewInfo{LogicalViewID: strings.TrimPrefix(lv.Name, prefix+"/logicalViews/"), Query: lv.Query})
3208+
for _, lView := range res.LogicalViews {
3209+
lv := LogicalViewInfo{LogicalViewID: strings.TrimPrefix(lView.Name, prefix+"/logicalViews/"), Query: lView.Query}
3210+
if lView.DeletionProtection {
3211+
lv.DeletionProtection = Protected
3212+
} else {
3213+
lv.DeletionProtection = Unprotected
3214+
}
3215+
views = append(views, lv)
31903216
}
31913217
return views, nil
31923218
}
@@ -3207,6 +3233,17 @@ func (iac *InstanceAdminClient) UpdateLogicalView(ctx context.Context, instanceI
32073233
updateMask.Paths = append(updateMask.Paths, "query")
32083234
lv.Query = conf.Query
32093235
}
3236+
if conf.DeletionProtection != None {
3237+
updateMask.Paths = append(updateMask.Paths, "deletion_protection")
3238+
switch dp := conf.DeletionProtection; dp {
3239+
case Protected:
3240+
lv.DeletionProtection = true
3241+
case Unprotected:
3242+
lv.DeletionProtection = false
3243+
default:
3244+
break
3245+
}
3246+
}
32103247
req := &btapb.UpdateLogicalViewRequest{
32113248
LogicalView: lv,
32123249
UpdateMask: updateMask,

bigtable/integration_test.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5093,8 +5093,9 @@ func TestIntegration_AdminLogicalView(t *testing.T) {
50935093
defer instanceAdminClient.DeleteLogicalView(ctx, testEnv.Config().Instance, logicalView)
50945094

50955095
logicalViewInfo := LogicalViewInfo{
5096-
LogicalViewID: logicalView,
5097-
Query: fmt.Sprintf("SELECT _key, fam1['col1'] as col FROM `%s`", tblConf.TableID),
5096+
LogicalViewID: logicalView,
5097+
Query: fmt.Sprintf("SELECT _key, fam1['col1'] as col FROM `%s`", tblConf.TableID),
5098+
DeletionProtection: Protected,
50985099
}
50995100
if err = instanceAdminClient.CreateLogicalView(ctx, testEnv.Config().Instance, &logicalViewInfo); err != nil {
51005101
t.Fatalf("Creating logical view: %v", err)
@@ -5114,6 +5115,9 @@ func TestIntegration_AdminLogicalView(t *testing.T) {
51145115
if got, want := logicalViews[0].Query, logicalViewInfo.Query; got != want {
51155116
t.Errorf("LogicalView Query: %q, want: %q", got, want)
51165117
}
5118+
if got, want := logicalViews[0].DeletionProtection, logicalViewInfo.DeletionProtection; got != want {
5119+
t.Errorf("LogicalView DeletionProtection: %v, want: %v", got, want)
5120+
}
51175121

51185122
// Get logical view
51195123
lvInfo, err := instanceAdminClient.LogicalViewInfo(ctx, testEnv.Config().Instance, logicalView)
@@ -5123,11 +5127,15 @@ func TestIntegration_AdminLogicalView(t *testing.T) {
51235127
if got, want := lvInfo.Query, logicalViewInfo.Query; got != want {
51245128
t.Errorf("LogicalView Query: %q, want: %q", got, want)
51255129
}
5130+
if got, want := lvInfo.DeletionProtection, logicalViewInfo.DeletionProtection; got != want {
5131+
t.Errorf("LogicalView DeletionProtection: %v, want: %v", got, want)
5132+
}
51265133

51275134
// Update logical view
51285135
newLogicalViewInfo := LogicalViewInfo{
5129-
LogicalViewID: logicalView,
5130-
Query: fmt.Sprintf("SELECT _key, fam2[col1] as col FROM `%s`", tblConf.TableID),
5136+
LogicalViewID: logicalView,
5137+
Query: fmt.Sprintf("SELECT _key, fam2['col1'] as col FROM `%s`", tblConf.TableID),
5138+
DeletionProtection: Unprotected,
51315139
}
51325140
err = instanceAdminClient.UpdateLogicalView(ctx, testEnv.Config().Instance, newLogicalViewInfo)
51335141
if err != nil {
@@ -5142,6 +5150,9 @@ func TestIntegration_AdminLogicalView(t *testing.T) {
51425150
if got, want := lvInfo.Query, newLogicalViewInfo.Query; got != want {
51435151
t.Errorf("LogicalView Query: %q, want: %q", got, want)
51445152
}
5153+
if got, want := lvInfo.DeletionProtection, newLogicalViewInfo.DeletionProtection; got != want {
5154+
t.Errorf("LogicalView DeletionProtection: %v, want: %v", got, want)
5155+
}
51455156

51465157
// Delete logical view
51475158
if err = instanceAdminClient.DeleteLogicalView(ctx, testEnv.Config().Instance, logicalView); err != nil {

0 commit comments

Comments
 (0)