pg_examiner 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/spec/schema_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe PGExaminer do
@@ -49,18 +51,18 @@ describe PGExaminer do
49
51
  c.should == c
50
52
 
51
53
  a.diff(a).should == {}
52
- a.diff(b).should == {schemas: {added: ['test_schema_b'], removed: ['test_schema_a']}}
53
- a.diff(c).should == {schemas: {removed: ['test_schema_a']}}
54
- b.diff(a).should == {schemas: {added: ['test_schema_a'], removed: ['test_schema_b']}}
54
+ a.diff(b).should == {"schemas" => {"added" => ['test_schema_b'], "removed" => ['test_schema_a']}}
55
+ a.diff(c).should == {"schemas" => {"removed" => ['test_schema_a']}}
56
+ b.diff(a).should == {"schemas" => {"added" => ['test_schema_a'], "removed" => ['test_schema_b']}}
55
57
  b.diff(b).should == {}
56
- b.diff(c).should == {schemas: {removed: ['test_schema_b']}}
57
- c.diff(a).should == {schemas: {added: ['test_schema_a']}}
58
- c.diff(b).should == {schemas: {added: ['test_schema_b']}}
58
+ b.diff(c).should == {"schemas" => {"removed" => ['test_schema_b']}}
59
+ c.diff(a).should == {"schemas" => {"added" => ['test_schema_a']}}
60
+ c.diff(b).should == {"schemas" => {"added" => ['test_schema_b']}}
59
61
  c.diff(c).should == {}
60
62
  end
61
63
 
62
64
  it "should be able to compare the contents of different schemas" do
63
- a = examine <<-SQL, :schema1
65
+ a = examine <<-SQL, "schema1"
64
66
  CREATE SCHEMA schema1;
65
67
  CREATE TABLE schema1.test_table (
66
68
  a integer,
@@ -68,7 +70,7 @@ describe PGExaminer do
68
70
  );
69
71
  SQL
70
72
 
71
- b = examine <<-SQL, :schema2
73
+ b = examine <<-SQL, "schema2"
72
74
  CREATE SCHEMA schema2;
73
75
  CREATE TABLE schema2.test_table (
74
76
  a integer,
@@ -76,7 +78,7 @@ describe PGExaminer do
76
78
  );
77
79
  SQL
78
80
 
79
- c = examine <<-SQL, :schema2
81
+ c = examine <<-SQL, "schema2"
80
82
  CREATE SCHEMA schema2;
81
83
  CREATE TABLE schema2.test_table_2 (
82
84
  a integer,
@@ -84,7 +86,7 @@ describe PGExaminer do
84
86
  );
85
87
  SQL
86
88
 
87
- d = examine <<-SQL, :schema2
89
+ d = examine <<-SQL, "schema2"
88
90
  CREATE SCHEMA schema2;
89
91
  SQL
90
92
 
@@ -93,7 +95,7 @@ describe PGExaminer do
93
95
  b.diff(a).should == {}
94
96
 
95
97
  a.should_not == c
96
- a.diff(c).should == {tables: {added: ['test_table_2'], removed: ['test_table']}}
97
- a.diff(d).should == {tables: {removed: ['test_table']}}
98
+ a.diff(c).should == {"tables" => {"added" => ['test_table_2'], "removed" => ['test_table']}}
99
+ a.diff(d).should == {"tables" => {"removed" => ['test_table']}}
98
100
  end
