pg_examiner 0.1.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.
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGExaminer do
4
+ it "should consider constraints when determining table equivalency" do
5
+ a = examine <<-SQL
6
+ CREATE TABLE test_table (
7
+ a integer,
8
+ CONSTRAINT con CHECK (a > 0)
9
+ );
10
+ SQL
11
+
12
+ b = examine <<-SQL
13
+ CREATE TABLE test_table (
14
+ a integer
15
+ );
16
+
17
+ ALTER TABLE test_table ADD CONSTRAINT con CHECK (a > 0);
18
+ SQL
19
+
20
+ c = examine <<-SQL
21
+ CREATE TABLE test_table (
22
+ a integer CONSTRAINT con CHECK (a > 0)
23
+ );
24
+ SQL
25
+
26
+ d = examine <<-SQL
27
+ CREATE TABLE test_table (
28
+ a integer
29
+ );
30
+
31
+ ALTER TABLE test_table ADD CONSTRAINT con_two CHECK (a > 0);
32
+ SQL
33
+
34
+ e = examine <<-SQL
35
+ CREATE TABLE test_table (
36
+ a integer CHECK (a > 0)
37
+ );
38
+ SQL
39
+
40
+ f = examine <<-SQL
41
+ CREATE TABLE test_table (
42
+ a integer
43
+ );
44
+ SQL
45
+
46
+ a.should == b
47
+ a.should == c
48
+ b.should == c
49
+ a.should_not == d
50
+ a.should_not == e
51
+ a.should_not == f
52
+ e.should_not == f
53
+ end
54
+
55
+ it "should consider foreign keys when differentiating between schemas" do
56
+ a = examine <<-SQL
57
+ CREATE TABLE parent (
58
+ int1 integer PRIMARY KEY,
59
+ int2 integer UNIQUE
60
+ );
61
+
62
+ CREATE TABLE child (
63
+ parent_id integer REFERENCES parent
64
+ );
65
+ SQL
66
+
67
+ b = examine <<-SQL
68
+ CREATE TABLE parent (
69
+ int1 integer PRIMARY KEY,
70
+ int2 integer UNIQUE
71
+ );
72
+
73
+ CREATE TABLE child (
74
+ parent_id integer,
75
+ FOREIGN KEY (parent_id) REFERENCES parent
76
+ );
77
+ SQL
78
+
79
+ c = examine <<-SQL
80
+ CREATE TABLE parent (
81
+ int1 integer PRIMARY KEY,
82
+ int2 integer UNIQUE
83
+ );
84
+
85
+ CREATE TABLE child (
86
+ parent_id integer,
87
+ FOREIGN KEY (parent_id) REFERENCES parent (int2)
88
+ );
89
+ SQL
90
+
91
+ d = examine <<-SQL
92
+ CREATE TABLE parent (
93
+ int1 integer PRIMARY KEY,
94
+ int2 integer UNIQUE
95
+ );
96
+
97
+ CREATE TABLE child (
98
+ parent_id integer,
99
+ FOREIGN KEY (parent_id) REFERENCES parent ON UPDATE CASCADE
100
+ );
101
+ SQL
102
+
103
+ e = examine <<-SQL
104
+ CREATE TABLE parent (
105
+ int1 integer PRIMARY KEY,
106
+ int2 integer UNIQUE
107
+ );
108
+
109
+ CREATE TABLE child (
110
+ parent_id integer,
111
+ FOREIGN KEY (parent_id) REFERENCES parent ON DELETE CASCADE
112
+ );
113
+ SQL
114
+
115
+ a.should == b
116
+ a.should_not == c
117
+ b.should_not == c
118
+ b.should_not == d
119
+ b.should_not == e
120
+ d.should_not == e
121
+ end
122
+
123
+ it "should consider constraints when determining table equivalency" do
124
+ a = examine <<-SQL
125
+ CREATE TABLE test_table (
126
+ a integer,
127
+ CONSTRAINT con CHECK (a > 0) NOT VALID
128
+ );
129
+ SQL
130
+
131
+ b = examine <<-SQL
132
+ CREATE TABLE test_table (
133
+ a integer,
134
+ CONSTRAINT con CHECK (a > 0)
135
+ );
136
+ SQL
137
+
138
+ c = examine <<-SQL
139
+ CREATE TABLE test_table (
140
+ a integer,
141
+ CONSTRAINT con CHECK (a > 0) NOT VALID
142
+ );
143
+
144
+ ALTER TABLE test_table VALIDATE CONSTRAINT con;
145
+ SQL
146
+
147
+ a.should_not == b
148
+ a.should_not == c
149
+ b.should == c
150
+ end
151
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGExaminer do
4
+ it "should be able to examine the extensions in the db" do
5
+ result = examine "SELECT 1"
6
+ result.should be_an_instance_of PGExaminer::Result
7
+ result.extensions.map(&:name).should == ['plpgsql']
8
+
9
+ result = examine <<-SQL
10
+ CREATE EXTENSION citext;
11
+ SQL
12
+
13
+ result.extensions.length.should == 2
14
+
15
+ citext, plpgsql = result.extensions # Ordered by name
16
+
17
+ citext.should be_an_instance_of PGExaminer::Result::Extension
18
+ citext.name.should == 'citext'
19
+ citext.schema.should be_an_instance_of PGExaminer::Result::Schema
20
+ citext.schema.name.should == 'public'
21
+
22
+ plpgsql.should be_an_instance_of PGExaminer::Result::Extension
23
+ plpgsql.name.should == 'plpgsql'
24
+ plpgsql.schema.should be nil
25
+ end
26
+ end
@@ -0,0 +1,452 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGExaminer do
4
+ it "should be able to differentiate between functions by their names" do
5
+ a = examine <<-SQL_FUNCTION
6
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
7
+ AS $$
8
+ SELECT one + two
9
+ $$
10
+ LANGUAGE SQL;
11
+ SQL_FUNCTION
12
+
13
+ b = examine <<-SQL_FUNCTION
14
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
15
+ AS $$
16
+ SELECT one + two
17
+ $$
18
+ LANGUAGE SQL;
19
+ SQL_FUNCTION
20
+
21
+ c = examine <<-SQL_FUNCTION
22
+ CREATE FUNCTION add_numbers(one integer, two integer) RETURNS integer
23
+ AS $$
24
+ SELECT one + two
25
+ $$
26
+ LANGUAGE SQL;
27
+ SQL_FUNCTION
28
+
29
+ a.should == b
30
+ a.should_not == c
31
+ b.should_not == c
32
+ end
33
+
34
+ it "should be able to differentiate between functions by their argument types" do
35
+ a = examine <<-SQL_FUNCTION
36
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
37
+ AS $$
38
+ SELECT one + two
39
+ $$
40
+ LANGUAGE SQL;
41
+ SQL_FUNCTION
42
+
43
+ b = examine <<-SQL_FUNCTION
44
+ CREATE FUNCTION add(one integer, two integer, three integer) RETURNS integer
45
+ AS $$
46
+ SELECT one + two
47
+ $$
48
+ LANGUAGE SQL;
49
+ SQL_FUNCTION
50
+
51
+ c = examine <<-SQL_FUNCTION
52
+ CREATE FUNCTION add(one integer, two integer, three integer[]) RETURNS integer
53
+ AS $$
54
+ SELECT one + two
55
+ $$
56
+ LANGUAGE SQL;
57
+ SQL_FUNCTION
58
+
59
+ d = examine <<-SQL_FUNCTION
60
+ CREATE FUNCTION add(one integer, two integer, VARIADIC three integer[]) RETURNS integer
61
+ AS $$
62
+ SELECT one + two
63
+ $$
64
+ LANGUAGE SQL;
65
+ SQL_FUNCTION
66
+
67
+ a.should_not == b
68
+ a.should_not == c
69
+ a.should_not == d
70
+ b.should_not == c
71
+ b.should_not == d
72
+ c.should_not == d
73
+ end
74
+
75
+ it "should be able to differentiate between functions by their argument defaults" do
76
+ a = examine <<-SQL_FUNCTION
77
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
78
+ AS $$
79
+ SELECT one + two
80
+ $$
81
+ LANGUAGE SQL;
82
+ SQL_FUNCTION
83
+
84
+ b = examine <<-SQL_FUNCTION
85
+ CREATE FUNCTION add(one integer, two integer DEFAULT 42) RETURNS integer
86
+ AS $$
87
+ SELECT one + two
88
+ $$
89
+ LANGUAGE SQL;
90
+ SQL_FUNCTION
91
+
92
+ a.should_not == b
93
+ end
94
+
95
+ it "should be able to differentiate between functions by their return types" do
96
+ a = examine <<-SQL_FUNCTION
97
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
98
+ AS $$
99
+ SELECT (one + two)::integer
100
+ $$
101
+ LANGUAGE SQL;
102
+ SQL_FUNCTION
103
+
104
+ b = examine <<-SQL_FUNCTION
105
+ CREATE FUNCTION add(one integer, two integer) RETURNS bigint
106
+ AS $$
107
+ SELECT (one + two)::bigint
108
+ $$
109
+ LANGUAGE SQL;
110
+ SQL_FUNCTION
111
+
112
+ c = examine <<-SQL_FUNCTION
113
+ CREATE FUNCTION add(one integer, two integer) RETURNS smallint
114
+ AS $$
115
+ SELECT (one + two)::smallint
116
+ $$
117
+ LANGUAGE SQL;
118
+ SQL_FUNCTION
119
+
120
+ a.should_not == b
121
+ a.should_not == c
122
+ b.should_not == c
123
+ end
124
+
125
+ it "should be able to differentiate between functions by their languages" do
126
+ a = examine <<-SQL_FUNCTION
127
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
128
+ AS $$
129
+ SELECT one + two
130
+ $$
131
+ LANGUAGE SQL;
132
+ SQL_FUNCTION
133
+
134
+ b = examine <<-SQL_FUNCTION
135
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
136
+ AS $$
137
+ BEGIN
138
+ RETURN one + two;
139
+ END
140
+ $$
141
+ LANGUAGE PLPGSQL;
142
+ SQL_FUNCTION
143
+
144
+ a.should_not == b
145
+ end
146
+
147
+ it "should be able to differentiate between functions by their other flags" do
148
+ a = examine <<-SQL_FUNCTION
149
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
150
+ AS $$
151
+ SELECT one + two
152
+ $$
153
+ LANGUAGE SQL;
154
+ SQL_FUNCTION
155
+
156
+ b = examine <<-SQL_FUNCTION
157
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
158
+ AS $$
159
+ SELECT one + two
160
+ $$
161
+ LANGUAGE SQL
162
+ COST 0.1;
163
+ SQL_FUNCTION
164
+
165
+ c = examine <<-SQL_FUNCTION
166
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
167
+ AS $$
168
+ SELECT one + two
169
+ $$
170
+ LANGUAGE SQL
171
+ RETURNS NULL ON NULL INPUT;
172
+ SQL_FUNCTION
173
+
174
+ d = examine <<-SQL_FUNCTION
175
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
176
+ AS $$
177
+ SELECT one + two
178
+ $$
179
+ LANGUAGE SQL
180
+ STRICT;
181
+ SQL_FUNCTION
182
+
183
+ a.should_not == b
184
+ a.should_not == c
185
+ a.should_not == d
186
+ end
187
+
188
+ it "should be able to differentiate between functions by their definitions" do
189
+ a = examine <<-SQL_FUNCTION
190
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
191
+ AS $$
192
+ SELECT one + two
193
+ $$
194
+ LANGUAGE SQL;
195
+ SQL_FUNCTION
196
+
197
+ b = examine <<-SQL_FUNCTION
198
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
199
+ AS $$
200
+ SELECT two + one
201
+ $$
202
+ LANGUAGE SQL;
203
+ SQL_FUNCTION
204
+
205
+ a.should_not == b
206
+ end
207
+
208
+ it "should be able to differentiate between functions by their volatility" do
209
+ a = examine <<-SQL_FUNCTION
210
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
211
+ AS $$
212
+ SELECT one + two
213
+ $$
214
+ LANGUAGE SQL;
215
+ SQL_FUNCTION
216
+
217
+ b = examine <<-SQL_FUNCTION
218
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
219
+ AS $$
220
+ SELECT one + two
221
+ $$
222
+ LANGUAGE SQL
223
+ VOLATILE;
224
+ SQL_FUNCTION
225
+
226
+ c = examine <<-SQL_FUNCTION
227
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
228
+ AS $$
229
+ SELECT one + two
230
+ $$
231
+ LANGUAGE SQL
232
+ STABLE;
233
+ SQL_FUNCTION
234
+
235
+ d = examine <<-SQL_FUNCTION
236
+ CREATE FUNCTION add(one integer, two integer) RETURNS integer
237
+ AS $$
238
+ SELECT one + two
239
+ $$
240
+ LANGUAGE SQL
241
+ IMMUTABLE;
242
+ SQL_FUNCTION
243
+
244
+ a.should == b
245
+ a.should_not == c
246
+ a.should_not == d
247
+ end
248
+
249
+ it "should be able to differentiate between triggers by their names" do
250
+ a = examine <<-SQL
251
+ CREATE TABLE test_table (
252
+ a integer
253
+ );
254
+
255
+ CREATE FUNCTION func() RETURNS trigger AS $$
256
+ BEGIN
257
+ NEW.a = 56;
258
+ RETURN NEW;
259
+ END;
260
+ $$
261
+ LANGUAGE plpgsql;
262
+
263
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
264
+ SQL
265
+
266
+ b = examine <<-SQL
267
+ CREATE TABLE test_table (
268
+ a integer
269
+ );
270
+
271
+ CREATE FUNCTION func() RETURNS trigger AS $$
272
+ BEGIN
273
+ NEW.a = 56;
274
+ RETURN NEW;
275
+ END;
276
+ $$
277
+ LANGUAGE plpgsql;
278
+
279
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
280
+ SQL
281
+
282
+ c = examine <<-SQL
283
+ CREATE TABLE test_table (
284
+ a integer
285
+ );
286
+
287
+ CREATE FUNCTION func() RETURNS trigger AS $$
288
+ BEGIN
289
+ NEW.a = 56;
290
+ RETURN NEW;
291
+ END;
292
+ $$
293
+ LANGUAGE plpgsql;
294
+
295
+ CREATE TRIGGER trig2 BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
296
+ SQL
297
+
298
+ a.should == b
299
+ a.should_not == c
300
+ b.should_not == c
301
+ end
302
+
303
+ it "should be able to differentiate between triggers by their parent tables" do
304
+ a = examine <<-SQL
305
+ CREATE TABLE test_table_a (
306
+ a integer
307
+ );
308
+
309
+ CREATE TABLE test_table_b (
310
+ a integer
311
+ );
312
+
313
+ CREATE FUNCTION func() RETURNS trigger AS $$
314
+ BEGIN
315
+ NEW.a = 56;
316
+ RETURN NEW;
317
+ END;
318
+ $$
319
+ LANGUAGE plpgsql;
320
+
321
+ CREATE TRIGGER trig BEFORE INSERT ON test_table_a FOR EACH ROW EXECUTE PROCEDURE func();
322
+ SQL
323
+
324
+ b = examine <<-SQL
325
+ CREATE TABLE test_table_a (
326
+ a integer
327
+ );
328
+
329
+ CREATE TABLE test_table_b (
330
+ a integer
331
+ );
332
+
333
+ CREATE FUNCTION func() RETURNS trigger AS $$
334
+ BEGIN
335
+ NEW.a = 56;
336
+ RETURN NEW;
337
+ END;
338
+ $$
339
+ LANGUAGE plpgsql;
340
+
341
+ CREATE TRIGGER trig BEFORE INSERT ON test_table_b FOR EACH ROW EXECUTE PROCEDURE func();
342
+ SQL
343
+
344
+ a.should_not == b
345
+ end
346
+
347
+ it "should be able to differentiate between triggers by their associated functions" do
348
+ a = examine <<-SQL
349
+ CREATE TABLE test_table (
350
+ a integer
351
+ );
352
+
353
+ CREATE FUNCTION func1() RETURNS trigger AS $$
354
+ BEGIN
355
+ NEW.a = 56;
356
+ RETURN NEW;
357
+ END;
358
+ $$
359
+ LANGUAGE plpgsql;
360
+
361
+ CREATE FUNCTION func2() RETURNS trigger AS $$
362
+ BEGIN
363
+ NEW.a = 56;
364
+ RETURN NEW;
365
+ END;
366
+ $$
367
+ LANGUAGE plpgsql;
368
+
369
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func1();
370
+ SQL
371
+
372
+ b = examine <<-SQL
373
+ CREATE TABLE test_table (
374
+ a integer
375
+ );
376
+
377
+ CREATE FUNCTION func1() RETURNS trigger AS $$
378
+ BEGIN
379
+ NEW.a = 56;
380
+ RETURN NEW;
381
+ END;
382
+ $$
383
+ LANGUAGE plpgsql;
384
+
385
+ CREATE FUNCTION func2() RETURNS trigger AS $$
386
+ BEGIN
387
+ NEW.a = 56;
388
+ RETURN NEW;
389
+ END;
390
+ $$
391
+ LANGUAGE plpgsql;
392
+
393
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func2();
394
+ SQL
395
+
396
+ a.should_not == b
397
+ end
398
+
399
+ it "should be able to differentiate between triggers by their firing conditions" do
400
+ a = examine <<-SQL
401
+ CREATE TABLE test_table (
402
+ a integer
403
+ );
404
+
405
+ CREATE FUNCTION func() RETURNS trigger AS $$
406
+ BEGIN
407
+ NEW.a = 56;
408
+ RETURN NEW;
409
+ END;
410
+ $$
411
+ LANGUAGE plpgsql;
412
+
413
+ CREATE TRIGGER trig BEFORE INSERT ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
414
+ SQL
415
+
416
+ b = examine <<-SQL
417
+ CREATE TABLE test_table (
418
+ a integer
419
+ );
420
+
421
+ CREATE FUNCTION func() RETURNS trigger AS $$
422
+ BEGIN
423
+ NEW.a = 56;
424
+ RETURN NEW;
425
+ END;
426
+ $$
427
+ LANGUAGE plpgsql;
428
+
429
+ CREATE TRIGGER trig BEFORE UPDATE ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
430
+ SQL
431
+
432
+ c = examine <<-SQL
433
+ CREATE TABLE test_table (
434
+ a integer
435
+ );
436
+
437
+ CREATE FUNCTION func() RETURNS trigger AS $$
438
+ BEGIN
439
+ NEW.a = 56;
440
+ RETURN NEW;
441
+ END;
442
+ $$
443
+ LANGUAGE plpgsql;
444
+
445
+ CREATE TRIGGER trig BEFORE DELETE ON test_table FOR EACH ROW EXECUTE PROCEDURE func();
446
+ SQL
447
+
448
+ a.should_not == b
449
+ a.should_not == c
450
+ b.should_not == c
451
+ end
452
+ end