Skip to content

Commit d43ce93

Browse files
sql/ydb: added index diff logic
1 parent 9920761 commit d43ce93

File tree

2 files changed

+191
-3
lines changed

2 files changed

+191
-3
lines changed

sql/ydb/diff.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,36 @@ func (d *diff) defaultChanged(from *schema.Column, to *schema.Column) bool {
128128
}
129129

130130
// IndexAttrChanged reports if the index attributes were changed.
131-
func (*diff) IndexAttrChanged(_, _ []schema.Attr) bool {
132-
return false // unimplemented.
131+
func (*diff) IndexAttrChanged(from, to []schema.Attr) bool {
132+
var fromA, toA IndexAttributes
133+
fromHas, toHas := sqlx.Has(from, &fromA), sqlx.Has(to, &toA)
134+
if fromHas != toHas {
135+
return true
136+
}
137+
if !fromHas {
138+
return false
139+
}
140+
141+
if fromA.Async != toA.Async {
142+
return true
143+
}
144+
145+
if len(fromA.CoverColumns) != len(toA.CoverColumns) {
146+
return true
147+
}
148+
149+
for i := range fromA.CoverColumns {
150+
if fromA.CoverColumns[i].Name != toA.CoverColumns[i].Name {
151+
return true
152+
}
153+
}
154+
return false
133155
}
134156

135157
// IndexPartAttrChanged reports if the index-part attributes were changed.
136158
func (*diff) IndexPartAttrChanged(_, _ *schema.Index, _ int) bool {
137-
return false // unimplemented.
159+
// YDB doesn't have per-part attributes like collation, prefix, or operator classes.
160+
return false
138161
}
139162

140163
// IsGeneratedIndexName reports if the index name was generated by the database.

sql/ydb/diff_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,70 @@ func TestDiff_TableDiff(t *testing.T) {
241241
},
242242
}
243243
}(),
244+
func() testcase {
245+
var (
246+
from = &schema.Table{
247+
Name: "users",
248+
Schema: &schema.Schema{Name: "local"},
249+
Columns: []*schema.Column{
250+
{Name: "id", Type: &schema.ColumnType{Type: &schema.IntegerType{T: TypeInt32}}},
251+
},
252+
}
253+
to = &schema.Table{
254+
Name: "users",
255+
Columns: []*schema.Column{
256+
{Name: "id", Type: &schema.ColumnType{Type: &schema.IntegerType{T: TypeInt32}}},
257+
},
258+
}
259+
)
260+
from.Indexes = []*schema.Index{
261+
{Name: "idx_id", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[0]}}, Attrs: []schema.Attr{&IndexAttributes{Async: false}}},
262+
}
263+
to.Indexes = []*schema.Index{
264+
{Name: "idx_id", Table: to, Parts: []*schema.IndexPart{{SeqNo: 1, C: to.Columns[0]}}, Attrs: []schema.Attr{&IndexAttributes{Async: true}}},
265+
}
266+
return testcase{
267+
name: "modify index async",
268+
from: from,
269+
to: to,
270+
wantChanges: []schema.Change{
271+
&schema.ModifyIndex{From: from.Indexes[0], To: to.Indexes[0], Change: schema.ChangeAttr},
272+
},
273+
}
274+
}(),
275+
func() testcase {
276+
var (
277+
from = &schema.Table{
278+
Name: "users",
279+
Schema: &schema.Schema{Name: "local"},
280+
Columns: []*schema.Column{
281+
{Name: "id", Type: &schema.ColumnType{Type: &schema.IntegerType{T: TypeInt32}}},
282+
{Name: "name", Type: &schema.ColumnType{Type: &schema.StringType{T: TypeUtf8}}},
283+
},
284+
}
285+
to = &schema.Table{
286+
Name: "users",
287+
Columns: []*schema.Column{
288+
{Name: "id", Type: &schema.ColumnType{Type: &schema.IntegerType{T: TypeInt32}}},
289+
{Name: "name", Type: &schema.ColumnType{Type: &schema.StringType{T: TypeUtf8}}},
290+
},
291+
}
292+
)
293+
from.Indexes = []*schema.Index{
294+
{Name: "idx_id", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[0]}}},
295+
}
296+
to.Indexes = []*schema.Index{
297+
{Name: "idx_id", Table: to, Parts: []*schema.IndexPart{{SeqNo: 1, C: to.Columns[0]}}, Attrs: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{to.Columns[1]}}}},
298+
}
299+
return testcase{
300+
name: "modify index add cover columns",
301+
from: from,
302+
to: to,
303+
wantChanges: []schema.Change{
304+
&schema.ModifyIndex{From: from.Indexes[0], To: to.Indexes[0], Change: schema.ChangeAttr},
305+
},
306+
}
307+
}(),
244308
}
245309

