11package main
22
33import "fmt"
4-
4+ import "database/sql"
5+ import "github.com/joncrlsn/pgutil"
56
67// ColumnSchema holds a channel streaming column data from one of the databases as well as
78// a reference to the current row of data we're viewing.
@@ -10,15 +11,16 @@ import "fmt"
1011type ColumnSchema struct {
1112 channel chan map [string ]string
1213 row map [string ]string
14+ done bool
1315}
1416
15- // NextRow reads from the channel and tells you whether or not there might be more rows
16- func (c * ColumnSchema ) NextRow (more bool ) bool {
17+ // NextRow reads from the channel and tells you if there are (probably) more or not
18+ func (c * ColumnSchema ) NextRow () bool {
1719 c .row = <- c .channel
18- if ! more || len (c .row ) == 0 {
19- return false
20+ if len (c .row ) == 0 {
21+ c . done = true
2022 }
21- return true
23+ return ! c . done
2224}
2325
2426// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
@@ -68,7 +70,43 @@ func (c ColumnSchema) Change(obj interface{}) {
6870 if ! ok {
6971 fmt .Println ("Error!!!, change needs a ColumnSchema instance" , c2 )
7072 }
71- // fmt.Printf("Changes? ")
73+
74+ // Detect column type change (mostly varchar length, or number size increase) (integer to/from bigint is OK)
75+ if c .row ["data_type" ] == c2 .row ["data_type" ] {
76+ if c .row ["data_type" ] == "character varying" {
77+ if c .row ["character_maximum_length" ] != c2 .row ["character_maximum_length" ] {
78+ if c .row ["character_maximum_length" ] < c2 .row ["character_maximum_length" ] {
79+ fmt .Println ("-- WARNING: The next statement will shorten a character varying column." )
80+ }
81+ fmt .Printf ("ALTER TABLE %s ALTER COLUMN %s TYPE character varying(%s);\n " , c .row ["table_name" ], c .row ["column_name" ], c .row ["character_maximum_length" ])
82+ }
83+ }
84+ }
85+
86+ // TODO: Code and test a column change from integer to bigint
87+ if c .row ["data_type" ] != c2 .row ["data_type" ] {
88+ fmt .Printf ("-- WARNING: This program does not (yet) handle type changes (%s to %s).\n " , c2 .row ["data_type" ], c .row ["data_type" ])
89+ }
90+
91+ // Detect column default change (or added, dropped)
92+ if c .row ["column_default" ] == "null" {
93+ if c .row ["column_default" ] != "null" {
94+ fmt .Printf ("ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT;\n " , c .row ["table_name" ], c .row ["column_name" ])
95+ }
96+ } else if c .row ["column_default" ] != c2 .row ["column_default" ] {
97+ fmt .Printf ("ALTER TABLE %s ALTER COLUMN %s DEFAULT %s;\n " , c .row ["table_name" ], c .row ["column_name" ], c .row ["column_default" ])
98+ }
99+
100+ if c .row ["is_nullable" ] != c2 .row ["is_nullable" ] {
101+ if c .row ["is_nullable" ] == "YES" {
102+ fmt .Printf ("ALTER TABLE %s ALTER COLUMN DROP NOT NULL" )
103+ } else {
104+ fmt .Printf ("ALTER TABLE %s ALTER COLUMN SET NOT NULL" )
105+ }
106+ }
107+
108+ // TODO Detect not-null and nullable change
109+
72110 // // if changing type
73111 // if c.row["data_type"] == "character varying" {
74112 // // varchar needs a length specified
@@ -90,3 +128,29 @@ func (c ColumnSchema) Change(obj interface{}) {
90128 // fmt.Printf("ALTER TABLE %s ALTER COLUMN %s DROP NOT NULL;\n", c.row["table_name"], c.row["column_name"])
91129 // return "Change"
92130}
131+
132+ /*
133+ * Compare the columns in the two databases
134+ */
135+ func compareColumns (conn1 * sql.DB , conn2 * sql.DB ) {
136+ sql := `
137+ SELECT table_name
138+ , column_name
139+ , data_type
140+ , is_nullable
141+ , column_default
142+ , character_maximum_length
143+ FROM information_schema.columns
144+ WHERE table_schema = 'public'
145+ ORDER by table_name, column_name;`
146+
147+ rowChan1 , _ := pgutil .QueryStrings (conn1 , sql )
148+ rowChan2 , _ := pgutil .QueryStrings (conn2 , sql )
149+
150+ // We have to explicitly type this as Schema for some reason
151+ var schema1 Schema = & ColumnSchema {channel : rowChan1 }
152+ var schema2 Schema = & ColumnSchema {channel : rowChan2 }
153+
154+ // Compare the columns
155+ doDiff (schema1 , schema2 )
156+ }
0 commit comments