1-- Tests for multirange data types.
2
3--
4-- test input parser
5--
6
7-- negative tests; should fail
8select ''::textmultirange;
9select '{,}'::textmultirange;
10select '{(,)}.'::textmultirange;
11select '{[a,c),}'::textmultirange;
12select '{,[a,c)}'::textmultirange;
13select '{-[a,z)}'::textmultirange;
14select '{[a,z) - }'::textmultirange;
15select '{(",a)}'::textmultirange;
16select '{(,,a)}'::textmultirange;
17select '{(),a)}'::textmultirange;
18select '{(a,))}'::textmultirange;
19select '{(],a)}'::textmultirange;
20select '{(a,])}'::textmultirange;
21select '{[z,a]}'::textmultirange;
22
23-- should succeed
24select '{}'::textmultirange;
25select '  {}  '::textmultirange;
26select ' { empty, empty }  '::textmultirange;
27select ' {( " a " " a ", " z " " z " )  }'::textmultirange;
28select '{(,z)}'::textmultirange;
29select '{(a,)}'::textmultirange;
30select '{[,z]}'::textmultirange;
31select '{[a,]}'::textmultirange;
32select '{(,)}'::textmultirange;
33select '{[ , ]}'::textmultirange;
34select '{["",""]}'::textmultirange;
35select '{[",",","]}'::textmultirange;
36select '{["\\","\\"]}'::textmultirange;
37select '{["""","\""]}'::textmultirange;
38select '{(\\,a)}'::textmultirange;
39select '{((,z)}'::textmultirange;
40select '{([,z)}'::textmultirange;
41select '{(!,()}'::textmultirange;
42select '{(!,[)}'::textmultirange;
43select '{[a,a]}'::textmultirange;
44select '{[a,a],[a,b]}'::textmultirange;
45select '{[a,b), [b,e]}'::textmultirange;
46select '{[a,d), [b,f]}'::textmultirange;
47select '{[a,a],[b,b]}'::textmultirange;
48-- without canonicalization, we can't join these:
49select '{[a,a], [b,b]}'::textmultirange;
50-- with canonicalization, we can join these:
51select '{[1,2], [3,4]}'::int4multirange;
52select '{[a,a], [b,b], [c,c]}'::textmultirange;
53select '{[a,d], [b,e]}'::textmultirange;
54select '{[a,d), [d,e)}'::textmultirange;
55-- these are allowed but normalize to empty:
56select '{[a,a)}'::textmultirange;
57select '{(a,a]}'::textmultirange;
58select '{(a,a)}'::textmultirange;
59
60--
61-- test the constructor
62---
63select textmultirange();
64select textmultirange(textrange('a', 'c'));
65select textmultirange(textrange('a', 'c'), textrange('f', 'g'));
66select textmultirange(textrange('a', 'c'), textrange('b', 'd'));
67
68--
69-- test casts, both a built-in range type and a user-defined one:
70--
71select 'empty'::int4range::int4multirange;
72select int4range(1, 3)::int4multirange;
73select int4range(1, null)::int4multirange;
74select int4range(null, null)::int4multirange;
75select 'empty'::textrange::textmultirange;
76select textrange('a', 'c')::textmultirange;
77select textrange('a', null)::textmultirange;
78select textrange(null, null)::textmultirange;
79
80--
81-- test unnest(multirange) function
82--
83select unnest(int4multirange(int4range('5', '6'), int4range('1', '2')));
84select unnest(textmultirange(textrange('a', 'b'), textrange('d', 'e')));
85
86--
87-- create some test data and test the operators
88--
89
90CREATE TABLE nummultirange_test (nmr NUMMULTIRANGE);
91CREATE INDEX nummultirange_test_btree ON nummultirange_test(nmr);
92
93INSERT INTO nummultirange_test VALUES('{}');
94INSERT INTO nummultirange_test VALUES('{[,)}');
95INSERT INTO nummultirange_test VALUES('{[3,]}');
96INSERT INTO nummultirange_test VALUES('{[,), [3,]}');
97INSERT INTO nummultirange_test VALUES('{[, 5)}');
98INSERT INTO nummultirange_test VALUES(nummultirange());
99INSERT INTO nummultirange_test VALUES(nummultirange(variadic '{}'::numrange[]));
100INSERT INTO nummultirange_test VALUES(nummultirange(numrange(1.1, 2.2)));
101INSERT INTO nummultirange_test VALUES('{empty}');
102INSERT INTO nummultirange_test VALUES(nummultirange(numrange(1.7, 1.7, '[]'), numrange(1.7, 1.9)));
103INSERT INTO nummultirange_test VALUES(nummultirange(numrange(1.7, 1.7, '[]'), numrange(1.9, 2.1)));
104
105SELECT nmr, isempty(nmr), lower(nmr), upper(nmr) FROM nummultirange_test ORDER BY nmr;
106SELECT nmr, lower_inc(nmr), lower_inf(nmr), upper_inc(nmr), upper_inf(nmr) FROM nummultirange_test ORDER BY nmr;
107
108SELECT * FROM nummultirange_test WHERE nmr = '{}';
109SELECT * FROM nummultirange_test WHERE nmr = '{(,5)}';
110SELECT * FROM nummultirange_test WHERE nmr = '{[3,)}';
111SELECT * FROM nummultirange_test WHERE nmr = '{[1.7,1.7]}';
112SELECT * FROM nummultirange_test WHERE nmr = '{[1.7,1.7],[1.9,2.1)}';
113SELECT * FROM nummultirange_test WHERE nmr < '{}';
114SELECT * FROM nummultirange_test WHERE nmr < '{[-1000.0, -1000.0]}';
115SELECT * FROM nummultirange_test WHERE nmr < '{[0.0, 1.0]}';
116SELECT * FROM nummultirange_test WHERE nmr < '{[1000.0, 1001.0]}';
117SELECT * FROM nummultirange_test WHERE nmr <= '{}';
118SELECT * FROM nummultirange_test WHERE nmr <= '{[3,)}';
119SELECT * FROM nummultirange_test WHERE nmr >= '{}';
120SELECT * FROM nummultirange_test WHERE nmr >= '{[3,)}';
121SELECT * FROM nummultirange_test WHERE nmr > '{}';
122SELECT * FROM nummultirange_test WHERE nmr > '{[-1000.0, -1000.0]}';
123SELECT * FROM nummultirange_test WHERE nmr > '{[0.0, 1.0]}';
124SELECT * FROM nummultirange_test WHERE nmr > '{[1000.0, 1001.0]}';
125SELECT * FROM nummultirange_test WHERE nmr <> '{}';
126SELECT * FROM nummultirange_test WHERE nmr <> '{(,5)}';
127
128select nummultirange(numrange(2.0, 1.0));
129select nummultirange(numrange(5.0, 6.0), numrange(1.0, 2.0));
130
131analyze nummultirange_test;
132
133-- overlaps
134SELECT * FROM nummultirange_test WHERE range_overlaps_multirange(numrange(4.0, 4.2), nmr);
135SELECT * FROM nummultirange_test WHERE numrange(4.0, 4.2) && nmr;
136SELECT * FROM nummultirange_test WHERE multirange_overlaps_range(nmr, numrange(4.0, 4.2));
137SELECT * FROM nummultirange_test WHERE nmr && numrange(4.0, 4.2);
138SELECT * FROM nummultirange_test WHERE multirange_overlaps_multirange(nmr, nummultirange(numrange(4.0, 4.2), numrange(6.0, 7.0)));
139SELECT * FROM nummultirange_test WHERE nmr && nummultirange(numrange(4.0, 4.2), numrange(6.0, 7.0));
140SELECT * FROM nummultirange_test WHERE nmr && nummultirange(numrange(6.0, 7.0));
141SELECT * FROM nummultirange_test WHERE nmr && nummultirange(numrange(6.0, 7.0), numrange(8.0, 9.0));
142
143-- mr contains x
144SELECT * FROM nummultirange_test WHERE multirange_contains_elem(nmr, 4.0);
145SELECT * FROM nummultirange_test WHERE nmr @> 4.0;
146SELECT * FROM nummultirange_test WHERE multirange_contains_range(nmr, numrange(4.0, 4.2));
147SELECT * FROM nummultirange_test WHERE nmr @> numrange(4.0, 4.2);
148SELECT * FROM nummultirange_test WHERE multirange_contains_multirange(nmr, '{[4.0,4.2), [6.0, 8.0)}');
149SELECT * FROM nummultirange_test WHERE nmr @> '{[4.0,4.2), [6.0, 8.0)}'::nummultirange;
150
151-- x is contained by mr
152SELECT * FROM nummultirange_test WHERE elem_contained_by_multirange(4.0, nmr);
153SELECT * FROM nummultirange_test WHERE 4.0 <@ nmr;
154SELECT * FROM nummultirange_test WHERE range_contained_by_multirange(numrange(4.0, 4.2), nmr);
155SELECT * FROM nummultirange_test WHERE numrange(4.0, 4.2) <@ nmr;
156SELECT * FROM nummultirange_test WHERE multirange_contained_by_multirange('{[4.0,4.2), [6.0, 8.0)}', nmr);
157SELECT * FROM nummultirange_test WHERE '{[4.0,4.2), [6.0, 8.0)}'::nummultirange <@ nmr;
158
159-- overlaps
160SELECT 'empty'::numrange && nummultirange();
161SELECT 'empty'::numrange && nummultirange(numrange(1,2));
162SELECT nummultirange() && 'empty'::numrange;
163SELECT nummultirange(numrange(1,2)) && 'empty'::numrange;
164SELECT nummultirange() && nummultirange();
165SELECT nummultirange() && nummultirange(numrange(1,2));
166SELECT nummultirange(numrange(1,2)) && nummultirange();
167SELECT nummultirange(numrange(3,4)) && nummultirange(numrange(1,2), numrange(7,8));
168SELECT nummultirange(numrange(1,2), numrange(7,8)) && nummultirange(numrange(3,4));
169SELECT nummultirange(numrange(3,4)) && nummultirange(numrange(1,2), numrange(3.5,8));
170SELECT nummultirange(numrange(1,2), numrange(3.5,8)) && numrange(3,4);
171SELECT nummultirange(numrange(1,2), numrange(3.5,8)) && nummultirange(numrange(3,4));
172select '{(10,20),(30,40),(50,60)}'::nummultirange && '(42,92)'::numrange;
173
174-- contains
175SELECT nummultirange() @> nummultirange();
176SELECT nummultirange() @> 'empty'::numrange;
177SELECT nummultirange(numrange(null,null)) @> numrange(1,2);
178SELECT nummultirange(numrange(null,null)) @> numrange(null,2);
179SELECT nummultirange(numrange(null,null)) @> numrange(2,null);
180SELECT nummultirange(numrange(null,5)) @> numrange(null,3);
181SELECT nummultirange(numrange(null,5)) @> numrange(null,8);
182SELECT nummultirange(numrange(5,null)) @> numrange(8,null);
183SELECT nummultirange(numrange(5,null)) @> numrange(3,null);
184SELECT nummultirange(numrange(1,5)) @> numrange(8,9);
185SELECT nummultirange(numrange(1,5)) @> numrange(3,9);
186SELECT nummultirange(numrange(1,5)) @> numrange(1,4);
187SELECT nummultirange(numrange(1,5)) @> numrange(1,5);
188SELECT nummultirange(numrange(-4,-2), numrange(1,5)) @> numrange(1,5);
189SELECT nummultirange(numrange(1,5), numrange(8,9)) @> numrange(1,5);
190SELECT nummultirange(numrange(1,5), numrange(8,9)) @> numrange(6,7);
191SELECT nummultirange(numrange(1,5), numrange(6,9)) @> numrange(6,7);
192SELECT '{[1,5)}'::nummultirange @> '{[1,5)}';
193SELECT '{[-4,-2), [1,5)}'::nummultirange @> '{[1,5)}';
194SELECT '{[1,5), [8,9)}'::nummultirange @> '{[1,5)}';
195SELECT '{[1,5), [8,9)}'::nummultirange @> '{[6,7)}';
196SELECT '{[1,5), [6,9)}'::nummultirange @> '{[6,7)}';
197select '{(10,20),(30,40),(50,60)}'::nummultirange @> '(52,56)'::numrange;
198SELECT numrange(null,null) @> nummultirange(numrange(1,2));
199SELECT numrange(null,null) @> nummultirange(numrange(null,2));
200SELECT numrange(null,null) @> nummultirange(numrange(2,null));
201SELECT numrange(null,5) @> nummultirange(numrange(null,3));
202SELECT numrange(null,5) @> nummultirange(numrange(null,8));
203SELECT numrange(5,null) @> nummultirange(numrange(8,null));
204SELECT numrange(5,null) @> nummultirange(numrange(3,null));
205SELECT numrange(1,5) @> nummultirange(numrange(8,9));
206SELECT numrange(1,5) @> nummultirange(numrange(3,9));
207SELECT numrange(1,5) @> nummultirange(numrange(1,4));
208SELECT numrange(1,5) @> nummultirange(numrange(1,5));
209SELECT numrange(1,9) @> nummultirange(numrange(-4,-2), numrange(1,5));
210SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(8,9));
211SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,9));
212SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,10));
213SELECT '{[1,9)}' @> '{[1,5)}'::nummultirange;
214SELECT '{[1,9)}' @> '{[-4,-2), [1,5)}'::nummultirange;
215SELECT '{[1,9)}' @> '{[1,5), [8,9)}'::nummultirange;
216SELECT '{[1,9)}' @> '{[1,5), [6,9)}'::nummultirange;
217SELECT '{[1,9)}' @> '{[1,5), [6,10)}'::nummultirange;
218
219-- is contained by
220SELECT nummultirange() <@ nummultirange();
221SELECT 'empty'::numrange <@ nummultirange();
222SELECT numrange(1,2) <@ nummultirange(numrange(null,null));
223SELECT numrange(null,2) <@ nummultirange(numrange(null,null));
224SELECT numrange(2,null) <@ nummultirange(numrange(null,null));
225SELECT numrange(null,3) <@ nummultirange(numrange(null,5));
226SELECT numrange(null,8) <@ nummultirange(numrange(null,5));
227SELECT numrange(8,null) <@ nummultirange(numrange(5,null));
228SELECT numrange(3,null) <@ nummultirange(numrange(5,null));
229SELECT numrange(8,9) <@ nummultirange(numrange(1,5));
230SELECT numrange(3,9) <@ nummultirange(numrange(1,5));
231SELECT numrange(1,4) <@ nummultirange(numrange(1,5));
232SELECT numrange(1,5) <@ nummultirange(numrange(1,5));
233SELECT numrange(1,5) <@ nummultirange(numrange(-4,-2), numrange(1,5));
234SELECT numrange(1,5) <@ nummultirange(numrange(1,5), numrange(8,9));
235SELECT numrange(6,7) <@ nummultirange(numrange(1,5), numrange(8,9));
236SELECT numrange(6,7) <@ nummultirange(numrange(1,5), numrange(6,9));
237SELECT '{[1,5)}' <@ '{[1,5)}'::nummultirange;
238SELECT '{[1,5)}' <@ '{[-4,-2), [1,5)}'::nummultirange;
239SELECT '{[1,5)}' <@ '{[1,5), [8,9)}'::nummultirange;
240SELECT '{[6,7)}' <@ '{[1,5), [8,9)}'::nummultirange;
241SELECT '{[6,7)}' <@ '{[1,5), [6,9)}'::nummultirange;
242SELECT nummultirange(numrange(1,2)) <@ numrange(null,null);
243SELECT nummultirange(numrange(null,2)) <@ numrange(null,null);
244SELECT nummultirange(numrange(2,null)) <@ numrange(null,null);
245SELECT nummultirange(numrange(null,3)) <@ numrange(null,5);
246SELECT nummultirange(numrange(null,8)) <@ numrange(null,5);
247SELECT nummultirange(numrange(8,null)) <@ numrange(5,null);
248SELECT nummultirange(numrange(3,null)) <@ numrange(5,null);
249SELECT nummultirange(numrange(8,9)) <@ numrange(1,5);
250SELECT nummultirange(numrange(3,9)) <@ numrange(1,5);
251SELECT nummultirange(numrange(1,4)) <@ numrange(1,5);
252SELECT nummultirange(numrange(1,5)) <@ numrange(1,5);
253SELECT nummultirange(numrange(-4,-2), numrange(1,5)) <@ numrange(1,9);
254SELECT nummultirange(numrange(1,5), numrange(8,9)) <@ numrange(1,9);
255SELECT nummultirange(numrange(1,5), numrange(6,9)) <@ numrange(1,9);
256SELECT nummultirange(numrange(1,5), numrange(6,10)) <@ numrange(1,9);
257SELECT '{[1,5)}'::nummultirange <@ '{[1,9)}';
258SELECT '{[-4,-2), [1,5)}'::nummultirange <@ '{[1,9)}';
259SELECT '{[1,5), [8,9)}'::nummultirange <@ '{[1,9)}';
260SELECT '{[1,5), [6,9)}'::nummultirange <@ '{[1,9)}';
261SELECT '{[1,5), [6,10)}'::nummultirange <@ '{[1,9)}';
262
263-- overleft
264SELECT 'empty'::numrange &< nummultirange();
265SELECT 'empty'::numrange &< nummultirange(numrange(1,2));
266SELECT nummultirange() &< 'empty'::numrange;
267SELECT nummultirange(numrange(1,2)) &< 'empty'::numrange;
268SELECT nummultirange() &< nummultirange();
269SELECT nummultirange(numrange(1,2)) &< nummultirange();
270SELECT nummultirange() &< nummultirange(numrange(1,2));
271SELECT numrange(6,7) &< nummultirange(numrange(3,4));
272SELECT numrange(1,2) &< nummultirange(numrange(3,4));
273SELECT numrange(1,4) &< nummultirange(numrange(3,4));
274SELECT numrange(1,6) &< nummultirange(numrange(3,4));
275SELECT numrange(3.5,6) &< nummultirange(numrange(3,4));
276SELECT nummultirange(numrange(6,7)) &< numrange(3,4);
277SELECT nummultirange(numrange(1,2)) &< numrange(3,4);
278SELECT nummultirange(numrange(1,4)) &< numrange(3,4);
279SELECT nummultirange(numrange(1,6)) &< numrange(3,4);
280SELECT nummultirange(numrange(3.5,6)) &< numrange(3,4);
281SELECT nummultirange(numrange(6,7)) &< nummultirange(numrange(3,4));
282SELECT nummultirange(numrange(1,2)) &< nummultirange(numrange(3,4));
283SELECT nummultirange(numrange(1,4)) &< nummultirange(numrange(3,4));
284SELECT nummultirange(numrange(1,6)) &< nummultirange(numrange(3,4));
285SELECT nummultirange(numrange(3.5,6)) &< nummultirange(numrange(3,4));
286
287-- overright
288SELECT nummultirange() &> 'empty'::numrange;
289SELECT nummultirange(numrange(1,2)) &> 'empty'::numrange;
290SELECT 'empty'::numrange &> nummultirange();
291SELECT 'empty'::numrange &> nummultirange(numrange(1,2));
292SELECT nummultirange() &> nummultirange();
293SELECT nummultirange() &> nummultirange(numrange(1,2));
294SELECT nummultirange(numrange(1,2)) &> nummultirange();
295SELECT nummultirange(numrange(3,4)) &> numrange(6,7);
296SELECT nummultirange(numrange(3,4)) &> numrange(1,2);
297SELECT nummultirange(numrange(3,4)) &> numrange(1,4);
298SELECT nummultirange(numrange(3,4)) &> numrange(1,6);
299SELECT nummultirange(numrange(3,4)) &> numrange(3.5,6);
300SELECT numrange(3,4) &> nummultirange(numrange(6,7));
301SELECT numrange(3,4) &> nummultirange(numrange(1,2));
302SELECT numrange(3,4) &> nummultirange(numrange(1,4));
303SELECT numrange(3,4) &> nummultirange(numrange(1,6));
304SELECT numrange(3,4) &> nummultirange(numrange(3.5,6));
305SELECT nummultirange(numrange(3,4)) &> nummultirange(numrange(6,7));
306SELECT nummultirange(numrange(3,4)) &> nummultirange(numrange(1,2));
307SELECT nummultirange(numrange(3,4)) &> nummultirange(numrange(1,4));
308SELECT nummultirange(numrange(3,4)) &> nummultirange(numrange(1,6));
309SELECT nummultirange(numrange(3,4)) &> nummultirange(numrange(3.5,6));
310
311-- meets
312SELECT 'empty'::numrange -|- nummultirange();
313SELECT 'empty'::numrange -|- nummultirange(numrange(1,2));
314SELECT nummultirange() -|- 'empty'::numrange;
315SELECT nummultirange(numrange(1,2)) -|- 'empty'::numrange;
316SELECT nummultirange() -|- nummultirange();
317SELECT nummultirange(numrange(1,2)) -|- nummultirange();
318SELECT nummultirange() -|- nummultirange(numrange(1,2));
319SELECT numrange(1,2) -|- nummultirange(numrange(2,4));
320SELECT numrange(1,2) -|- nummultirange(numrange(3,4));
321SELECT nummultirange(numrange(1,2)) -|- numrange(2,4);
322SELECT nummultirange(numrange(1,2)) -|- numrange(3,4);
323SELECT nummultirange(numrange(1,2)) -|- nummultirange(numrange(2,4));
324SELECT nummultirange(numrange(1,2)) -|- nummultirange(numrange(3,4));
325SELECT nummultirange(numrange(1,2), numrange(5,6)) -|- nummultirange(numrange(3,4));
326SELECT nummultirange(numrange(1,2), numrange(5,6)) -|- nummultirange(numrange(6,7));
327SELECT nummultirange(numrange(1,2), numrange(5,6)) -|- nummultirange(numrange(8,9));
328SELECT nummultirange(numrange(1,2)) -|- nummultirange(numrange(2,4), numrange(6,7));
329
330-- strictly left
331select 'empty'::numrange << nummultirange();
332select numrange(1,2) << nummultirange();
333select numrange(1,2) << nummultirange(numrange(3,4));
334select numrange(1,2) << nummultirange(numrange(0,4));
335select numrange(1,2) << nummultirange(numrange(0,4), numrange(7,8));
336select nummultirange() << 'empty'::numrange;
337select nummultirange() << numrange(1,2);
338select nummultirange(numrange(3,4)) << numrange(3,6);
339select nummultirange(numrange(0,2)) << numrange(3,6);
340select nummultirange(numrange(0,2), numrange(7,8)) << numrange(3,6);
341select nummultirange(numrange(-4,-2), numrange(0,2)) << numrange(3,6);
342select nummultirange() << nummultirange();
343select nummultirange() << nummultirange(numrange(1,2));
344select nummultirange(numrange(1,2)) << nummultirange();
345select nummultirange(numrange(1,2)) << nummultirange(numrange(1,2));
346select nummultirange(numrange(1,2)) << nummultirange(numrange(3,4));
347select nummultirange(numrange(1,2)) << nummultirange(numrange(3,4), numrange(7,8));
348select nummultirange(numrange(1,2), numrange(4,5)) << nummultirange(numrange(3,4), numrange(7,8));
349
350-- strictly right
351select nummultirange() >> 'empty'::numrange;
352select nummultirange() >> numrange(1,2);
353select nummultirange(numrange(3,4)) >> numrange(1,2);
354select nummultirange(numrange(0,4)) >> numrange(1,2);
355select nummultirange(numrange(0,4), numrange(7,8)) >> numrange(1,2);
356select 'empty'::numrange >> nummultirange();
357select numrange(1,2) >> nummultirange();
358select numrange(3,6) >> nummultirange(numrange(3,4));
359select numrange(3,6) >> nummultirange(numrange(0,2));
360select numrange(3,6) >> nummultirange(numrange(0,2), numrange(7,8));
361select numrange(3,6) >> nummultirange(numrange(-4,-2), numrange(0,2));
362select nummultirange() >> nummultirange();
363select nummultirange(numrange(1,2)) >> nummultirange();
364select nummultirange() >> nummultirange(numrange(1,2));
365select nummultirange(numrange(1,2)) >> nummultirange(numrange(1,2));
366select nummultirange(numrange(3,4)) >> nummultirange(numrange(1,2));
367select nummultirange(numrange(3,4), numrange(7,8)) >> nummultirange(numrange(1,2));
368select nummultirange(numrange(3,4), numrange(7,8)) >> nummultirange(numrange(1,2), numrange(4,5));
369
370-- union
371SELECT nummultirange() + nummultirange();
372SELECT nummultirange() + nummultirange(numrange(1,2));
373SELECT nummultirange(numrange(1,2)) + nummultirange();
374SELECT nummultirange(numrange(1,2)) + nummultirange(numrange(1,2));
375SELECT nummultirange(numrange(1,2)) + nummultirange(numrange(2,4));
376SELECT nummultirange(numrange(1,2)) + nummultirange(numrange(3,4));
377SELECT nummultirange(numrange(1,2), numrange(4,5)) + nummultirange(numrange(2,4));
378SELECT nummultirange(numrange(1,2), numrange(4,5)) + nummultirange(numrange(3,4));
379SELECT nummultirange(numrange(1,2), numrange(4,5)) + nummultirange(numrange(0,9));
380
381-- merge
382SELECT range_merge(nummultirange());
383SELECT range_merge(nummultirange(numrange(1,2)));
384SELECT range_merge(nummultirange(numrange(1,2), numrange(7,8)));
385
386-- minus
387SELECT nummultirange() - nummultirange();
388SELECT nummultirange() - nummultirange(numrange(1,2));
389SELECT nummultirange(numrange(1,2)) - nummultirange();
390SELECT nummultirange(numrange(1,2), numrange(3,4)) - nummultirange();
391SELECT nummultirange(numrange(1,2)) - nummultirange(numrange(1,2));
392SELECT nummultirange(numrange(1,2)) - nummultirange(numrange(2,4));
393SELECT nummultirange(numrange(1,2)) - nummultirange(numrange(3,4));
394SELECT nummultirange(numrange(1,4)) - nummultirange(numrange(1,2));
395SELECT nummultirange(numrange(1,4)) - nummultirange(numrange(2,3));
396SELECT nummultirange(numrange(1,4)) - nummultirange(numrange(0,8));
397SELECT nummultirange(numrange(1,4)) - nummultirange(numrange(0,2));
398SELECT nummultirange(numrange(1,8)) - nummultirange(numrange(0,2), numrange(3,4));
399SELECT nummultirange(numrange(1,8)) - nummultirange(numrange(2,3), numrange(5,null));
400SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(-2,0));
401SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(2,4));
402SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(3,5));
403SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(0,9));
404SELECT nummultirange(numrange(1,3), numrange(4,5)) - nummultirange(numrange(2,9));
405SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(8,9));
406SELECT nummultirange(numrange(1,2), numrange(4,5)) - nummultirange(numrange(-2,0), numrange(8,9));
407
408-- intersection
409SELECT nummultirange() * nummultirange();
410SELECT nummultirange() * nummultirange(numrange(1,2));
411SELECT nummultirange(numrange(1,2)) * nummultirange();
412SELECT '{[1,3)}'::nummultirange * '{[1,5)}'::nummultirange;
413SELECT '{[1,3)}'::nummultirange * '{[0,5)}'::nummultirange;
414SELECT '{[1,3)}'::nummultirange * '{[0,2)}'::nummultirange;
415SELECT '{[1,3)}'::nummultirange * '{[2,5)}'::nummultirange;
416SELECT '{[1,4)}'::nummultirange * '{[2,3)}'::nummultirange;
417SELECT '{[1,4)}'::nummultirange * '{[0,2), [3,5)}'::nummultirange;
418SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,8), [9,12)}'::nummultirange;
419SELECT '{[1,4), [7,10)}'::nummultirange * '{[9,12)}'::nummultirange;
420SELECT '{[1,4), [7,10)}'::nummultirange * '{[-5,-4), [5,6), [9,12)}'::nummultirange;
421SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,2), [3,8), [9,12)}'::nummultirange;
422SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,2), [3,8), [9,12)}'::nummultirange;
423
424-- test GiST index
425create table test_multirange_gist(mr int4multirange);
426insert into test_multirange_gist select int4multirange(int4range(g, g+10),int4range(g+20, g+30),int4range(g+40, g+50)) from generate_series(1,2000) g;
427insert into test_multirange_gist select '{}'::int4multirange from generate_series(1,500) g;
428insert into test_multirange_gist select int4multirange(int4range(g, g+10000)) from generate_series(1,1000) g;
429insert into test_multirange_gist select int4multirange(int4range(NULL, g*10, '(]'), int4range(g*10, g*20, '(]')) from generate_series(1,100) g;
430insert into test_multirange_gist select int4multirange(int4range(g*10, g*20, '(]'), int4range(g*20, NULL, '(]')) from generate_series(1,100) g;
431create index test_mulrirange_gist_idx on test_multirange_gist using gist (mr);
432
433-- test statistics and selectivity estimation as well
434--
435-- We don't check the accuracy of selectivity estimation, but at least check
436-- it doesn't fall.
437analyze test_multirange_gist;
438
439-- first, verify non-indexed results
440SET enable_seqscan    = t;
441SET enable_indexscan  = f;
442SET enable_bitmapscan = f;
443
444select count(*) from test_multirange_gist where mr = '{}'::int4multirange;
445select count(*) from test_multirange_gist where mr @> 'empty'::int4range;
446select count(*) from test_multirange_gist where mr && 'empty'::int4range;
447select count(*) from test_multirange_gist where mr <@ 'empty'::int4range;
448select count(*) from test_multirange_gist where mr << 'empty'::int4range;
449select count(*) from test_multirange_gist where mr >> 'empty'::int4range;
450select count(*) from test_multirange_gist where mr &< 'empty'::int4range;
451select count(*) from test_multirange_gist where mr &> 'empty'::int4range;
452select count(*) from test_multirange_gist where mr -|- 'empty'::int4range;
453select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
454select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
455select count(*) from test_multirange_gist where mr && '{}'::int4multirange;
456select count(*) from test_multirange_gist where mr <@ '{}'::int4multirange;
457select count(*) from test_multirange_gist where mr << '{}'::int4multirange;
458select count(*) from test_multirange_gist where mr >> '{}'::int4multirange;
459select count(*) from test_multirange_gist where mr &< '{}'::int4multirange;
460select count(*) from test_multirange_gist where mr &> '{}'::int4multirange;
461select count(*) from test_multirange_gist where mr -|- '{}'::int4multirange;
462
463select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60));
464select count(*) from test_multirange_gist where mr @> 10;
465select count(*) from test_multirange_gist where mr @> int4range(10,20);
466select count(*) from test_multirange_gist where mr && int4range(10,20);
467select count(*) from test_multirange_gist where mr <@ int4range(10,50);
468select count(*) from test_multirange_gist where mr << int4range(100,500);
469select count(*) from test_multirange_gist where mr >> int4range(100,500);
470select count(*) from test_multirange_gist where mr &< int4range(100,500);
471select count(*) from test_multirange_gist where mr &> int4range(100,500);
472select count(*) from test_multirange_gist where mr -|- int4range(100,500);
473select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
474select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40));
475select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange;
476select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange;
477select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500));
478select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500));
479select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500));
480select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500));
481select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500));
482
483-- now check same queries using index
484SET enable_seqscan    = f;
485SET enable_indexscan  = t;
486SET enable_bitmapscan = f;
487
488select count(*) from test_multirange_gist where mr = '{}'::int4multirange;
489select count(*) from test_multirange_gist where mr @> 'empty'::int4range;
490select count(*) from test_multirange_gist where mr && 'empty'::int4range;
491select count(*) from test_multirange_gist where mr <@ 'empty'::int4range;
492select count(*) from test_multirange_gist where mr << 'empty'::int4range;
493select count(*) from test_multirange_gist where mr >> 'empty'::int4range;
494select count(*) from test_multirange_gist where mr &< 'empty'::int4range;
495select count(*) from test_multirange_gist where mr &> 'empty'::int4range;
496select count(*) from test_multirange_gist where mr -|- 'empty'::int4range;
497select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
498select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
499select count(*) from test_multirange_gist where mr && '{}'::int4multirange;
500select count(*) from test_multirange_gist where mr <@ '{}'::int4multirange;
501select count(*) from test_multirange_gist where mr << '{}'::int4multirange;
502select count(*) from test_multirange_gist where mr >> '{}'::int4multirange;
503select count(*) from test_multirange_gist where mr &< '{}'::int4multirange;
504select count(*) from test_multirange_gist where mr &> '{}'::int4multirange;
505select count(*) from test_multirange_gist where mr -|- '{}'::int4multirange;
506
507select count(*) from test_multirange_gist where mr @> 'empty'::int4range;
508select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60));
509select count(*) from test_multirange_gist where mr @> 10;
510select count(*) from test_multirange_gist where mr @> int4range(10,20);
511select count(*) from test_multirange_gist where mr && int4range(10,20);
512select count(*) from test_multirange_gist where mr <@ int4range(10,50);
513select count(*) from test_multirange_gist where mr << int4range(100,500);
514select count(*) from test_multirange_gist where mr >> int4range(100,500);
515select count(*) from test_multirange_gist where mr &< int4range(100,500);
516select count(*) from test_multirange_gist where mr &> int4range(100,500);
517select count(*) from test_multirange_gist where mr -|- int4range(100,500);
518select count(*) from test_multirange_gist where mr @> '{}'::int4multirange;
519select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40));
520select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange;
521select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange;
522select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500));
523select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500));
524select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500));
525select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500));
526select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500));
527
528drop table test_multirange_gist;
529
530--
531-- range_agg function
532--
533create table reservations ( room_id integer not null, booked_during daterange );
534insert into reservations values
535-- 1: has a meets and a gap
536(1, daterange('2018-07-01', '2018-07-07')),
537(1, daterange('2018-07-07', '2018-07-14')),
538(1, daterange('2018-07-20', '2018-07-22')),
539-- 2: just a single row
540(2, daterange('2018-07-01', '2018-07-03')),
541-- 3: one null range
542(3, NULL),
543-- 4: two null ranges
544(4, NULL),
545(4, NULL),
546-- 5: a null range and a non-null range
547(5, NULL),
548(5, daterange('2018-07-01', '2018-07-03')),
549-- 6: has overlap
550(6, daterange('2018-07-01', '2018-07-07')),
551(6, daterange('2018-07-05', '2018-07-10')),
552-- 7: two ranges that meet: no gap or overlap
553(7, daterange('2018-07-01', '2018-07-07')),
554(7, daterange('2018-07-07', '2018-07-14')),
555-- 8: an empty range
556(8, 'empty'::daterange)
557;
558SELECT   room_id, range_agg(booked_during)
559FROM     reservations
560GROUP BY room_id
561ORDER BY room_id;
562
563-- range_agg on a custom range type too
564SELECT  range_agg(r)
565FROM    (VALUES
566          ('[a,c]'::textrange),
567          ('[b,b]'::textrange),
568          ('[c,f]'::textrange),
569          ('[g,h)'::textrange),
570          ('[h,j)'::textrange)
571        ) t(r);
572
573select range_intersect_agg(nmr) from nummultirange_test;
574select range_intersect_agg(nmr) from nummultirange_test where false;
575-- test with just one input:
576select range_intersect_agg(nmr) from (values ('{[1,2]}'::nummultirange)) t(nmr);
577select range_intersect_agg(nmr) from nummultirange_test where nmr @> 4.0;
578
579create table nummultirange_test2(nmr nummultirange);
580create index nummultirange_test2_hash_idx on nummultirange_test2 using hash (nmr);
581
582INSERT INTO nummultirange_test2 VALUES('{[, 5)}');
583INSERT INTO nummultirange_test2 VALUES(nummultirange(numrange(1.1, 2.2)));
584INSERT INTO nummultirange_test2 VALUES(nummultirange(numrange(1.1, 2.2)));
585INSERT INTO nummultirange_test2 VALUES(nummultirange(numrange(1.1, 2.2,'()')));
586INSERT INTO nummultirange_test2 VALUES('{}');
587
588select * from nummultirange_test2 where nmr = '{}';
589select * from nummultirange_test2 where nmr = nummultirange(numrange(1.1, 2.2));
590select * from nummultirange_test2 where nmr = nummultirange(numrange(1.1, 2.3));
591
592set enable_nestloop=t;
593set enable_hashjoin=f;
594set enable_mergejoin=f;
595select * from nummultirange_test natural join nummultirange_test2 order by nmr;
596set enable_nestloop=f;
597set enable_hashjoin=t;
598set enable_mergejoin=f;
599select * from nummultirange_test natural join nummultirange_test2 order by nmr;
600set enable_nestloop=f;
601set enable_hashjoin=f;
602set enable_mergejoin=t;
603select * from nummultirange_test natural join nummultirange_test2 order by nmr;
604
605set enable_nestloop to default;
606set enable_hashjoin to default;
607set enable_mergejoin to default;
608
609DROP TABLE nummultirange_test2;
610
611--
612-- Test user-defined multirange of floats
613--
614
615select '{[123.001, 5.e9)}'::float8multirange @> 888.882::float8;
616create table float8multirange_test(f8mr float8multirange, i int);
617insert into float8multirange_test values(float8multirange(float8range(-100.00007, '1.111113e9')), 42);
618select * from float8multirange_test;
619drop table float8multirange_test;
620
621--
622-- Test multirange types over domains
623--
624
625create domain mydomain as int4;
626create type mydomainrange as range(subtype=mydomain);
627select '{[4,50)}'::mydomainmultirange @> 7::mydomain;
628drop domain mydomain cascade;
629
630--
631-- Test domains over multirange types
632--
633
634create domain restrictedmultirange as int4multirange check (upper(value) < 10);
635select '{[4,5)}'::restrictedmultirange @> 7;
636select '{[4,50)}'::restrictedmultirange @> 7; -- should fail
637drop domain restrictedmultirange;
638
639---
640-- Check automatic naming of multiranges
641---
642
643create type intr as range(subtype=int);
644select intr_multirange(intr(1,10));
645drop type intr;
646create type intmultirange as (x int, y int);
647create type intrange as range(subtype=int); -- should fail
648drop type intmultirange;
649create type intr_multirange as (x int, y int);
650create type intr as range(subtype=int); -- should fail
651drop type intr_multirange;
652
653--
654-- Test multiple multirange types over the same subtype and manual naming of
655-- the multirange type.
656--
657
658-- should fail
659create type textrange1 as range(subtype=text, multirange_type_name=int, collation="C");
660-- should pass
661create type textrange1 as range(subtype=text, multirange_type_name=multirange_of_text, collation="C");
662-- should pass, because existing _textrange1 is automatically renamed
663create type textrange2 as range(subtype=text, multirange_type_name=_textrange1, collation="C");
664
665select multirange_of_text(textrange2('a','Z'));  -- should fail
666select multirange_of_text(textrange1('a','Z')) @> 'b'::text;
667select unnest(multirange_of_text(textrange1('a','b'), textrange1('d','e')));
668select _textrange1(textrange2('a','z')) @> 'b'::text;
669
670drop type textrange1;
671drop type textrange2;
672
673--
674-- Test polymorphic type system
675--
676
677create function anyarray_anymultirange_func(a anyarray, r anymultirange)
678  returns anyelement as 'select $1[1] + lower($2);' language sql;
679
680select anyarray_anymultirange_func(ARRAY[1,2], int4multirange(int4range(10,20)));
681
682-- should fail
683select anyarray_anymultirange_func(ARRAY[1,2], nummultirange(numrange(10,20)));
684
685drop function anyarray_anymultirange_func(anyarray, anymultirange);
686
687-- should fail
688create function bogus_func(anyelement)
689  returns anymultirange as 'select int4multirange(int4range(1,10))' language sql;
690
691-- should fail
692create function bogus_func(int)
693  returns anymultirange as 'select int4multirange(int4range(1,10))' language sql;
694
695create function range_add_bounds(anymultirange)
696  returns anyelement as 'select lower($1) + upper($1)' language sql;
697
698select range_add_bounds(int4multirange(int4range(1, 17)));
699select range_add_bounds(nummultirange(numrange(1.0001, 123.123)));
700
701create function multirangetypes_sql(q anymultirange, b anyarray, out c anyelement)
702  as $$ select upper($1) + $2[1] $$
703  language sql;
704
705select multirangetypes_sql(int4multirange(int4range(1,10)), ARRAY[2,20]);
706select multirangetypes_sql(nummultirange(numrange(1,10)), ARRAY[2,20]);  -- match failure
707
708create function anycompatiblearray_anycompatiblemultirange_func(a anycompatiblearray, mr anycompatiblemultirange)
709  returns anycompatible as 'select $1[1] + lower($2);' language sql;
710
711select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1,2], multirange(int4range(10,20)));
712
713select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1,2], multirange(numrange(10,20)));
714
715-- should fail
716select anycompatiblearray_anycompatiblemultirange_func(ARRAY[1.1,2], multirange(int4range(10,20)));
717
718drop function anycompatiblearray_anycompatiblemultirange_func(anycompatiblearray, anycompatiblemultirange);
719
720create function anycompatiblerange_anycompatiblemultirange_func(r anycompatiblerange, mr anycompatiblemultirange)
721  returns anycompatible as 'select lower($1) + lower($2);' language sql;
722
723select anycompatiblerange_anycompatiblemultirange_func(int4range(1,2), multirange(int4range(10,20)));
724
725-- should fail
726select anycompatiblerange_anycompatiblemultirange_func(numrange(1,2), multirange(int4range(10,20)));
727
728drop function anycompatiblerange_anycompatiblemultirange_func(anycompatiblerange, anycompatiblemultirange);
729
730-- should fail
731create function bogus_func(anycompatible)
732  returns anycompatiblerange as 'select int4range(1,10)' language sql;
733
734--
735-- Arrays of multiranges
736--
737
738select ARRAY[nummultirange(numrange(1.1, 1.2)), nummultirange(numrange(12.3, 155.5))];
739
740create table i8mr_array (f1 int, f2 int8multirange[]);
741insert into i8mr_array values (42, array[int8multirange(int8range(1,10)), int8multirange(int8range(2,20))]);
742select * from i8mr_array;
743drop table i8mr_array;
744
745--
746-- Multiranges of arrays
747--
748
749select arraymultirange(arrayrange(ARRAY[1,2], ARRAY[2,1]));
750select arraymultirange(arrayrange(ARRAY[2,1], ARRAY[1,2]));  -- fail
751
752select array[1,1] <@ arraymultirange(arrayrange(array[1,2], array[2,1]));
753select array[1,3] <@ arraymultirange(arrayrange(array[1,2], array[2,1]));
754
755--
756-- Ranges of composites
757--
758
759create type two_ints as (a int, b int);
760create type two_ints_range as range (subtype = two_ints);
761
762-- with force_parallel_mode on, this exercises tqueue.c's range remapping
763select *, row_to_json(upper(t)) as u from
764  (values (two_ints_multirange(two_ints_range(row(1,2), row(3,4)))),
765          (two_ints_multirange(two_ints_range(row(5,6), row(7,8))))) v(t);
766
767drop type two_ints cascade;
768
769--
770-- Check behavior when subtype lacks a hash function
771--
772
773set enable_sort = off;  -- try to make it pick a hash setop implementation
774
775select '{(2,5)}'::cashmultirange except select '{(5,6)}'::cashmultirange;
776
777reset enable_sort;
778
779--
780-- OUT/INOUT/TABLE functions
781--
782
783-- infer anymultirange from anymultirange
784create function mr_outparam_succeed(i anymultirange, out r anymultirange, out t text)
785  as $$ select $1, 'foo'::text $$ language sql;
786
787select * from mr_outparam_succeed(int4multirange(int4range(1,2)));
788
789-- infer anyarray from anymultirange
790create function mr_outparam_succeed2(i anymultirange, out r anyarray, out t text)
791  as $$ select ARRAY[upper($1)], 'foo'::text $$ language sql;
792
793select * from mr_outparam_succeed2(int4multirange(int4range(1,2)));
794
795-- infer anyrange from anymultirange
796create function mr_outparam_succeed3(i anymultirange, out r anyrange, out t text)
797  as $$ select range_merge($1), 'foo'::text $$ language sql;
798select * from mr_outparam_succeed3(int4multirange(int4range(1,2)));
799
800-- infer anymultirange from anyrange
801create function mr_outparam_succeed4(i anyrange, out r anymultirange, out t text)
802  as $$ select multirange($1), 'foo'::text $$ language sql;
803
804select * from mr_outparam_succeed4(int4range(1,2));
805
806-- infer anyelement from anymultirange
807create function mr_inoutparam_succeed(out i anyelement, inout r anymultirange)
808  as $$ select upper($1), $1 $$ language sql;
809
810select * from mr_inoutparam_succeed(int4multirange(int4range(1,2)));
811
812-- infer anyelement+anymultirange from anyelement+anymultirange
813create function mr_table_succeed(i anyelement, r anymultirange) returns table(i anyelement, r anymultirange)
814  as $$ select $1, $2 $$ language sql;
815
816select * from mr_table_succeed(123, int4multirange(int4range(1,11)));
817
818-- use anymultirange in plpgsql
819create function mr_polymorphic(i anyrange) returns anymultirange
820  as $$ begin return multirange($1); end; $$ language plpgsql;
821select mr_polymorphic(int4range(1, 4));
822
823-- should fail
824create function mr_outparam_fail(i anyelement, out r anymultirange, out t text)
825  as $$ select '[1,10]', 'foo' $$ language sql;
826
827--should fail
828create function mr_inoutparam_fail(inout i anyelement, out r anymultirange)
829  as $$ select $1, '[1,10]' $$ language sql;
830
831--should fail
832create function mr_table_fail(i anyelement) returns table(i anyelement, r anymultirange)
833  as $$ select $1, '[1,10]' $$ language sql;
834