Skip to content

Commit 773fc66

Browse files
committed
sql/postgres: support partial indexes
1 parent 92b33f2 commit 773fc66

File tree

6 files changed

+79
-5
lines changed

6 files changed

+79
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
apply 1.hcl
2+
cmpshow users 1.sql
3+
4+
apply 2.hcl
5+
cmpshow users 2.sql
6+
7+
-- 1.hcl --
8+
schema "$db" {}
9+
10+
table "users" {
11+
schema = schema.$db
12+
column "name" {
13+
null = false
14+
type = text
15+
}
16+
column "active" {
17+
null = true
18+
type = boolean
19+
}
20+
index "users_name" {
21+
columns = [column.name]
22+
where = "active"
23+
}
24+
}
25+
26+
-- 1.sql --
27+
Table "script_index_partial.users"
28+
Column | Type | Collation | Nullable | Default
29+
--------+---------+-----------+----------+---------
30+
name | text | | not null |
31+
active | boolean | | |
32+
Indexes:
33+
"users_name" btree (name) WHERE active
34+
35+
36+
-- 2.hcl --
37+
schema "$db" {}
38+
39+
table "users" {
40+
schema = schema.$db
41+
column "name" {
42+
null = false
43+
type = text
44+
}
45+
column "active" {
46+
null = true
47+
type = boolean
48+
}
49+
index "users_name" {
50+
columns = [column.name]
51+
where = "active AND name <> ''"
52+
}
53+
}
54+
55+
-- 2.sql --
56+
Table "script_index_partial.users"
57+
Column | Type | Collation | Nullable | Default
58+
--------+---------+-----------+----------+---------
59+
name | text | | not null |
60+
active | boolean | | |
61+
Indexes:
62+
"users_name" btree (name) WHERE active AND name <> ''::text

sql/postgres/diff.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,7 @@ func (*diff) IndexAttrChanged(from, to []schema.Attr) bool {
115115
return true
116116
}
117117
var p1, p2 IndexPredicate
118-
if sqlx.Has(from, &p1) != sqlx.Has(to, &p2) || p1.P != p2.P {
119-
return true
120-
}
121-
return false
118+
return sqlx.Has(from, &p1) != sqlx.Has(to, &p2) || (p1.P != p2.P && p1.P != sqlx.MayWrap(p2.P))
122119
}
123120

124121
// IndexPartAttrChanged reports if the index-part attributes were changed.

sql/postgres/diff_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,13 @@ func TestDiff_TableDiff(t *testing.T) {
190190
{Name: "c1_index", Unique: true, Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[0]}}},
191191
{Name: "c2_unique", Unique: true, Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[1]}}},
192192
{Name: "c3_predicate", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[1]}}},
193+
{Name: "c4_predicate", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[1]}}, Attrs: []schema.Attr{&IndexPredicate{P: "(c4 <> NULL)"}}},
193194
}
194195
to.Indexes = []*schema.Index{
195196
{Name: "c1_index", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[0]}}},
196197
{Name: "c3_unique", Unique: true, Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: to.Columns[1]}}},
197198
{Name: "c3_predicate", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[1]}}, Attrs: []schema.Attr{&IndexPredicate{P: "c3 <> NULL"}}},
199+
{Name: "c4_predicate", Table: from, Parts: []*schema.IndexPart{{SeqNo: 1, C: from.Columns[1]}}, Attrs: []schema.Attr{&IndexPredicate{P: "c4 <> NULL"}}},
198200
}
199201
return testcase{
200202
name: "indexes",

sql/postgres/migrate_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ func TestPlanChanges(t *testing.T) {
262262
},
263263
Attrs: []schema.Attr{
264264
&schema.Comment{Text: "comment"},
265+
&IndexPredicate{P: "success"},
265266
},
266267
},
267268
},
@@ -288,7 +289,7 @@ func TestPlanChanges(t *testing.T) {
288289
Reverse: `ALTER TABLE "users" DROP COLUMN "name", DROP CONSTRAINT "name_not_empty", ADD CONSTRAINT "id_nonzero" CHECK ("id" <> 0), DROP CONSTRAINT "id_iseven", ADD CONSTRAINT "id_iseven" CHECK ("id" % 2 = 0)`,
289290
},
290291
{
291-
Cmd: `CREATE INDEX "id_key" ON "users" ("id" DESC)`,
292+
Cmd: `CREATE INDEX "id_key" ON "users" ("id" DESC) WHERE success`,
292293
Reverse: `DROP INDEX "id_key"`,
293294
},
294295
{

sql/postgres/sqlspec.go

+10
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@ func convertIndex(spec *sqlspec.Index, parent *schema.Table) (*schema.Index, err
245245
}
246246
idx.Attrs = append(idx.Attrs, &IndexType{T: t})
247247
}
248+
if attr, ok := spec.Attr("where"); ok {
249+
p, err := attr.String()
250+
if err != nil {
251+
return nil, err
252+
}
253+
idx.Attrs = append(idx.Attrs, &IndexPredicate{P: p})
254+
}
248255
return idx, nil
249256
}
250257

@@ -367,6 +374,9 @@ func indexSpec(idx *schema.Index) (*sqlspec.Index, error) {
367374
if i := (IndexType{}); sqlx.Has(idx.Attrs, &i) && i.T != IndexTypeBTree {
368375
spec.Extra.Attrs = append(spec.Extra.Attrs, specutil.VarAttr("type", strings.ToUpper(i.T)))
369376
}
377+
if i := (IndexPredicate{}); sqlx.Has(idx.Attrs, &i) && i.P != "" {
378+
spec.Extra.Attrs = append(spec.Extra.Attrs, specutil.VarAttr("where", i.P))
379+
}
370380
return spec, nil
371381
}
372382

sql/postgres/sqlspec_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ table "table" {
5656
table.table.column.col,
5757
table.table.column.age,
5858
]
59+
where = "active"
5960
comment = "index comment"
6061
}
6162
foreign_key "accounts" {
@@ -234,6 +235,7 @@ enum "account_type" {
234235
Attrs: []schema.Attr{
235236
&schema.Comment{Text: "index comment"},
236237
&IndexType{T: IndexTypeHash},
238+
&IndexPredicate{P: "active"},
237239
},
238240
},
239241
}

0 commit comments

Comments
 (0)