99
101
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PGExaminer do
6
+ it "should be able to tell when a sequence exists" do
7
+ a = examine ""
8
+
9
+ b = examine <<-SQL
10
+ CREATE SEQUENCE my_sequence;
11
+ SQL
12
+
13
+ c = examine <<-SQL
14
+ CREATE SEQUENCE my_other_sequence;
15
+ SQL
16
+
17
+ a.diff(b).should == {"schemas"=>{"public"=>{"sequences"=>{"added"=>["my_sequence"]}}}}
18
+ a.diff(c).should == {"schemas"=>{"public"=>{"sequences"=>{"added"=>["my_other_sequence"]}}}}
19
+ b.diff(c).should == {"schemas"=>{"public"=>{"sequences"=>{"added"=>["my_other_sequence"], "removed"=>["my_sequence"]}}}}
20
+ end
21
+
22
+ it "should be able to tell when a table is associated with an index" do
23
+ a = examine <<-SQL
24
+ CREATE TABLE test_table (
25
+ id serial
26
+ )
27
+ SQL
28
+
29
+ b = examine <<-SQL
30
+ CREATE SEQUENCE test_table_id_seq;
31
+
32
+ CREATE TABLE test_table (
33
+ id integer NOT NULL default nextval('test_table_id_seq')
34
+ )
35
+ SQL
36
+
37
+ a.diff(b).should == {}
38
+
39
+ # TODO: Add concept of the column owning the sequence?
40
+ end
41
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'pg'
3
5
  require 'pry'
data/spec/table_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe PGExaminer do
@@ -21,7 +23,7 @@ describe PGExaminer do
21
23
  table.should be_an_instance_of PGExaminer::Result::Table
22
24
  table.columns.length.should == 2
23
25
 
24
- id, body = table.columns # Returned in proper ordering
26
+ body, id = table.columns # Returned in alphabetical ordering
25
27
 
26
28
  id.should be_an_instance_of PGExaminer::Result::Column
27
29
  id.name.should == 'id'
@@ -85,7 +87,7 @@ describe PGExaminer do
85
87
 
86
88
  a.should_not == b
87
89
 
88
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{:added=>["test_table_b"], :removed=>["test_table_a"]}}}}
90
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"added"=>["test_table_b"], "removed"=>["test_table_a"]}, "sequences"=>{"added"=>["test_table_b_id_seq"], "removed"=>["test_table_a_id_seq"]}}}}
89
91
  end
90
92
 
91
93
  it "should consider tables with current columns in the same order equivalent" do
@@ -136,9 +138,7 @@ describe PGExaminer do
136
138
  )
137
139
  SQL
138
140
 
139
- a.should_not == b
140
-
141
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{}}}}}}
141
+ a.should == b
142
142
  end
143
143
 
144
144
  it "should consider tables with columns of differing types not equivalent" do
@@ -163,8 +163,8 @@ describe PGExaminer do
163
163
  a.should_not == b
164
164
  a.should_not == c
165
165
 
166
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{"a"=>{:type=>{"int4"=>"text"}}}}}}}}
167
- a.diff(c).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{"a"=>{:default=>{nil=>"5"}}}}}}}}
166
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"columns"=>{"a"=>{"type"=>{"int4"=>"text"}}}}}}}}
167
+ a.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"columns"=>{"a"=>{"default"=>{nil=>"5"}}}}}}}}
168
168
  end
169
169
 
170
170
  it "should consider array types as different from scalar types" do
@@ -182,7 +182,7 @@ describe PGExaminer do
182
182
 
183
183
  a.should_not == b
184
184
 
185
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{"a"=>{:attndims=>{"0"=>"1"}, :type=>{"int4"=>"_int4"}}}}}}}}
185
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"columns"=>{"a"=>{"array dimensionality"=>{"0"=>"1"}, "type"=>{"int4"=>"_int4"}}}}}}}}
186
186
  end
187
187
 
188
188
  it "should consider the presence of not-null constraints" do
@@ -200,7 +200,7 @@ describe PGExaminer do
200
200
 
201
201
  a.should_not == b
202
202
 
203
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{"a"=>{:attnotnull=>{"f"=>"t"}}}}}}}}
203
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"columns"=>{"a"=>{"column is marked not-null"=>{"f"=>"t"}}}}}}}}
204
204
  end
205
205
 
206
206
  it "should consider the presence of type-specific data" do
@@ -218,7 +218,7 @@ describe PGExaminer do
218
218
 
219
219
  a.should_not == b
220
220
 
221
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:columns=>{"a"=>{:atttypmod=>{"53"=>"54"}}}}}}}}
221
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"columns"=>{"a"=>{"datatype information (atttypmod)"=>{"53"=>"54"}}}}}}}}
222
222
  end
