@oliphaunt/extension-pgtap-linux-arm64-gnu 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.
- package/LICENSE +21 -0
- package/README.md +6 -0
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/extension-contract.json +31 -0
- package/package.json +49 -0
- package/runtime/share/licenses/pgtap/README.md +153 -0
- package/runtime/share/postgresql/extension/pgtap--0.90.0--0.91.0.sql +29 -0
- package/runtime/share/postgresql/extension/pgtap--0.91.0--0.92.0.sql +1650 -0
- package/runtime/share/postgresql/extension/pgtap--0.92.0--0.93.0.sql +679 -0
- package/runtime/share/postgresql/extension/pgtap--0.93.0--0.94.0.sql +193 -0
- package/runtime/share/postgresql/extension/pgtap--0.94.0--0.95.0.sql +639 -0
- package/runtime/share/postgresql/extension/pgtap--0.95.0--0.96.0.sql +415 -0
- package/runtime/share/postgresql/extension/pgtap--0.96.0--0.97.0.sql +375 -0
- package/runtime/share/postgresql/extension/pgtap--0.97.0--0.98.0.sql +441 -0
- package/runtime/share/postgresql/extension/pgtap--0.98.0--0.99.0.sql +209 -0
- package/runtime/share/postgresql/extension/pgtap--0.99.0--1.0.0.sql +737 -0
- package/runtime/share/postgresql/extension/pgtap--1.0.0--1.1.0.sql +186 -0
- package/runtime/share/postgresql/extension/pgtap--1.1.0--1.2.0.sql +889 -0
- package/runtime/share/postgresql/extension/pgtap--1.2.0--1.3.0.sql +495 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.0--1.3.1.sql +229 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.1--1.3.2.sql +34 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.2--1.3.3.sql +42 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.3--1.3.4.sql +89 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.4--1.3.5.sql +1 -0
- package/runtime/share/postgresql/extension/pgtap--1.3.5.sql +11520 -0
- package/runtime/share/postgresql/extension/pgtap--unpackaged--0.91.0.sql +714 -0
- package/runtime/share/postgresql/extension/pgtap-core--1.3.5.sql +4390 -0
- package/runtime/share/postgresql/extension/pgtap-core.sql +4390 -0
- package/runtime/share/postgresql/extension/pgtap-schema--1.3.5.sql +6764 -0
- package/runtime/share/postgresql/extension/pgtap-schema.sql +6764 -0
- package/runtime/share/postgresql/extension/pgtap.control +6 -0
- package/runtime/share/postgresql/extension/pgtap.sql +11520 -0
- package/runtime/share/postgresql/extension/uninstall_pgtap.sql +1088 -0
- package/share/licenses/pgtap/README.md +153 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
CREATE OR REPLACE FUNCTION pgtap_version()
|
|
2
|
+
RETURNS NUMERIC AS 'SELECT 0.98;'
|
|
3
|
+
LANGUAGE SQL IMMUTABLE;
|
|
4
|
+
|
|
5
|
+
CREATE OR REPLACE FUNCTION _rexists ( CHAR[], NAME, NAME )
|
|
6
|
+
RETURNS BOOLEAN AS $$
|
|
7
|
+
SELECT EXISTS(
|
|
8
|
+
SELECT true
|
|
9
|
+
FROM pg_catalog.pg_namespace n
|
|
10
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
11
|
+
WHERE c.relkind = ANY($1)
|
|
12
|
+
AND n.nspname = $2
|
|
13
|
+
AND c.relname = $3
|
|
14
|
+
);
|
|
15
|
+
$$ LANGUAGE SQL;
|
|
16
|
+
|
|
17
|
+
CREATE OR REPLACE FUNCTION _rexists ( CHAR[], NAME )
|
|
18
|
+
RETURNS BOOLEAN AS $$
|
|
19
|
+
SELECT EXISTS(
|
|
20
|
+
SELECT true
|
|
21
|
+
FROM pg_catalog.pg_class c
|
|
22
|
+
WHERE c.relkind = ANY($1)
|
|
23
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
24
|
+
AND c.relname = $2
|
|
25
|
+
);
|
|
26
|
+
$$ LANGUAGE SQL;
|
|
27
|
+
|
|
28
|
+
CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME, NAME )
|
|
29
|
+
RETURNS BOOLEAN AS $$
|
|
30
|
+
SELECT _rexists(ARRAY[$1], $2, $3);
|
|
31
|
+
$$ LANGUAGE SQL;
|
|
32
|
+
|
|
33
|
+
CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME )
|
|
34
|
+
RETURNS BOOLEAN AS $$
|
|
35
|
+
SELECT _rexists(ARRAY[$1], $2);
|
|
36
|
+
$$ LANGUAGE SQL;
|
|
37
|
+
|
|
38
|
+
-- has_table( schema, table, description )
|
|
39
|
+
CREATE OR REPLACE FUNCTION has_table ( NAME, NAME, TEXT )
|
|
40
|
+
RETURNS TEXT AS $$
|
|
41
|
+
SELECT ok( _rexists( '{r,p}'::char[], $1, $2 ), $3 );
|
|
42
|
+
$$ LANGUAGE SQL;
|
|
43
|
+
|
|
44
|
+
-- has_table( schema, table )
|
|
45
|
+
CREATE OR REPLACE FUNCTION has_table ( NAME, NAME )
|
|
46
|
+
RETURNS TEXT AS $$
|
|
47
|
+
SELECT ok(
|
|
48
|
+
_rexists( '{r,p}'::char[], $1, $2 ),
|
|
49
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist'
|
|
50
|
+
);
|
|
51
|
+
$$ LANGUAGE SQL;
|
|
52
|
+
|
|
53
|
+
-- has_table( table, description )
|
|
54
|
+
CREATE OR REPLACE FUNCTION has_table ( NAME, TEXT )
|
|
55
|
+
RETURNS TEXT AS $$
|
|
56
|
+
SELECT ok( _rexists( '{r,p}'::char[], $1 ), $2 );
|
|
57
|
+
$$ LANGUAGE SQL;
|
|
58
|
+
|
|
59
|
+
-- hasnt_table( schema, table, description )
|
|
60
|
+
CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME, TEXT )
|
|
61
|
+
RETURNS TEXT AS $$
|
|
62
|
+
SELECT ok( NOT _rexists( '{r,p}'::char[], $1, $2 ), $3 );
|
|
63
|
+
$$ LANGUAGE SQL;
|
|
64
|
+
|
|
65
|
+
-- hasnt_table( schema, table )
|
|
66
|
+
CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME )
|
|
67
|
+
RETURNS TEXT AS $$
|
|
68
|
+
SELECT ok(
|
|
69
|
+
NOT _rexists( '{r,p}'::char[], $1, $2 ),
|
|
70
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist'
|
|
71
|
+
);
|
|
72
|
+
$$ LANGUAGE SQL;
|
|
73
|
+
|
|
74
|
+
-- hasnt_table( table, description )
|
|
75
|
+
CREATE OR REPLACE FUNCTION hasnt_table ( NAME, TEXT )
|
|
76
|
+
RETURNS TEXT AS $$
|
|
77
|
+
SELECT ok( NOT _rexists( '{r,p}'::char[], $1 ), $2 );
|
|
78
|
+
$$ LANGUAGE SQL;
|
|
79
|
+
|
|
80
|
+
CREATE OR REPLACE FUNCTION _extras ( CHAR[], NAME, NAME[] )
|
|
81
|
+
RETURNS NAME[] AS $$
|
|
82
|
+
SELECT ARRAY(
|
|
83
|
+
SELECT c.relname
|
|
84
|
+
FROM pg_catalog.pg_namespace n
|
|
85
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
86
|
+
WHERE c.relkind = ANY($1)
|
|
87
|
+
AND n.nspname = $2
|
|
88
|
+
AND c.relname NOT IN('pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq')
|
|
89
|
+
EXCEPT
|
|
90
|
+
SELECT $3[i]
|
|
91
|
+
FROM generate_series(1, array_upper($3, 1)) s(i)
|
|
92
|
+
);
|
|
93
|
+
$$ LANGUAGE SQL;
|
|
94
|
+
|
|
95
|
+
CREATE OR REPLACE FUNCTION _extras ( CHAR[], NAME[] )
|
|
96
|
+
RETURNS NAME[] AS $$
|
|
97
|
+
SELECT ARRAY(
|
|
98
|
+
SELECT c.relname
|
|
99
|
+
FROM pg_catalog.pg_namespace n
|
|
100
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
101
|
+
WHERE pg_catalog.pg_table_is_visible(c.oid)
|
|
102
|
+
AND n.nspname <> 'pg_catalog'
|
|
103
|
+
AND c.relkind = ANY($1)
|
|
104
|
+
AND c.relname NOT IN ('__tcache__', 'pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq')
|
|
105
|
+
EXCEPT
|
|
106
|
+
SELECT $2[i]
|
|
107
|
+
FROM generate_series(1, array_upper($2, 1)) s(i)
|
|
108
|
+
);
|
|
109
|
+
$$ LANGUAGE SQL;
|
|
110
|
+
|
|
111
|
+
CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME, NAME[] )
|
|
112
|
+
RETURNS NAME[] AS $$
|
|
113
|
+
SELECT _extras(ARRAY[$1], $2, $3);
|
|
114
|
+
$$ LANGUAGE SQL;
|
|
115
|
+
|
|
116
|
+
CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME[] )
|
|
117
|
+
RETURNS NAME[] AS $$
|
|
118
|
+
SELECT _extras(ARRAY[$1], $2);
|
|
119
|
+
$$ LANGUAGE SQL;
|
|
120
|
+
|
|
121
|
+
CREATE OR REPLACE FUNCTION _missing ( CHAR[], NAME, NAME[] )
|
|
122
|
+
RETURNS NAME[] AS $$
|
|
123
|
+
SELECT ARRAY(
|
|
124
|
+
SELECT $3[i]
|
|
125
|
+
FROM generate_series(1, array_upper($3, 1)) s(i)
|
|
126
|
+
EXCEPT
|
|
127
|
+
SELECT c.relname
|
|
128
|
+
FROM pg_catalog.pg_namespace n
|
|
129
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
130
|
+
WHERE c.relkind = ANY($1)
|
|
131
|
+
AND n.nspname = $2
|
|
132
|
+
);
|
|
133
|
+
$$ LANGUAGE SQL;
|
|
134
|
+
|
|
135
|
+
CREATE OR REPLACE FUNCTION _missing ( CHAR[], NAME[] )
|
|
136
|
+
RETURNS NAME[] AS $$
|
|
137
|
+
SELECT ARRAY(
|
|
138
|
+
SELECT $2[i]
|
|
139
|
+
FROM generate_series(1, array_upper($2, 1)) s(i)
|
|
140
|
+
EXCEPT
|
|
141
|
+
SELECT c.relname
|
|
142
|
+
FROM pg_catalog.pg_namespace n
|
|
143
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
144
|
+
WHERE pg_catalog.pg_table_is_visible(c.oid)
|
|
145
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
146
|
+
AND c.relkind = ANY($1)
|
|
147
|
+
);
|
|
148
|
+
$$ LANGUAGE SQL;
|
|
149
|
+
|
|
150
|
+
CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME, NAME[] )
|
|
151
|
+
RETURNS NAME[] AS $$
|
|
152
|
+
SELECT _missing(ARRAY[$1], $2, $3);
|
|
153
|
+
$$ LANGUAGE SQL;
|
|
154
|
+
|
|
155
|
+
CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME[] )
|
|
156
|
+
RETURNS NAME[] AS $$
|
|
157
|
+
SELECT _missing(ARRAY[$1], $2);
|
|
158
|
+
$$ LANGUAGE SQL;
|
|
159
|
+
|
|
160
|
+
-- tables_are( schema, tables, description )
|
|
161
|
+
CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[], TEXT )
|
|
162
|
+
RETURNS TEXT AS $$
|
|
163
|
+
SELECT _are( 'tables', _extras('{r,p}'::char[], $1, $2), _missing('{r,p}'::char[], $1, $2), $3);
|
|
164
|
+
$$ LANGUAGE SQL;
|
|
165
|
+
|
|
166
|
+
-- tables_are( tables, description )
|
|
167
|
+
CREATE OR REPLACE FUNCTION tables_are ( NAME[], TEXT )
|
|
168
|
+
RETURNS TEXT AS $$
|
|
169
|
+
SELECT _are( 'tables', _extras('{r,p}'::char[], $1), _missing('{r,p}'::char[], $1), $2);
|
|
170
|
+
$$ LANGUAGE SQL;
|
|
171
|
+
|
|
172
|
+
-- tables_are( schema, tables )
|
|
173
|
+
CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[] )
|
|
174
|
+
RETURNS TEXT AS $$
|
|
175
|
+
SELECT _are(
|
|
176
|
+
'tables', _extras('{r,p}'::char[], $1, $2), _missing('{r,p}'::char[], $1, $2),
|
|
177
|
+
'Schema ' || quote_ident($1) || ' should have the correct tables'
|
|
178
|
+
);
|
|
179
|
+
$$ LANGUAGE SQL;
|
|
180
|
+
|
|
181
|
+
-- tables_are( tables )
|
|
182
|
+
CREATE OR REPLACE FUNCTION tables_are ( NAME[] )
|
|
183
|
+
RETURNS TEXT AS $$
|
|
184
|
+
SELECT _are(
|
|
185
|
+
'tables', _extras('{r,p}'::char[], $1), _missing('{r,p}'::char[], $1),
|
|
186
|
+
'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables'
|
|
187
|
+
);
|
|
188
|
+
$$ LANGUAGE SQL;
|
|
189
|
+
|
|
190
|
+
CREATE OR REPLACE FUNCTION _get_rel_owner ( CHAR[], NAME, NAME )
|
|
191
|
+
RETURNS NAME AS $$
|
|
192
|
+
SELECT pg_catalog.pg_get_userbyid(c.relowner)
|
|
193
|
+
FROM pg_catalog.pg_class c
|
|
194
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
195
|
+
WHERE c.relkind = ANY($1)
|
|
196
|
+
AND n.nspname = $2
|
|
197
|
+
AND c.relname = $3
|
|
198
|
+
$$ LANGUAGE SQL;
|
|
199
|
+
|
|
200
|
+
CREATE OR REPLACE FUNCTION _get_rel_owner ( CHAR[], NAME )
|
|
201
|
+
RETURNS NAME AS $$
|
|
202
|
+
SELECT pg_catalog.pg_get_userbyid(c.relowner)
|
|
203
|
+
FROM pg_catalog.pg_class c
|
|
204
|
+
WHERE c.relkind = ANY($1)
|
|
205
|
+
AND c.relname = $2
|
|
206
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
207
|
+
$$ LANGUAGE SQL;
|
|
208
|
+
|
|
209
|
+
CREATE OR REPLACE FUNCTION _get_rel_owner ( CHAR, NAME, NAME )
|
|
210
|
+
RETURNS NAME AS $$
|
|
211
|
+
SELECT _get_rel_owner(ARRAY[$1], $2, $3);
|
|
212
|
+
$$ LANGUAGE SQL;
|
|
213
|
+
|
|
214
|
+
CREATE OR REPLACE FUNCTION _get_rel_owner ( CHAR, NAME )
|
|
215
|
+
RETURNS NAME AS $$
|
|
216
|
+
SELECT _get_rel_owner(ARRAY[$1], $2);
|
|
217
|
+
$$ LANGUAGE SQL;
|
|
218
|
+
|
|
219
|
+
-- table_owner_is ( schema, table, user, description )
|
|
220
|
+
CREATE OR REPLACE FUNCTION table_owner_is ( NAME, NAME, NAME, TEXT )
|
|
221
|
+
RETURNS TEXT AS $$
|
|
222
|
+
DECLARE
|
|
223
|
+
owner NAME := _get_rel_owner('{r,p}'::char[], $1, $2);
|
|
224
|
+
BEGIN
|
|
225
|
+
-- Make sure the table exists.
|
|
226
|
+
IF owner IS NULL THEN
|
|
227
|
+
RETURN ok(FALSE, $4) || E'\n' || diag(
|
|
228
|
+
E' Table ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist'
|
|
229
|
+
);
|
|
230
|
+
END IF;
|
|
231
|
+
|
|
232
|
+
RETURN is(owner, $3, $4);
|
|
233
|
+
END;
|
|
234
|
+
$$ LANGUAGE plpgsql;
|
|
235
|
+
|
|
236
|
+
-- table_owner_is ( table, user, description )
|
|
237
|
+
CREATE OR REPLACE FUNCTION table_owner_is ( NAME, NAME, TEXT )
|
|
238
|
+
RETURNS TEXT AS $$
|
|
239
|
+
DECLARE
|
|
240
|
+
owner NAME := _get_rel_owner('{r,p}'::char[], $1);
|
|
241
|
+
BEGIN
|
|
242
|
+
-- Make sure the table exists.
|
|
243
|
+
IF owner IS NULL THEN
|
|
244
|
+
RETURN ok(FALSE, $3) || E'\n' || diag(
|
|
245
|
+
E' Table ' || quote_ident($1) || ' does not exist'
|
|
246
|
+
);
|
|
247
|
+
END IF;
|
|
248
|
+
|
|
249
|
+
RETURN is(owner, $2, $3);
|
|
250
|
+
END;
|
|
251
|
+
$$ LANGUAGE plpgsql;
|
|
252
|
+
|
|
253
|
+
-- is_partitioned( schema, table, description )
|
|
254
|
+
CREATE OR REPLACE FUNCTION is_partitioned ( NAME, NAME, TEXT )
|
|
255
|
+
RETURNS TEXT AS $$
|
|
256
|
+
SELECT ok( _rexists('p', $1, $2), $3);
|
|
257
|
+
$$ LANGUAGE sql;
|
|
258
|
+
|
|
259
|
+
-- is_partitioned( schema, table )
|
|
260
|
+
CREATE OR REPLACE FUNCTION is_partitioned ( NAME, NAME )
|
|
261
|
+
RETURNS TEXT AS $$
|
|
262
|
+
SELECT ok(
|
|
263
|
+
_rexists('p', $1, $2),
|
|
264
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should be partitioned'
|
|
265
|
+
);
|
|
266
|
+
$$ LANGUAGE sql;
|
|
267
|
+
|
|
268
|
+
-- is_partitioned( table, description )
|
|
269
|
+
CREATE OR REPLACE FUNCTION is_partitioned ( NAME, TEXT )
|
|
270
|
+
RETURNS TEXT AS $$
|
|
271
|
+
SELECT ok( _rexists('p', $1), $2);
|
|
272
|
+
$$ LANGUAGE sql;
|
|
273
|
+
|
|
274
|
+
-- is_partitioned( table )
|
|
275
|
+
CREATE OR REPLACE FUNCTION is_partitioned ( NAME )
|
|
276
|
+
RETURNS TEXT AS $$
|
|
277
|
+
SELECT ok(
|
|
278
|
+
_rexists('p', $1),
|
|
279
|
+
'Table ' || quote_ident($1) || ' should be partitioned'
|
|
280
|
+
);
|
|
281
|
+
$$ LANGUAGE sql;
|
|
282
|
+
|
|
283
|
+
-- isnt_partitioned( schema, table, description )
|
|
284
|
+
CREATE OR REPLACE FUNCTION isnt_partitioned ( NAME, NAME, TEXT )
|
|
285
|
+
RETURNS TEXT AS $$
|
|
286
|
+
SELECT ok( NOT _rexists('p', $1, $2), $3);
|
|
287
|
+
$$ LANGUAGE sql;
|
|
288
|
+
|
|
289
|
+
-- isnt_partitioned( schema, table )
|
|
290
|
+
CREATE OR REPLACE FUNCTION isnt_partitioned ( NAME, NAME )
|
|
291
|
+
RETURNS TEXT AS $$
|
|
292
|
+
SELECT ok(
|
|
293
|
+
NOT _rexists('p', $1, $2),
|
|
294
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not be partitioned'
|
|
295
|
+
);
|
|
296
|
+
$$ LANGUAGE sql;
|
|
297
|
+
|
|
298
|
+
-- isnt_partitioned( table, description )
|
|
299
|
+
CREATE OR REPLACE FUNCTION isnt_partitioned ( NAME, TEXT )
|
|
300
|
+
RETURNS TEXT AS $$
|
|
301
|
+
SELECT ok( NOT _rexists('p', $1), $2);
|
|
302
|
+
$$ LANGUAGE sql;
|
|
303
|
+
|
|
304
|
+
-- isnt_partitioned( table )
|
|
305
|
+
CREATE OR REPLACE FUNCTION isnt_partitioned ( NAME )
|
|
306
|
+
RETURNS TEXT AS $$
|
|
307
|
+
SELECT ok(
|
|
308
|
+
NOT _rexists('p', $1),
|
|
309
|
+
'Table ' || quote_ident($1) || ' should not be partitioned'
|
|
310
|
+
);
|
|
311
|
+
$$ LANGUAGE sql;
|
|
312
|
+
|
|
313
|
+
-- _partof( child_schema, child_table, parent_schema, parent_table )
|
|
314
|
+
CREATE OR REPLACE FUNCTION _partof ( NAME, NAME, NAME, NAME )
|
|
315
|
+
RETURNS BOOLEAN AS $$
|
|
316
|
+
SELECT EXISTS(
|
|
317
|
+
SELECT true
|
|
318
|
+
FROM pg_catalog.pg_namespace cn
|
|
319
|
+
JOIN pg_catalog.pg_class cc ON cn.oid = cc.relnamespace
|
|
320
|
+
JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid
|
|
321
|
+
JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid
|
|
322
|
+
JOIN pg_catalog.pg_namespace pn ON pc.relnamespace = pn.oid
|
|
323
|
+
WHERE cn.nspname = $1
|
|
324
|
+
AND cc.relname = $2
|
|
325
|
+
AND cc.relispartition
|
|
326
|
+
AND pn.nspname = $3
|
|
327
|
+
AND pc.relname = $4
|
|
328
|
+
AND pc.relkind = 'p'
|
|
329
|
+
)
|
|
330
|
+
$$ LANGUAGE sql;
|
|
331
|
+
|
|
332
|
+
-- _partof( child_table, parent_table )
|
|
333
|
+
CREATE OR REPLACE FUNCTION _partof ( NAME, NAME )
|
|
334
|
+
RETURNS BOOLEAN AS $$
|
|
335
|
+
SELECT EXISTS(
|
|
336
|
+
SELECT true
|
|
337
|
+
FROM pg_catalog.pg_class cc
|
|
338
|
+
JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid
|
|
339
|
+
JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid
|
|
340
|
+
WHERE cc.relname = $1
|
|
341
|
+
AND cc.relispartition
|
|
342
|
+
AND pc.relname = $2
|
|
343
|
+
AND pc.relkind = 'p'
|
|
344
|
+
AND pg_catalog.pg_table_is_visible(cc.oid)
|
|
345
|
+
AND pg_catalog.pg_table_is_visible(pc.oid)
|
|
346
|
+
)
|
|
347
|
+
$$ LANGUAGE sql;
|
|
348
|
+
|
|
349
|
+
-- is_partition_of( child_schema, child_table, parent_schema, parent_table, description )
|
|
350
|
+
CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME, TEXT )
|
|
351
|
+
RETURNS TEXT AS $$
|
|
352
|
+
SELECT ok( _partof($1, $2, $3, $4), $5);
|
|
353
|
+
$$ LANGUAGE sql;
|
|
354
|
+
|
|
355
|
+
-- is_partition_of( child_schema, child_table, parent_schema, parent_table )
|
|
356
|
+
CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME )
|
|
357
|
+
RETURNS TEXT AS $$
|
|
358
|
+
SELECT ok(
|
|
359
|
+
_partof($1, $2, $3, $4),
|
|
360
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should be a partition of '
|
|
361
|
+
|| quote_ident($3) || '.' || quote_ident($4)
|
|
362
|
+
);
|
|
363
|
+
$$ LANGUAGE sql;
|
|
364
|
+
|
|
365
|
+
-- is_partition_of( child_table, parent_table, description )
|
|
366
|
+
CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, TEXT )
|
|
367
|
+
RETURNS TEXT AS $$
|
|
368
|
+
SELECT ok( _partof($1, $2), $3);
|
|
369
|
+
$$ LANGUAGE sql;
|
|
370
|
+
|
|
371
|
+
-- is_partition_of( child_table, parent_table )
|
|
372
|
+
CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME )
|
|
373
|
+
RETURNS TEXT AS $$
|
|
374
|
+
SELECT ok(
|
|
375
|
+
_partof($1, $2),
|
|
376
|
+
'Table ' || quote_ident($1) || ' should be a partition of ' || quote_ident($2)
|
|
377
|
+
);
|
|
378
|
+
$$ LANGUAGE sql;
|
|
379
|
+
|
|
380
|
+
-- _parts(schema, table)
|
|
381
|
+
CREATE OR REPLACE FUNCTION _parts( NAME, NAME )
|
|
382
|
+
RETURNS SETOF NAME AS $$
|
|
383
|
+
SELECT i.inhrelid::regclass::name
|
|
384
|
+
FROM pg_catalog.pg_namespace n
|
|
385
|
+
JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
|
|
386
|
+
JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent
|
|
387
|
+
WHERE n.nspname = $1
|
|
388
|
+
AND c.relname = $2
|
|
389
|
+
AND c.relkind = 'p'
|
|
390
|
+
$$ LANGUAGE SQL;
|
|
391
|
+
|
|
392
|
+
-- _parts(table)
|
|
393
|
+
CREATE OR REPLACE FUNCTION _parts( NAME )
|
|
394
|
+
RETURNS SETOF NAME AS $$
|
|
395
|
+
SELECT i.inhrelid::regclass::name
|
|
396
|
+
FROM pg_catalog.pg_class c
|
|
397
|
+
JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent
|
|
398
|
+
WHERE c.relname = $1
|
|
399
|
+
AND c.relkind = 'p'
|
|
400
|
+
AND pg_catalog.pg_table_is_visible(c.oid)
|
|
401
|
+
$$ LANGUAGE SQL;
|
|
402
|
+
|
|
403
|
+
-- partitions_are( schema, table, partitions, description )
|
|
404
|
+
CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[], TEXT )
|
|
405
|
+
RETURNS TEXT AS $$
|
|
406
|
+
SELECT _are(
|
|
407
|
+
'partitions',
|
|
408
|
+
ARRAY(SELECT _parts($1, $2) EXCEPT SELECT unnest($3)),
|
|
409
|
+
ARRAY(SELECT unnest($3) EXCEPT SELECT _parts($1, $2)),
|
|
410
|
+
$4
|
|
411
|
+
);
|
|
412
|
+
$$ LANGUAGE SQL;
|
|
413
|
+
|
|
414
|
+
-- partitions_are( schema, table, partitions )
|
|
415
|
+
CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[] )
|
|
416
|
+
RETURNS TEXT AS $$
|
|
417
|
+
SELECT partitions_are(
|
|
418
|
+
$1, $2, $3,
|
|
419
|
+
'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct partitions'
|
|
420
|
+
);
|
|
421
|
+
$$ LANGUAGE SQL;
|
|
422
|
+
|
|
423
|
+
-- partitions_are( table, partitions, description )
|
|
424
|
+
CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[], TEXT )
|
|
425
|
+
RETURNS TEXT AS $$
|
|
426
|
+
SELECT _are(
|
|
427
|
+
'partitions',
|
|
428
|
+
ARRAY(SELECT _parts($1) EXCEPT SELECT unnest($2)),
|
|
429
|
+
ARRAY(SELECT unnest($2) EXCEPT SELECT _parts($1)),
|
|
430
|
+
$3
|
|
431
|
+
);
|
|
432
|
+
$$ LANGUAGE SQL;
|
|
433
|
+
|
|
434
|
+
-- partitions_are( table, partitions )
|
|
435
|
+
CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[] )
|
|
436
|
+
RETURNS TEXT AS $$
|
|
437
|
+
SELECT partitions_are(
|
|
438
|
+
$1, $2,
|
|
439
|
+
'Table ' || quote_ident($1) || ' should have the correct partitions'
|
|
440
|
+
);
|
|
441
|
+
$$ LANGUAGE SQL;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
CREATE OR REPLACE FUNCTION pgtap_version()
|
|
2
|
+
RETURNS NUMERIC AS 'SELECT 0.99;'
|
|
3
|
+
LANGUAGE SQL IMMUTABLE;
|
|
4
|
+
|
|
5
|
+
CREATE OR REPLACE FUNCTION pg_version_num()
|
|
6
|
+
RETURNS integer AS $$
|
|
7
|
+
SELECT current_setting('server_version_num')::integer;
|
|
8
|
+
$$ LANGUAGE SQL IMMUTABLE;
|
|
9
|
+
|
|
10
|
+
CREATE OR REPLACE FUNCTION _ident_array_to_sorted_string( name[], text )
|
|
11
|
+
RETURNS text AS $$
|
|
12
|
+
SELECT array_to_string(ARRAY(
|
|
13
|
+
SELECT quote_ident($1[i])
|
|
14
|
+
FROM generate_series(1, array_upper($1, 1)) s(i)
|
|
15
|
+
ORDER BY $1[i]
|
|
16
|
+
), $2);
|
|
17
|
+
$$ LANGUAGE SQL immutable;
|
|
18
|
+
|
|
19
|
+
CREATE OR REPLACE FUNCTION _array_to_sorted_string( name[], text )
|
|
20
|
+
RETURNS text AS $$
|
|
21
|
+
SELECT array_to_string(ARRAY(
|
|
22
|
+
SELECT $1[i]
|
|
23
|
+
FROM generate_series(1, array_upper($1, 1)) s(i)
|
|
24
|
+
ORDER BY $1[i]
|
|
25
|
+
), $2);
|
|
26
|
+
$$ LANGUAGE SQL immutable;
|
|
27
|
+
|
|
28
|
+
CREATE OR REPLACE FUNCTION _are ( text, name[], name[], TEXT )
|
|
29
|
+
RETURNS TEXT AS $$
|
|
30
|
+
DECLARE
|
|
31
|
+
what ALIAS FOR $1;
|
|
32
|
+
extras ALIAS FOR $2;
|
|
33
|
+
missing ALIAS FOR $3;
|
|
34
|
+
descr ALIAS FOR $4;
|
|
35
|
+
msg TEXT := '';
|
|
36
|
+
res BOOLEAN := TRUE;
|
|
37
|
+
BEGIN
|
|
38
|
+
IF extras[1] IS NOT NULL THEN
|
|
39
|
+
res = FALSE;
|
|
40
|
+
msg := E'\n' || diag(
|
|
41
|
+
' Extra ' || what || E':\n '
|
|
42
|
+
|| _ident_array_to_sorted_string( extras, E'\n ' )
|
|
43
|
+
);
|
|
44
|
+
END IF;
|
|
45
|
+
IF missing[1] IS NOT NULL THEN
|
|
46
|
+
res = FALSE;
|
|
47
|
+
msg := msg || E'\n' || diag(
|
|
48
|
+
' Missing ' || what || E':\n '
|
|
49
|
+
|| _ident_array_to_sorted_string( missing, E'\n ' )
|
|
50
|
+
);
|
|
51
|
+
END IF;
|
|
52
|
+
|
|
53
|
+
RETURN ok(res, descr) || msg;
|
|
54
|
+
END;
|
|
55
|
+
$$ LANGUAGE plpgsql;
|
|
56
|
+
|
|
57
|
+
CREATE OR REPLACE FUNCTION _areni ( text, text[], text[], TEXT )
|
|
58
|
+
RETURNS TEXT AS $$
|
|
59
|
+
DECLARE
|
|
60
|
+
what ALIAS FOR $1;
|
|
61
|
+
extras ALIAS FOR $2;
|
|
62
|
+
missing ALIAS FOR $3;
|
|
63
|
+
descr ALIAS FOR $4;
|
|
64
|
+
msg TEXT := '';
|
|
65
|
+
res BOOLEAN := TRUE;
|
|
66
|
+
BEGIN
|
|
67
|
+
IF extras[1] IS NOT NULL THEN
|
|
68
|
+
res = FALSE;
|
|
69
|
+
msg := E'\n' || diag(
|
|
70
|
+
' Extra ' || what || E':\n '
|
|
71
|
+
|| _array_to_sorted_string( extras, E'\n ' )
|
|
72
|
+
);
|
|
73
|
+
END IF;
|
|
74
|
+
IF missing[1] IS NOT NULL THEN
|
|
75
|
+
res = FALSE;
|
|
76
|
+
msg := msg || E'\n' || diag(
|
|
77
|
+
' Missing ' || what || E':\n '
|
|
78
|
+
|| _array_to_sorted_string( missing, E'\n ' )
|
|
79
|
+
);
|
|
80
|
+
END IF;
|
|
81
|
+
|
|
82
|
+
RETURN ok(res, descr) || msg;
|
|
83
|
+
END;
|
|
84
|
+
$$ LANGUAGE plpgsql;
|
|
85
|
+
|
|
86
|
+
-- Note: this fixes a bug in the 97->98 upgrade script
|
|
87
|
+
-- table_owner_is ( table, user, description )
|
|
88
|
+
/*
|
|
89
|
+
CREATE OR REPLACE FUNCTION table_owner_is ( NAME, NAME, TEXT )
|
|
90
|
+
RETURNS TEXT AS $$
|
|
91
|
+
DECLARE
|
|
92
|
+
owner NAME := _get_rel_owner('{r,p}'::char[], $1);
|
|
93
|
+
BEGIN
|
|
94
|
+
-- Make sure the table exists.
|
|
95
|
+
IF owner IS NULL THEN
|
|
96
|
+
RETURN ok(FALSE, $3) || E'\n' || diag(
|
|
97
|
+
E' Table ' || quote_ident($1) || ' does not exist'
|
|
98
|
+
);
|
|
99
|
+
END IF;
|
|
100
|
+
|
|
101
|
+
RETURN is(owner, $2, $3);
|
|
102
|
+
END;
|
|
103
|
+
$$ LANGUAGE plpgsql;
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
-- _hasc( schema, table, constraint_type )
|
|
107
|
+
CREATE OR REPLACE FUNCTION _hasc ( NAME, NAME, CHAR )
|
|
108
|
+
RETURNS BOOLEAN AS $$
|
|
109
|
+
SELECT EXISTS(
|
|
110
|
+
SELECT true
|
|
111
|
+
FROM pg_catalog.pg_namespace n
|
|
112
|
+
JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid
|
|
113
|
+
JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
|
|
114
|
+
JOIN pg_catalog.pg_index i ON c.oid = i.indrelid
|
|
115
|
+
WHERE i.indisprimary = true
|
|
116
|
+
AND n.nspname = $1
|
|
117
|
+
AND c.relname = $2
|
|
118
|
+
AND x.contype = $3
|
|
119
|
+
);
|
|
120
|
+
$$ LANGUAGE sql;
|
|
121
|
+
|
|
122
|
+
-- _hasc( table, constraint_type )
|
|
123
|
+
CREATE OR REPLACE FUNCTION _hasc ( NAME, CHAR )
|
|
124
|
+
RETURNS BOOLEAN AS $$
|
|
125
|
+
SELECT EXISTS(
|
|
126
|
+
SELECT true
|
|
127
|
+
FROM pg_catalog.pg_class c
|
|
128
|
+
JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
|
|
129
|
+
JOIN pg_catalog.pg_index i ON c.oid = i.indrelid
|
|
130
|
+
WHERE i.indisprimary = true
|
|
131
|
+
AND pg_table_is_visible(c.oid)
|
|
132
|
+
AND c.relname = $1
|
|
133
|
+
AND x.contype = $2
|
|
134
|
+
);
|
|
135
|
+
$$ LANGUAGE sql;
|
|
136
|
+
|
|
137
|
+
CREATE OR REPLACE VIEW tap_funky
|
|
138
|
+
AS SELECT p.oid AS oid,
|
|
139
|
+
n.nspname AS schema,
|
|
140
|
+
p.proname AS name,
|
|
141
|
+
pg_catalog.pg_get_userbyid(p.proowner) AS owner,
|
|
142
|
+
array_to_string(p.proargtypes::regtype[], ',') AS args,
|
|
143
|
+
CASE p.proretset WHEN TRUE THEN 'setof ' ELSE '' END
|
|
144
|
+
|| p.prorettype::regtype AS returns,
|
|
145
|
+
p.prolang AS langoid,
|
|
146
|
+
p.proisstrict AS is_strict,
|
|
147
|
+
p.prokind AS kind,
|
|
148
|
+
p.prosecdef AS is_definer,
|
|
149
|
+
p.proretset AS returns_set,
|
|
150
|
+
p.provolatile::char AS volatility,
|
|
151
|
+
pg_catalog.pg_function_is_visible(p.oid) AS is_visible
|
|
152
|
+
FROM pg_catalog.pg_proc p
|
|
153
|
+
JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
|
|
154
|
+
;
|
|
155
|
+
|
|
156
|
+
CREATE OR REPLACE FUNCTION _agg ( NAME, NAME, NAME[] )
|
|
157
|
+
RETURNS BOOLEAN AS $$
|
|
158
|
+
SELECT kind = 'a'
|
|
159
|
+
FROM tap_funky
|
|
160
|
+
WHERE schema = $1
|
|
161
|
+
AND name = $2
|
|
162
|
+
AND args = array_to_string($3, ',')
|
|
163
|
+
$$ LANGUAGE SQL;
|
|
164
|
+
|
|
165
|
+
CREATE OR REPLACE FUNCTION _agg ( NAME, NAME )
|
|
166
|
+
RETURNS BOOLEAN AS $$
|
|
167
|
+
SELECT kind = 'a' FROM tap_funky WHERE schema = $1 AND name = $2
|
|
168
|
+
$$ LANGUAGE SQL;
|
|
169
|
+
|
|
170
|
+
CREATE OR REPLACE FUNCTION _agg ( NAME, NAME[] )
|
|
171
|
+
RETURNS BOOLEAN AS $$
|
|
172
|
+
SELECT kind = 'a'
|
|
173
|
+
FROM tap_funky
|
|
174
|
+
WHERE name = $1
|
|
175
|
+
AND args = array_to_string($2, ',')
|
|
176
|
+
AND is_visible;
|
|
177
|
+
$$ LANGUAGE SQL;
|
|
178
|
+
|
|
179
|
+
CREATE OR REPLACE FUNCTION _agg ( NAME )
|
|
180
|
+
RETURNS BOOLEAN AS $$
|
|
181
|
+
SELECT kind = 'a' FROM tap_funky WHERE name = $1 AND is_visible;
|
|
182
|
+
$$ LANGUAGE SQL;
|
|
183
|
+
|
|
184
|
+
-- _hasc( schema, table, constraint_type )
|
|
185
|
+
CREATE OR REPLACE FUNCTION _hasc ( NAME, NAME, CHAR )
|
|
186
|
+
RETURNS BOOLEAN AS $$
|
|
187
|
+
SELECT EXISTS(
|
|
188
|
+
SELECT true
|
|
189
|
+
FROM pg_catalog.pg_namespace n
|
|
190
|
+
JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid
|
|
191
|
+
JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
|
|
192
|
+
WHERE n.nspname = $1
|
|
193
|
+
AND c.relname = $2
|
|
194
|
+
AND x.contype = $3
|
|
195
|
+
);
|
|
196
|
+
$$ LANGUAGE sql;
|
|
197
|
+
|
|
198
|
+
-- _hasc( table, constraint_type )
|
|
199
|
+
CREATE OR REPLACE FUNCTION _hasc ( NAME, CHAR )
|
|
200
|
+
RETURNS BOOLEAN AS $$
|
|
201
|
+
SELECT EXISTS(
|
|
202
|
+
SELECT true
|
|
203
|
+
FROM pg_catalog.pg_class c
|
|
204
|
+
JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
|
|
205
|
+
WHERE pg_table_is_visible(c.oid)
|
|
206
|
+
AND c.relname = $1
|
|
207
|
+
AND x.contype = $2
|
|
208
|
+
);
|
|
209
|
+
$$ LANGUAGE sql;
|