17 -- boxes are specified by two points, given by four floats x1,y1,x2,y2
18 CREATE TABLE BOX_TBL (f1 box);
19 INSERT INTO BOX_TBL (f1) VALUES ('(2.0,2.0,0.0,0.0)');
20 INSERT INTO BOX_TBL (f1) VALUES ('(1.0,1.0,3.0,3.0)');
21 INSERT INTO BOX_TBL (f1) VALUES ('((-8, 2), (-2, -10))');
22 -- degenerate cases where the box is a line or a point
23 -- note that lines and points boxes all have zero area
24 INSERT INTO BOX_TBL (f1) VALUES ('(2.5, 2.5, 2.5,3.5)');
25 INSERT INTO BOX_TBL (f1) VALUES ('(3.0, 3.0,3.0,3.0)');
26 -- badly formatted box inputs
27 INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
28 ERROR: invalid input syntax for type box: "(2.3, 4.5)"
29 LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)');
31 INSERT INTO BOX_TBL (f1) VALUES ('[1, 2, 3, 4)');
32 ERROR: invalid input syntax for type box: "[1, 2, 3, 4)"
33 LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('[1, 2, 3, 4)');
35 INSERT INTO BOX_TBL (f1) VALUES ('(1, 2, 3, 4]');
36 ERROR: invalid input syntax for type box: "(1, 2, 3, 4]"
37 LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(1, 2, 3, 4]');
39 INSERT INTO BOX_TBL (f1) VALUES ('(1, 2, 3, 4) x');
40 ERROR: invalid input syntax for type box: "(1, 2, 3, 4) x"
41 LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('(1, 2, 3, 4) x');
43 INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
44 ERROR: invalid input syntax for type box: "asdfasdf(ad"
45 LINE 1: INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad');
47 SELECT * FROM BOX_TBL;
57 SELECT b.*, area(b.f1) as barea
60 ---------------------+-------
64 (2.5,3.5),(2.5,2.5) | 0
71 WHERE b.f1 && box '(2.5,2.5,1.0,1.0)';
79 -- left-or-overlap (x only)
82 WHERE b1.f1 &< box '(2.0,2.0,2.5,2.5)';
90 -- right-or-overlap (x only)
93 WHERE b1.f1 &> box '(2.0,2.0,2.5,2.5)';
103 WHERE b.f1 << box '(3.0,3.0,5.0,5.0)';
105 ---------------------
114 WHERE b.f1 <= box '(3.0,3.0,5.0,5.0)';
116 ---------------------
126 WHERE b.f1 < box '(3.0,3.0,5.0,5.0)';
128 ---------------------
136 WHERE b.f1 = box '(3.0,3.0,5.0,5.0)';
145 FROM BOX_TBL b -- zero area
146 WHERE b.f1 > box '(3.5,3.0,4.5,3.0)';
156 FROM BOX_TBL b -- zero area
157 WHERE b.f1 >= box '(3.5,3.0,4.5,3.0)';
159 ---------------------
170 WHERE box '(3.0,3.0,5.0,5.0)' >> b.f1;
172 ---------------------
181 WHERE b.f1 <@ box '(0,0,3,3)';
192 WHERE box '(0,0,3,3)' @> b.f1;
203 WHERE box '(1,1,3,3)' ~= b.f1;
209 -- center of box, left unary operator
210 SELECT @@(b1.f1) AS p
223 FROM BOX_TBL b1, BOX_TBL b2
224 WHERE b1.f1 @> b2.f1 and not b1.f1 ~= b2.f1;
226 -------------+-------------
227 (3,3),(1,1) | (3,3),(3,3)
230 SELECT height(f1), width(f1) FROM BOX_TBL;
241 -- Test the SP-GiST index
243 CREATE TEMPORARY TABLE box_temp (f1 box);
245 SELECT box(point(i, i), point(i * 2, i * 2))
246 FROM generate_series(1, 50) AS i;
247 CREATE INDEX box_spgist ON box_temp USING spgist (f1);
251 ('(-3,4.3333333333)(40,1)'),
252 ('(0,100)(0,infinity)'),
253 ('(-infinity,0)(0,infinity)'),
254 ('(-infinity,-infinity)(infinity,infinity)');
255 SET enable_seqscan = false;
256 SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
258 ----------------------------
265 (0,Infinity),(-Infinity,0)
268 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)';
270 ----------------------------------------------
271 Index Only Scan using box_spgist on box_temp
272 Index Cond: (f1 << '(30,40),(10,20)'::box)
275 SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
277 ----------------------------
285 (0,Infinity),(-Infinity,0)
288 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)';
290 ----------------------------------------------------
291 Index Only Scan using box_spgist on box_temp
292 Index Cond: (f1 &< '(10,100),(5,4.333334)'::box)
295 SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
297 -------------------------------------------
314 (Infinity,Infinity),(-Infinity,-Infinity)
317 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)';
319 ----------------------------------------------
320 Index Only Scan using box_spgist on box_temp
321 Index Cond: (f1 && '(25,30),(15,20)'::box)
324 SELECT * FROM box_temp WHERE f1 &> '(40,30),(45,50)';
340 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &> '(40,30),(45,50)';
342 ----------------------------------------------
343 Index Only Scan using box_spgist on box_temp
344 Index Cond: (f1 &> '(45,50),(40,30)'::box)
347 SELECT * FROM box_temp WHERE f1 >> '(30,40),(40,30)';
362 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 >> '(30,40),(40,30)';
364 ----------------------------------------------
365 Index Only Scan using box_spgist on box_temp
366 Index Cond: (f1 >> '(40,40),(30,30)'::box)
369 SELECT * FROM box_temp WHERE f1 <<| '(10,4.33334),(5,100)';
371 --------------------------
374 (40,4.3333333333),(-3,1)
377 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 <<| '(10,4.33334),(5,100)';
379 ----------------------------------------------------
380 Index Only Scan using box_spgist on box_temp
381 Index Cond: (f1 <<| '(10,100),(5,4.33334)'::box)
384 SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)';
386 --------------------------
389 (40,4.3333333333),(-3,1)
392 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)';
394 ----------------------------------------------------
395 Index Only Scan using box_spgist on box_temp
396 Index Cond: (f1 &<| '(10,4.3333334),(5,1)'::box)
399 SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
401 ----------------------
406 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)';
408 -----------------------------------------------------------
409 Index Only Scan using box_spgist on box_temp
410 Index Cond: (f1 |&> '(49.99,49.99),(49.99,49.99)'::box)
413 SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
415 ----------------------
429 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)';
431 -----------------------------------------------
432 Index Only Scan using box_spgist on box_temp
433 Index Cond: (f1 |>> '(39,40),(37,38)'::box)
436 SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)';
438 -------------------------------------------
442 (Infinity,Infinity),(-Infinity,-Infinity)
445 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)';
447 ----------------------------------------------
448 Index Only Scan using box_spgist on box_temp
449 Index Cond: (f1 @> '(15,15),(10,11)'::box)
452 SELECT * FROM box_temp WHERE f1 <@ '(10,15),(30,35)';
458 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 <@ '(10,15),(30,35)';
460 ----------------------------------------------
461 Index Only Scan using box_spgist on box_temp
462 Index Cond: (f1 <@ '(30,35),(10,15)'::box)
465 SELECT * FROM box_temp WHERE f1 ~= '(20,20),(40,40)';
471 EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 ~= '(20,20),(40,40)';
473 ----------------------------------------------
474 Index Only Scan using box_spgist on box_temp
475 Index Cond: (f1 ~= '(40,40),(20,20)'::box)
478 RESET enable_seqscan;
479 DROP INDEX box_spgist;
481 -- Test the SP-GiST index on the larger volume of data
483 CREATE TABLE quad_box_tbl (id int, b box);
484 INSERT INTO quad_box_tbl
485 SELECT (x - 1) * 100 + y, box(point(x * 10, y * 10), point(x * 10 + 5, y * 10 + 5))
486 FROM generate_series(1, 100) x,
487 generate_series(1, 100) y;
488 -- insert repeating data to test allTheSame
489 INSERT INTO quad_box_tbl
490 SELECT i, '((200, 300),(210, 310))'
491 FROM generate_series(10001, 11000) AS i;
492 INSERT INTO quad_box_tbl
496 (11003, '((-infinity,-infinity),(infinity,infinity))'),
497 (11004, '((-infinity,100),(-infinity,500))'),
498 (11005, '((-infinity,-infinity),(700,infinity))');
499 CREATE INDEX quad_box_tbl_idx ON quad_box_tbl USING spgist(b);
500 -- get reference results for ORDER BY distance from seq scan
501 SET enable_seqscan = ON;
502 SET enable_indexscan = OFF;
503 SET enable_bitmapscan = OFF;
504 CREATE TABLE quad_box_tbl_ord_seq1 AS
505 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
507 CREATE TABLE quad_box_tbl_ord_seq2 AS
508 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
509 FROM quad_box_tbl WHERE b <@ box '((200,300),(500,600))';
510 SET enable_seqscan = OFF;
511 SET enable_indexscan = ON;
512 SET enable_bitmapscan = ON;
513 SELECT count(*) FROM quad_box_tbl WHERE b << box '((100,200),(300,500))';
519 SELECT count(*) FROM quad_box_tbl WHERE b &< box '((100,200),(300,500))';
525 SELECT count(*) FROM quad_box_tbl WHERE b && box '((100,200),(300,500))';
531 SELECT count(*) FROM quad_box_tbl WHERE b &> box '((100,200),(300,500))';
537 SELECT count(*) FROM quad_box_tbl WHERE b >> box '((100,200),(300,500))';
543 SELECT count(*) FROM quad_box_tbl WHERE b >> box '((100,200),(300,500))';
549 SELECT count(*) FROM quad_box_tbl WHERE b <<| box '((100,200),(300,500))';
555 SELECT count(*) FROM quad_box_tbl WHERE b &<| box '((100,200),(300,500))';
561 SELECT count(*) FROM quad_box_tbl WHERE b |&> box '((100,200),(300,500))';
567 SELECT count(*) FROM quad_box_tbl WHERE b |>> box '((100,200),(300,500))';
573 SELECT count(*) FROM quad_box_tbl WHERE b @> box '((201,301),(202,303))';
579 SELECT count(*) FROM quad_box_tbl WHERE b <@ box '((100,200),(300,500))';
585 SELECT count(*) FROM quad_box_tbl WHERE b ~= box '((200,300),(205,305))';
591 -- test ORDER BY distance
592 SET enable_indexscan = ON;
593 SET enable_bitmapscan = OFF;
595 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
598 ---------------------------------------------------------
600 -> Index Scan using quad_box_tbl_idx on quad_box_tbl
601 Order By: (b <-> '(123,456)'::point)
604 CREATE TEMP TABLE quad_box_tbl_ord_idx1 AS
605 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
608 FROM quad_box_tbl_ord_seq1 seq FULL JOIN quad_box_tbl_ord_idx1 idx
609 ON seq.n = idx.n AND seq.id = idx.id AND
610 (seq.dist = idx.dist OR seq.dist IS NULL AND idx.dist IS NULL)
611 WHERE seq.id IS NULL OR idx.id IS NULL;
612 n | dist | id | n | dist | id
613 ---+------+----+---+------+----
617 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
618 FROM quad_box_tbl WHERE b <@ box '((200,300),(500,600))';
620 ---------------------------------------------------------
622 -> Index Scan using quad_box_tbl_idx on quad_box_tbl
623 Index Cond: (b <@ '(500,600),(200,300)'::box)
624 Order By: (b <-> '(123,456)'::point)
627 CREATE TEMP TABLE quad_box_tbl_ord_idx2 AS
628 SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id
629 FROM quad_box_tbl WHERE b <@ box '((200,300),(500,600))';
631 FROM quad_box_tbl_ord_seq2 seq FULL JOIN quad_box_tbl_ord_idx2 idx
632 ON seq.n = idx.n AND seq.id = idx.id AND
633 (seq.dist = idx.dist OR seq.dist IS NULL AND idx.dist IS NULL)
634 WHERE seq.id IS NULL OR idx.id IS NULL;
635 n | dist | id | n | dist | id
636 ---+------+----+---+------+----
639 RESET enable_seqscan;
640 RESET enable_indexscan;
641 RESET enable_bitmapscan;
642 -- test non-error-throwing API for some core types
643 SELECT pg_input_is_valid('200', 'box');
649 SELECT * FROM pg_input_error_info('200', 'box');
650 message | detail | hint | sql_error_code
651 ------------------------------------------+--------+------+----------------
652 invalid input syntax for type box: "200" | | | 22P02
655 SELECT pg_input_is_valid('((200,300),(500, xyz))', 'box');
661 SELECT * FROM pg_input_error_info('((200,300),(500, xyz))', 'box');
662 message | detail | hint | sql_error_code
663 -------------------------------------------------------------+--------+------+----------------
664 invalid input syntax for type box: "((200,300),(500, xyz))" | | | 22P02