223
223
 
224
224
  it "should consider unlogged and temporary tables as different from permanent tables" do
@@ -244,9 +244,9 @@ describe PGExaminer do
244
244
  a.should_not == c
245
245
  b.should_not == c
246
246
 
247
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:relpersistence=>{"p"=>"u"}}}}}}
248
- a.diff(c).should == {:schemas=>{"public"=>{:tables=>{:removed=>["test_table"]}}}}
249
- b.diff(c).should == {:schemas=>{"public"=>{:tables=>{:removed=>["test_table"]}}}}
247
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"table type (relpersistence)"=>{"p"=>"u"}}}}}}
248
+ a.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"removed"=>["test_table"]}}}}
249
+ b.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"removed"=>["test_table"]}}}}
250
250
  end
251
251
 
252
252
  it "should consider additional specified options when comparing tables" do
@@ -282,8 +282,8 @@ describe PGExaminer do
282
282
  b.should_not == c
283
283
  c.should == d
284
284
 
285
- a.diff(b).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:reloptions=>{nil=>"{fillfactor=90}"}}}}}}
286
- a.diff(c).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:reloptions=>{nil=>"{fillfactor=70}"}}}}}}
287
- b.diff(c).should == {:schemas=>{"public"=>{:tables=>{"test_table"=>{:reloptions=>{"{fillfactor=90}"=>"{fillfactor=70}"}}}}}}
285
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"table options"=>{nil=>"{fillfactor=90}"}}}}}}
286
+ a.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"table options"=>{nil=>"{fillfactor=70}"}}}}}}
287
+ b.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"table options"=>{"{fillfactor=90}"=>"{fillfactor=70}"}}}}}}
288
288
  end
289
289
  end
