--
-- POLYGON
--
-- polygon logic
--
CREATE TABLE POLYGON_TBL (
    f1 polygon
);

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(2.0,0.0),(2.0,4.0),(0.0,0.0)');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(3.0,1.0),(3.0,3.0),(1.0,0.0)');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(1,2),(3,4),(5,6),(7,8)');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(7,8),(5,6),(3,4),(1,2)');

-- Reverse
INSERT INTO POLYGON_TBL (f1)
    VALUES ('(1,2),(7,8),(5,6),(3,-4)');

-- degenerate polygons
INSERT INTO POLYGON_TBL (f1)
    VALUES ('(0.0,0.0)');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(0.0,1.0),(0.0,1.0)');

-- bad polygon input strings
INSERT INTO POLYGON_TBL (f1)
    VALUES ('0.0');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(0.0 0.0');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(0,1,2)');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('(0,1,2,3');

INSERT INTO POLYGON_TBL (f1)
    VALUES ('asdf');

SELECT
    '' AS four,
    *
FROM
    POLYGON_TBL;

--
-- Test the SP-GiST index
--
CREATE TABLE quad_poly_tbl (
    id int,
    p polygon
);

INSERT INTO quad_poly_tbl
SELECT
    (x - 1) * 100 + y,
    polygon(circle(point(x * 10, y * 10), 1 + (x + y) % 10))
FROM
    generate_series(1, 100) x,
    generate_series(1, 100) y;

INSERT INTO quad_poly_tbl
SELECT
    i,
    polygon '((200, 300),(210, 310),(230, 290))'
FROM
    generate_series(10001, 11000) AS i;

INSERT INTO quad_poly_tbl
    VALUES (11001, NULL), (11002, NULL), (11003, NULL);

CREATE INDEX quad_poly_tbl_idx ON quad_poly_tbl USING spgist (p);

-- get reference results for ORDER BY distance from seq scan
SET enable_seqscan = ON;

SET enable_indexscan = OFF;

SET enable_bitmapscan = OFF;

CREATE TEMP TABLE quad_poly_tbl_ord_seq2 AS
SELECT
    rank() OVER (ORDER BY p <-> point '123,456') n,
    p <-> point '123,456' dist,
    id
FROM
    quad_poly_tbl
WHERE
    p <@ polygon '((300,300),(400,600),(600,500),(700,200))';

-- check results results from index scan
SET enable_seqscan = OFF;

SET enable_indexscan = OFF;

SET enable_bitmapscan = ON;

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p << polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p << polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &< polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &< polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p && polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p && polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &> polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &> polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p >> polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p >> polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p <<| polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p <<| polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &<| polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p &<| polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p |&> polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p |&> polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p |>> polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p |>> polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p <@ polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p <@ polygon '((300,300),(400,600),(600,500),(700,200))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p @> polygon '((340,550),(343,552),(341,553))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p @> polygon '((340,550),(343,552),(341,553))';

EXPLAIN (
    COSTS OFF
)
SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p ~= polygon '((200, 300),(210, 310),(230, 290))';

SELECT
    count(*)
FROM
    quad_poly_tbl
WHERE
    p ~= polygon '((200, 300),(210, 310),(230, 290))';

-- test ORDER BY distance
SET enable_indexscan = ON;

SET enable_bitmapscan = OFF;

EXPLAIN (
    COSTS OFF
)
SELECT
    rank() OVER (ORDER BY p <-> point '123,456') n,
    p <-> point '123,456' dist,
    id
FROM
    quad_poly_tbl
WHERE
    p <@ polygon '((300,300),(400,600),(600,500),(700,200))';

CREATE TEMP TABLE quad_poly_tbl_ord_idx2 AS
SELECT
    rank() OVER (ORDER BY p <-> point '123,456') n,
    p <-> point '123,456' dist,
    id
FROM
    quad_poly_tbl
WHERE
    p <@ polygon '((300,300),(400,600),(600,500),(700,200))';

SELECT
    *
FROM
    quad_poly_tbl_ord_seq2 seq
    FULL JOIN quad_poly_tbl_ord_idx2 idx ON seq.n = idx.n
        AND seq.id = idx.id
        AND (seq.dist = idx.dist
            OR seq.dist IS NULL
            AND idx.dist IS NULL)
WHERE
    seq.id IS NULL
    OR idx.id IS NULL;

RESET enable_seqscan;

RESET enable_indexscan;

RESET enable_bitmapscan;