246310
for _, tt := range tests {
@@ -406,3 +470,104 @@ func TestDiff_DefaultChanged(t *testing.T) {
406470
})
407471
}
408472
}
473+
474+
func TestDiff_IndexAttrChanged(t *testing.T) {
475+
d := &diff{conn: &conn{}}
476+
477+
col1 := &schema.Column{Name: "name"}
478+
col2 := &schema.Column{Name: "email"}
479+
480+
tests := []struct {
481+
name string
482+
from []schema.Attr
483+
to []schema.Attr
484+
changed bool
485+
}{
486+
{
487+
name: "no attributes",
488+
from: nil,
489+
to: nil,
490+
},
491+
{
492+
name: "add async attribute",
493+
from: nil,
494+
to: []schema.Attr{&IndexAttributes{Async: true}},
495+
changed: true,
496+
},
497+
{
498+
name: "remove async attribute",
499+
from: []schema.Attr{&IndexAttributes{Async: true}},
500+
to: nil,
501+
changed: true,
502+
},
503+
{
504+
name: "same async false",
505+
from: []schema.Attr{&IndexAttributes{Async: false}},
506+
to: []schema.Attr{&IndexAttributes{Async: false}},
507+
},
508+
{
509+
name: "same async true",
510+
from: []schema.Attr{&IndexAttributes{Async: true}},
511+
to: []schema.Attr{&IndexAttributes{Async: true}},
512+
},
513+
{
514+
name: "change async false to true",
515+
from: []schema.Attr{&IndexAttributes{Async: false}},
516+
to: []schema.Attr{&IndexAttributes{Async: true}},
517+
changed: true,
518+
},
519+
{
520+
name: "change async true to false",
521+
from: []schema.Attr{&IndexAttributes{Async: true}},
522+
to: []schema.Attr{&IndexAttributes{Async: false}},
523+
changed: true,
524+
},
525+
{
526+
name: "same cover columns",
527+
from: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
528+
to: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
529+
},
530+
{
531+
name: "add cover columns",
532+
from: []schema.Attr{&IndexAttributes{}},
533+
to: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
534+
changed: true,
535+
},
536+
{
537+
name: "remove cover columns",
538+
from: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
539+
to: []schema.Attr{&IndexAttributes{}},
540+
changed: true,
541+
},
542+
{
543+
name: "different cover columns count",
544+
from: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
545+
to: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1, col2}}},
546+
changed: true,
547+
},
548+
{
549+
name: "different cover column names",
550+
from: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col1}}},
551+
to: []schema.Attr{&IndexAttributes{CoverColumns: []*schema.Column{col2}}},
552+
changed: true,
553+
},
554+
{
555+
name: "same async and cover columns",
556+
from: []schema.Attr{&IndexAttributes{Async: true, CoverColumns: []*schema.Column{col1, col2}}},
557+
to: []schema.Attr{&IndexAttributes{Async: true, CoverColumns: []*schema.Column{col1, col2}}},
558+
},
559+
{
560+
name: "same cover columns different async",
561+
from: []schema.Attr{&IndexAttributes{Async: false, CoverColumns: []*schema.Column{col1}}},
562+
to: []schema.Attr{&IndexAttributes{Async: true, CoverColumns: []*schema.Column{col1}}},
563+
changed: true,
564+
},
565+
}
566+
567+
for _, tt := range tests {
568+
t.Run(tt.name, func(t *testing.T) {
569+
changed := d.IndexAttrChanged(tt.from, tt.to)
570+
require.Equal(t, tt.changed, changed)
571+
})
572+
}
573+
}

0 commit comments

Comments
 (0)