@@ -0,0 +1,310 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PGExaminer do
6
+ it "should be able to differentiate between triggers by their names" do
7
+ a = examine <<-SQL
8
+ CREATE TABLE test_table (
9
+ a integer
10
+ );
11
+
12
+ CREATE FUNCTION func() RETURNS trigger AS $$
13
+ BEGIN
14
+ NEW.a = 56;
15
+ RETURN NEW;
16
+ END;
17
+ $$
18
+ LANGUAGE plpgsql;
19
+
20
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
21
+ SQL
22
+
23
+ b = examine <<-SQL
24
+ CREATE TABLE test_table (
25
+ a integer
26
+ );
27
+
28
+ CREATE FUNCTION func() RETURNS trigger AS $$
29
+ BEGIN
30
+ NEW.a = 56;
31
+ RETURN NEW;
32
+ END;
33
+ $$
34
+ LANGUAGE plpgsql;
35
+
36
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
37
+ SQL
38
+
39
+ c = examine <<-SQL
40
+ CREATE TABLE test_table (
41
+ a integer
42
+ );
43
+
44
+ CREATE FUNCTION func() RETURNS trigger AS $$
45
+ BEGIN
46
+ NEW.a = 56;
47
+ RETURN NEW;
48
+ END;
49
+ $$
50
+ LANGUAGE plpgsql;
51
+
52
+ CREATE TRIGGER trig2 BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
53
+ SQL
54
+
55
+ a.should == b
56
+ a.should_not == c
57
+ b.should_not == c
58
+
59
+ a.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"triggers"=>{"added"=>["trig2"], "removed"=>["trig"]}}}}}}
60
+ b.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"triggers"=>{"added"=>["trig2"], "removed"=>["trig"]}}}}}}
61
+ end
62
+
63
+ it "should be able to differentiate between triggers by their parent tables" do
64
+ a = examine <<-SQL
65
+ CREATE TABLE test_table_a (
66
+ a integer
67
+ );
68
+
69
+ CREATE TABLE test_table_b (
70
+ a integer
71
+ );
72
+
73
+ CREATE FUNCTION func() RETURNS trigger AS $$
74
+ BEGIN
75
+ NEW.a = 56;
76
+ RETURN NEW;
77
+ END;
78
+ $$
79
+ LANGUAGE plpgsql;
80
+
81
+ CREATE TRIGGER trig BEFORE INSERT ON test_table_a FOR EACH ROW EXECUTE PROCEDURE func();
82
+ SQL
83
+
84
+ b = examine <<-SQL
85
+ CREATE TABLE test_table_a (
86
+ a integer
87
+ );
88
+
89
+ CREATE TABLE test_table_b (
90
+ a integer
91
+ );
92
+
93
+ CREATE FUNCTION func() RETURNS trigger AS $$
94
+ BEGIN
95
+ NEW.a = 56;
96
+ RETURN NEW;
97
+ END;
98
+ $$
99
+ LANGUAGE plpgsql;
100
+
101
+ CREATE TRIGGER trig BEFORE INSERT ON test_table_b FOR EACH ROW EXECUTE PROCEDURE func();
102
+ SQL
103
+
104
+ a.should_not == b
105
+
106
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table_a"=>{"triggers"=>{"removed"=>["trig"]}}, "test_table_b"=>{"triggers"=>{"added"=>["trig"]}}}}}}
107
+ end
108
+
109
+ it "should be able to differentiate between triggers by their associated functions" do
110
+ a = examine <<-SQL
111
+ CREATE TABLE test_table (
112
+ a integer
113
+ );
114
+
115
+ CREATE FUNCTION func1() RETURNS trigger AS $$
116
+ BEGIN
117
+ NEW.a = 56;
118
+ RETURN NEW;
119
+ END;
120
+ $$
121
+ LANGUAGE plpgsql;
122
+
123
+ CREATE FUNCTION func2() RETURNS trigger AS $$
124
+ BEGIN
125
+ NEW.a = 56;
126
+ RETURN NEW;
127
+ END;
128
+ $$
129
+ LANGUAGE plpgsql;
130
+
131
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func1();
132
+ SQL
133
+
134
+ b = examine <<-SQL
135
+ CREATE TABLE test_table (
136
+ a integer
137
+ );
138
+
139
+ CREATE FUNCTION func1() RETURNS trigger AS $$
140
+ BEGIN
141
+ NEW.a = 56;
142
+ RETURN NEW;
143
+ END;
144
+ $$
145
+ LANGUAGE plpgsql;
146
+
147
+ CREATE FUNCTION func2() RETURNS trigger AS $$
148
+ BEGIN
149
+ NEW.a = 56;
150
+ RETURN NEW;
151
+ END;
152
+ $$
153
+ LANGUAGE plpgsql;
154
+
155
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func2();
156
+ SQL
157
+
158
+ a.should_not == b
159
+
160
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"triggers"=>{"trig"=>{"function"=>{"func1"=>"func2"}}}}}}}}
161
+ end
162
+
163
+ it "should be able to differentiate between triggers by their firing conditions" do
164
+ a = examine <<-SQL
165
+ CREATE TABLE test_table (
166
+ a integer
167
+ );
168
+
169
+ CREATE FUNCTION func() RETURNS trigger AS $$
170
+ BEGIN
171
+ NEW.a = 56;
172
+ RETURN NEW;
173
+ END;
174
+ $$
175
+ LANGUAGE plpgsql;
176
+
177
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
178
+ SQL
179
+
180
+ b = examine <<-SQL
181
+ CREATE TABLE test_table (
182
+ a integer
183
+ );
184
+
185
+ CREATE FUNCTION func() RETURNS trigger AS $$
186
+ BEGIN
187
+ NEW.a = 56;
188
+ RETURN NEW;
189
+ END;
190
+ $$
191
+ LANGUAGE plpgsql;
192
+
193
+ CREATE TRIGGER trig BEFORE UPDATE ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
194
+ SQL
195
+
196
+ c = examine <<-SQL
197
+ CREATE TABLE test_table (
198
+ a integer
199
+ );
200
+
201
+ CREATE FUNCTION func() RETURNS trigger AS $$
202
+ BEGIN
203
+ NEW.a = 56;
204
+ RETURN NEW;
205
+ END;
206
+ $$
207
+ LANGUAGE plpgsql;
208
+
209
+ CREATE TRIGGER trig BEFORE DELETE ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
210
+ SQL
211
+
212
+ a.should_not == b
213
+ a.should_not == c
214
+ b.should_not == c
215
+
216
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"triggers"=>{"trig"=>{"trigger firing conditions (tgtype)"=>{"7"=>"19"}}}}}}}}
217
+ end
218
+
219
+ it "should be able to differentiate between normal triggers and constraint triggers" do
220
+ a = examine <<-SQL
221
+ CREATE TABLE test_table (
222
+ a integer
223
+ );
224
+
225
+ CREATE FUNCTION func() RETURNS trigger AS $$
226
+ BEGIN
227
+ NEW.a = 56;
228
+ RETURN NEW;
229
+ END;
230
+ $$
231
+ LANGUAGE plpgsql;
232
+
233
+ CREATE TRIGGER trig AFTER INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
234
+ SQL
235
+
236
+ b = examine <<-SQL
237
+ CREATE TABLE test_table (
238
+ a integer
239
+ );
240
+
241
+ CREATE FUNCTION func() RETURNS trigger AS $$
242
+ BEGIN
243
+ NEW.a = 56;
244
+ RETURN NEW;
245
+ END;
246
+ $$
247
+ LANGUAGE plpgsql;
248
+
249
+ CREATE CONSTRAINT TRIGGER trig AFTER INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
250
+ SQL
251
+
252
+ a.should_not == b
253
+
254
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"constraints"=>{"added"=>["trig"]}}}}}}
255
+ end
256
+
257
+ it "should be able to differentiate between deferrable and non-deferrable constraint triggers" do
258
+ a = examine <<-SQL
259
+ CREATE TABLE test_table (
260
+ a integer
261
+ );
262
+
263
+ CREATE FUNCTION func() RETURNS trigger AS $$
264
+ BEGIN
265
+ NEW.a = 56;
266
+ RETURN NEW;
267
+ END;
268
+ $$
269
+ LANGUAGE plpgsql;
270
+
271
+ CREATE CONSTRAINT TRIGGER trig AFTER INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
272
+ SQL
273
+
274
+ b = examine <<-SQL
275
+ CREATE TABLE test_table (
276
+ a integer
277
+ );
278
+
279
+ CREATE FUNCTION func() RETURNS trigger AS $$
280
+ BEGIN
281
+ NEW.a = 56;
282
+ RETURN NEW;
283
+ END;
284
+ $$
285
+ LANGUAGE plpgsql;
286
+
287
+ CREATE CONSTRAINT TRIGGER trig AFTER INSERT ON test_table DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE func();
288
+ SQL
289
+
290
+ c = examine <<-SQL
291
+ CREATE TABLE test_table (
292
+ a integer
293
+ );
294
+
295
+ CREATE FUNCTION func() RETURNS trigger AS $$
296
+ BEGIN
297
+ NEW.a = 56;
298
+ RETURN NEW;
299
+ END;
300
+ $$
301
+ LANGUAGE plpgsql;
302
+
303
+ CREATE CONSTRAINT TRIGGER trig AFTER INSERT ON test_table DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE func();
304
+ SQL
305
+
306
+ a.diff(b).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"constraints"=>{"trig"=>{"constraint definition"=>{"TRIGGER"=>"TRIGGER DEFERRABLE"}}}}}}}}
307
+ a.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"constraints"=>{"trig"=>{"constraint definition"=>{"TRIGGER"=>"TRIGGER DEFERRABLE INITIALLY DEFERRED"}}}}}}}}
308
+ b.diff(c).should == {"schemas"=>{"public"=>{"tables"=>{"test_table"=>{"constraints"=>{"trig"=>{"constraint definition"=>{"TRIGGER DEFERRABLE"=>"TRIGGER DEFERRABLE INITIALLY DEFERRED"}}}}}}}}
309
+ end
310
+ end