-- -- CREATE_INDEX -- Create ancillary data structures (i.e. indices) -- -- -- BTREE -- CREATE INDEX onek_unique1 ON onek USING btree(unique1 int4_ops); CREATE INDEX onek_unique2 ON onek USING btree(unique2 int4_ops); CREATE INDEX onek_hundred ON onek USING btree(hundred int4_ops); CREATE INDEX onek_stringu1 ON onek USING btree(stringu1 name_ops); CREATE INDEX tenk1_unique1 ON tenk1 USING btree(unique1 int4_ops); CREATE INDEX tenk1_unique2 ON tenk1 USING btree(unique2 int4_ops); CREATE INDEX tenk1_hundred ON tenk1 USING btree(hundred int4_ops); CREATE INDEX tenk1_thous_tenthous ON tenk1 (thousand, tenthous); CREATE INDEX tenk2_unique1 ON tenk2 USING btree(unique1 int4_ops); CREATE INDEX tenk2_unique2 ON tenk2 USING btree(unique2 int4_ops); CREATE INDEX tenk2_hundred ON tenk2 USING btree(hundred int4_ops); CREATE INDEX rix ON road USING btree (name text_ops); CREATE INDEX iix ON ihighway USING btree (name text_ops); CREATE INDEX six ON shighway USING btree (name text_ops); -- test comments COMMENT ON INDEX six_wrong IS 'bad index'; ERROR: relation "six_wrong" does not exist COMMENT ON INDEX six IS 'good index'; COMMENT ON INDEX six IS NULL; -- -- BTREE ascending/descending cases -- -- we load int4/text from pure descending data (each key is a new -- low key) and name/f8 from pure ascending data (each key is a new -- high key). we had a bug where new low keys would sometimes be -- "lost". -- CREATE INDEX bt_i4_index ON bt_i4_heap USING btree (seqno int4_ops); CREATE INDEX bt_name_index ON bt_name_heap USING btree (seqno name_ops); CREATE INDEX bt_txt_index ON bt_txt_heap USING btree (seqno text_ops); CREATE INDEX bt_f8_index ON bt_f8_heap USING btree (seqno float8_ops); -- -- BTREE partial indices -- CREATE INDEX onek2_u1_prtl ON onek2 USING btree(unique1 int4_ops) where unique1 < 20 or unique1 > 980; CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops) where stringu1 < 'B'; CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K'; -- -- RTREE -- -- rtrees use a quadratic page-splitting algorithm that takes a -- really, really long time. we don't test all rtree opclasses -- in the regression test (we check them using the sequoia 2000 -- benchmark). -- CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base); SET enable_seqscan = ON; SET enable_indexscan = OFF; SET enable_bitmapscan = OFF; SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box ORDER BY home_base USING <<; home_base ----------------------- (337,455),(240,359) (1444,403),(1346,344) (2 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count ------- 2 (1 row) SET enable_seqscan = OFF; SET enable_indexscan = ON; SET enable_bitmapscan = ON; -- there's no easy way to check that these commands actually use -- the index, unfortunately. (EXPLAIN would work, but its output -- changes too often for me to want to put an EXPLAIN in the test...) SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box ORDER BY home_base USING <<; home_base ----------------------- (337,455),(240,359) (1444,403),(1346,344) (2 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count ------- 2 (1 row) DROP INDEX rect2ind; -- -- GiST (rtree-equivalent opclasses only) -- CREATE INDEX grect2ind ON fast_emp4000 USING gist (home_base); CREATE INDEX gpolygonind ON polygon_tbl USING gist (f1); CREATE INDEX gcircleind ON circle_tbl USING gist (f1); CREATE TEMP TABLE gpolygon_tbl AS SELECT polygon(home_base) AS f1 FROM slow_emp4000; CREATE TEMP TABLE gcircle_tbl AS SELECT circle(home_base) AS f1 FROM slow_emp4000; CREATE INDEX ggpolygonind ON gpolygon_tbl USING gist (f1); CREATE INDEX ggcircleind ON gcircle_tbl USING gist (f1); SET enable_seqscan = ON; SET enable_indexscan = OFF; SET enable_bitmapscan = OFF; SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box ORDER BY home_base USING <<; home_base ----------------------- (337,455),(240,359) (1444,403),(1346,344) (2 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count ------- 2 (1 row) SELECT * FROM polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon ORDER BY f1 USING <<; f1 --------------------- ((2,0),(2,4),(0,0)) (1 row) SELECT * FROM circle_tbl WHERE f1 && circle(point(1,-2), 1) ORDER BY f1 USING <<; f1 --------------- <(1,3),5> <(1,2),100> <(1,2),3> <(100,1),115> (4 rows) SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; count ------- 2 (1 row) SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; count ------- 2 (1 row) SET enable_seqscan = OFF; SET enable_indexscan = ON; SET enable_bitmapscan = ON; -- there's no easy way to check that these commands actually use -- the index, unfortunately. (EXPLAIN would work, but its output -- changes too often for me to want to put an EXPLAIN in the test...) SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box ORDER BY home_base USING <<; home_base ----------------------- (337,455),(240,359) (1444,403),(1346,344) (2 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count ------- 2 (1 row) SELECT * FROM polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon ORDER BY f1 USING <<; f1 --------------------- ((2,0),(2,4),(0,0)) (1 row) SELECT * FROM circle_tbl WHERE f1 && circle(point(1,-2), 1) ORDER BY f1 USING <<; f1 --------------- <(1,3),5> <(1,2),100> <(1,2),3> <(100,1),115> (4 rows) SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; count ------- 2 (1 row) SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; count ------- 2 (1 row) RESET enable_seqscan; RESET enable_indexscan; RESET enable_bitmapscan; -- -- HASH -- CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops); CREATE INDEX hash_name_index ON hash_name_heap USING hash (random name_ops); CREATE INDEX hash_txt_index ON hash_txt_heap USING hash (random text_ops); CREATE INDEX hash_f8_index ON hash_f8_heap USING hash (random float8_ops); -- CREATE INDEX hash_ovfl_index ON hash_ovfl_heap USING hash (x int4_ops); -- -- Test functional index -- CREATE TABLE func_index_heap (f1 text, f2 text); CREATE UNIQUE INDEX func_index_index on func_index_heap (textcat(f1,f2)); INSERT INTO func_index_heap VALUES('ABC','DEF'); INSERT INTO func_index_heap VALUES('AB','CDEFG'); INSERT INTO func_index_heap VALUES('QWE','RTY'); -- this should fail because of unique index: INSERT INTO func_index_heap VALUES('ABCD', 'EF'); ERROR: duplicate key violates unique constraint "func_index_index" -- but this shouldn't: INSERT INTO func_index_heap VALUES('QWERTY'); -- -- Same test, expressional index -- DROP TABLE func_index_heap; CREATE TABLE func_index_heap (f1 text, f2 text); CREATE UNIQUE INDEX func_index_index on func_index_heap ((f1 || f2) text_ops); INSERT INTO func_index_heap VALUES('ABC','DEF'); INSERT INTO func_index_heap VALUES('AB','CDEFG'); INSERT INTO func_index_heap VALUES('QWE','RTY'); -- this should fail because of unique index: INSERT INTO func_index_heap VALUES('ABCD', 'EF'); ERROR: duplicate key violates unique constraint "func_index_index" -- but this shouldn't: INSERT INTO func_index_heap VALUES('QWERTY'); -- -- Also try building functional, expressional, and partial indexes on -- tables that already contain data. -- create unique index hash_f8_index_1 on hash_f8_heap(abs(random)); create unique index hash_f8_index_2 on hash_f8_heap((seqno + 1), random); create unique index hash_f8_index_3 on hash_f8_heap(random) where seqno > 1000;