Skip to content

Commit bcb3122

Browse files
committed
Added index.go
1 parent b323e4a commit bcb3122

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

index.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package main
2+
3+
import "fmt"
4+
import "database/sql"
5+
import "github.com/joncrlsn/pgutil"
6+
7+
// IndexSchema holds a channel that streams index metadata from one of the databases.
8+
// It also holds a reference to the current row of data we're viewing.
9+
//
10+
// IndexSchema implements the Schema interface defined in pgdiff.go
11+
type IndexSchema struct {
12+
channel chan map[string]string
13+
row map[string]string
14+
done bool
15+
}
16+
17+
// NextRow reads from the channel and tells you if there are (probably) more or not
18+
func (c *IndexSchema) NextRow() bool {
19+
c.row = <-c.channel
20+
if len(c.row) == 0 {
21+
c.done = true
22+
}
23+
return !c.done
24+
}
25+
26+
// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
27+
func (c *IndexSchema) Compare(obj interface{}) int {
28+
c2, ok := obj.(*IndexSchema)
29+
if !ok {
30+
fmt.Println("Error!!!, Change(...) needs a IndexSchema instance", c2)
31+
return +999
32+
}
33+
34+
//fmt.Printf("Comparing %s with %s", c.row["table_name"], c2.row["table_name"])
35+
val := _compareString(c.row["table_name"], c2.row["table_name"])
36+
if val != 0 {
37+
return val
38+
}
39+
40+
val = _compareString(c.row["index_name"], c2.row["index_name"])
41+
return val
42+
}
43+
44+
// Add generates SQL to add the index
45+
func (c IndexSchema) Add() {
46+
uniqueStr := ""
47+
if c.row["unique"] == "true" {
48+
uniqueStr = "UNIQUE "
49+
}
50+
fmt.Printf("CREATE %sINDEX %s ON %s (%s);\n", uniqueStr, c.row["index_name"], c.row["table_name"], c.row["column_names"])
51+
}
52+
53+
// Drop generates SQL to drop the index
54+
func (c IndexSchema) Drop() {
55+
fmt.Printf("DROP INDEX %s;\n", c.row["index_name"])
56+
}
57+
58+
// Change handles the case where the table and index name match, but the details do not
59+
func (c IndexSchema) Change(obj interface{}) {
60+
c2, ok := obj.(*IndexSchema)
61+
if !ok {
62+
fmt.Println("Error!!!, change needs an IndexSchema instance", c2)
63+
}
64+
// No need to do anything, we either drop or add indices
65+
}
66+
67+
/*
68+
* Compare the columns in the two databases
69+
*/
70+
func compareIndexes(conn1 *sql.DB, conn2 *sql.DB) {
71+
sql := `
72+
SELECT
73+
t.relname AS table_name,
74+
i.relname AS index_name,
75+
ix.indisunique AS unique,
76+
array_to_string(array_agg(a.attname), ', ') AS column_names
77+
FROM
78+
pg_index AS ix,
79+
pg_class AS t,
80+
pg_class AS i,
81+
pg_attribute AS a
82+
WHERE
83+
t.oid = ix.indrelid
84+
AND i.oid = ix.indexrelid
85+
AND a.attrelid = t.oid
86+
AND a.attnum = ANY(ix.indkey)
87+
AND t.relkind = 'r'
88+
AND t.relname not like 'pg_%'
89+
GROUP BY t.relname, i.relname, ix.indisunique
90+
ORDER BY t.relname, i.relname, ix.indisunique ASC;`
91+
92+
rowChan1, _ := pgutil.QueryStrings(conn1, sql)
93+
rowChan2, _ := pgutil.QueryStrings(conn2, sql)
94+
95+
// We have to explicitly type this as Schema for some reason
96+
var schema1 Schema = &IndexSchema{channel: rowChan1}
97+
var schema2 Schema = &IndexSchema{channel: rowChan2}
98+
99+
// Compare the columns
100+
doDiff(schema1, schema2)
101+
}

pgdiff.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ func main() {
7474
comparePrimaryKeys(conn1, conn2)
7575
} else if schemaType == "UNIQUE" {
7676
compareUniqueConstraints(conn1, conn2)
77+
} else if schemaType == "INDEX" {
78+
compareIndexes(conn1, conn2)
7779
} else if schemaType == "FOREIGN_KEY" {
7880
compareForeignKeys(conn1, conn2)
7981
} else {

0 commit comments

Comments
 (0)