diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..5ad68edc33 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +# Don't send some content to the Docker host when building +img +travis +.git +.travis.yml + +*.gcno +*.gcda +*.gcov +*.so +*.o diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..9dd95cb320 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +sudo: required + +language: c + +services: + - docker + +before_install: + - cp travis/* . + +install: + - ./mk_dockerfile.sh + - docker-compose build + +script: + - docker-compose run $(bash <(curl -s https://codecov.io/env)) tests + +notifications: + email: + on_success: change + on_failure: always + +env: + - PG_VERSION=11 LEVEL=hardcore + - PG_VERSION=11 + - PG_VERSION=10 + - PG_VERSION=9.6 diff --git a/LICENSE b/LICENSE index c786b781e6..5b55f87617 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ RUM is released under the PostgreSQL License, a liberal Open Source license, similar to the BSD or MIT licenses. -Copyright (c) 2015-2018, Postgres Professional +Portions Copyright (c) 2015-2019, Postgres Professional Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of California @@ -8,4 +8,4 @@ Permission to use, copy, modify, and distribute this software and its documentat IN NO EVENT SHALL POSTGRES PROFESSIONAL BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF POSTGRES PROFESSIONAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -POSTGRES PROFESSIONAL SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND POSTGRES PROFESSIONAL HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. \ No newline at end of file +POSTGRES PROFESSIONAL SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND POSTGRES PROFESSIONAL HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. diff --git a/Makefile b/Makefile index 19476e53af..36ae70c8d2 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,8 @@ endif wal-check: temp-install $(prove_check) +check: wal-check + all: $(SQL_built) #9.6 requires 1.3 file but 10.0 could live with update files diff --git a/README.md b/README.md index dd575c479c..98a13bb17f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Build Status](https://api.travis-ci.com/postgrespro/rum.svg?branch=master)](https://travis-ci.com/postgrespro/rum) [![PGXN version](https://badge.fury.io/pg/rum.svg)](https://badge.fury.io/pg/rum) [![GitHub license](https://img.shields.io/badge/license-PostgreSQL-blue.svg)](https://raw.githubusercontent.com/postgrespro/rum/master/LICENSE) diff --git a/expected/altorder.out b/expected/altorder.out index f99f0b1e81..9f7178b86a 100644 --- a/expected/altorder.out +++ b/expected/altorder.out @@ -1,120 +1,174 @@ CREATE TABLE atsts (id int, t tsvector, d timestamp); \copy atsts from 'data/tsts.data' +-- PGPRO-2537: We need more data to test rumsort.c with logtape.c +\copy atsts from 'data/tsts.data' +\copy atsts from 'data/tsts.data' +\copy atsts from 'data/tsts.data' CREATE INDEX atsts_idx ON atsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; count ------- - 158 + 632 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'wr&qh'; count ------- - 17 + 68 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq&yt'; count ------- - 6 + 24 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq|yt'; count ------- - 98 + 392 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq&yt)|(wr&qh)'; count ------- - 23 + 92 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq|yt)&(wr|qh)'; count ------- - 39 + 156 (1 row) SET enable_indexscan=OFF; SET enable_indexonlyscan=OFF; SET enable_bitmapscan=OFF; SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 - 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 - 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 - 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 - 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 - 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; count ------- - 357 + 1422 (1 row) SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; count ------- - 153 + 612 (1 row) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 71 | Wed May 04 18:21:22.326724 2016 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 232 | Wed May 11 11:21:22.326724 2016 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) + 355 | Mon May 16 14:21:22.326724 2016 +(36 rows) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 406 | Wed May 18 17:21:22.326724 2016 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 484 | Sat May 21 23:21:22.326724 2016 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 +(32 rows) -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; @@ -130,37 +184,37 @@ SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; count ------- - 158 + 632 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'wr&qh'; count ------- - 17 + 68 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq&yt'; count ------- - 6 + 24 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq|yt'; count ------- - 98 + 392 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq&yt)|(wr&qh)'; count ------- - 23 + 92 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq|yt)&(wr|qh)'; count ------- - 39 + 156 (1 row) EXPLAIN (costs off) @@ -177,7 +231,7 @@ SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; count ------- - 357 + 1422 (1 row) EXPLAIN (costs off) @@ -194,9 +248,13 @@ SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; count ------- - 153 + 612 (1 row) +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; QUERY PLAN @@ -208,13 +266,13 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY (4 rows) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 - 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) EXPLAIN (costs off) @@ -228,13 +286,13 @@ SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY (4 rows) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 - 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 - 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) EXPLAIN (costs off) @@ -250,11 +308,11 @@ SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 - 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 - 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) EXPLAIN (costs off) @@ -269,11 +327,11 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts ORDER BY d <=> '2016-05-16 SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 356 | Mon May 16 15:21:22.326724 2016 | 3597.326724 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 357 | Mon May 16 16:21:22.326724 2016 | 7197.326724 - 353 | Mon May 16 12:21:22.326724 2016 | 7202.673276 (5 rows) EXPLAIN (costs off) @@ -290,15 +348,42 @@ SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER id | d -----+--------------------------------- 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 71 | Wed May 04 18:21:22.326724 2016 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 232 | Wed May 11 11:21:22.326724 2016 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) + 355 | Mon May 16 14:21:22.326724 2016 +(36 rows) EXPLAIN (costs off) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; @@ -314,12 +399,36 @@ SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER id | d -----+--------------------------------- 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 457 | Fri May 20 20:21:22.326724 2016 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) +(32 rows) diff --git a/expected/altorder_1.out b/expected/altorder_1.out index b8c3141b94..5bd8925d7c 100644 --- a/expected/altorder_1.out +++ b/expected/altorder_1.out @@ -1,293 +1,433 @@ CREATE TABLE atsts (id int, t tsvector, d timestamp); \copy atsts from 'data/tsts.data' +-- PGPRO-2537: We need more data to test rumsort.c with logtape.c +\copy atsts from 'data/tsts.data' +\copy atsts from 'data/tsts.data' +\copy atsts from 'data/tsts.data' CREATE INDEX atsts_idx ON atsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +ERROR: doesn't support order index over pass-by-reference column +INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; count ------- - 158 + 632 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'wr&qh'; count ------- - 17 + 68 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq&yt'; count ------- - 6 + 24 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq|yt'; count ------- - 98 + 392 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq&yt)|(wr&qh)'; count ------- - 23 + 92 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq|yt)&(wr|qh)'; count ------- - 39 + 156 (1 row) SET enable_indexscan=OFF; SET enable_indexonlyscan=OFF; SET enable_bitmapscan=OFF; SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 - 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; - id | d | ?column? ------+---------------------------------+--------------- - 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 - 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 - 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 - 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 - 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 (5 rows) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 - 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 - 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 - 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; count ------- - 357 + 1422 (1 row) SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; count ------- - 153 + 612 (1 row) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 39 | Tue May 03 10:21:22.326724 2016 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 168 | Sun May 08 19:21:22.326724 2016 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 354 | Mon May 16 13:21:22.326724 2016 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) + 355 | Mon May 16 14:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(36 rows) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 406 | Wed May 18 17:21:22.326724 2016 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 457 | Fri May 20 20:21:22.326724 2016 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) +(32 rows) -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atsts - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on atsts_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Seq Scan on atsts + Filter: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; count ------- - 158 + 632 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'wr&qh'; count ------- - 17 + 68 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq&yt'; count ------- - 6 + 24 (1 row) SELECT count(*) FROM atsts WHERE t @@ 'eq|yt'; count ------- - 98 + 392 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq&yt)|(wr&qh)'; count ------- - 23 + 92 (1 row) SELECT count(*) FROM atsts WHERE t @@ '(eq|yt)&(wr|qh)'; count ------- - 39 + 156 (1 row) EXPLAIN (costs off) SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atsts - Recheck Cond: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) - -> Bitmap Index Scan on atsts_idx - Index Cond: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(5 rows) + -> Seq Scan on atsts + Filter: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) SELECT count(*) FROM atsts WHERE d < '2016-05-16 14:21:25'; count ------- - 357 + 1422 (1 row) EXPLAIN (costs off) SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atsts - Recheck Cond: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) - -> Bitmap Index Scan on atsts_idx - Index Cond: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(5 rows) + -> Seq Scan on atsts + Filter: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; count ------- - 153 + 612 (1 row) +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atsts_idx on atsts - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atsts_idx on atsts - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atsts_idx on atsts - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atsts_idx on atsts - Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(3 rows) + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts +(4 rows) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 356 | Mon May 16 15:21:22.326724 2016 | 3597.326724 +(5 rows) + EXPLAIN (costs off) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ Sort Sort Key: d - -> Index Scan using atsts_idx on atsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) (4 rows) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 + 16 | Mon May 02 11:21:22.326724 2016 16 | Mon May 02 11:21:22.326724 2016 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 135 | Sat May 07 10:21:22.326724 2016 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 252 | Thu May 12 07:21:22.326724 2016 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) + 355 | Mon May 16 14:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(36 rows) EXPLAIN (costs off) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ Sort Sort Key: d - -> Index Scan using atsts_idx on atsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atsts + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) (4 rows) SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 + 371 | Tue May 17 06:21:22.326724 2016 371 | Tue May 17 06:21:22.326724 2016 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 428 | Thu May 19 15:21:22.326724 2016 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 484 | Sat May 21 23:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) +(32 rows) diff --git a/expected/altorder_hash.out b/expected/altorder_hash.out index a828287541..125c195be9 100644 --- a/expected/altorder_hash.out +++ b/expected/altorder_hash.out @@ -2,8 +2,8 @@ CREATE TABLE atstsh (id int, t tsvector, d timestamp); \copy atstsh from 'data/tsts.data' CREATE INDEX atstsh_idx ON atstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; count ------- @@ -112,9 +112,8 @@ SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDE 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; @@ -197,6 +196,10 @@ SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; 153 (1 row) +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; QUERY PLAN diff --git a/expected/altorder_hash_1.out b/expected/altorder_hash_1.out index ce969c44bd..2d93f3f5eb 100644 --- a/expected/altorder_hash_1.out +++ b/expected/altorder_hash_1.out @@ -2,8 +2,9 @@ CREATE TABLE atstsh (id int, t tsvector, d timestamp); \copy atstsh from 'data/tsts.data' CREATE INDEX atstsh_idx ON atstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +ERROR: doesn't support order index over pass-by-reference column +INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; count ------- @@ -112,20 +113,17 @@ SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDE 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atstsh - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on atstsh_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Seq Scan on atstsh + Filter: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; count @@ -165,14 +163,12 @@ SELECT count(*) FROM atstsh WHERE t @@ '(eq|yt)&(wr|qh)'; EXPLAIN (costs off) SELECT count(*) FROM atstsh WHERE d < '2016-05-16 14:21:25'; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atstsh - Recheck Cond: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) - -> Bitmap Index Scan on atstsh_idx - Index Cond: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(5 rows) + -> Seq Scan on atstsh + Filter: (d < 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) SELECT count(*) FROM atstsh WHERE d < '2016-05-16 14:21:25'; count @@ -182,14 +178,12 @@ SELECT count(*) FROM atstsh WHERE d < '2016-05-16 14:21:25'; EXPLAIN (costs off) SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on atstsh - Recheck Cond: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) - -> Bitmap Index Scan on atstsh_idx - Index Cond: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(5 rows) + -> Seq Scan on atstsh + Filter: (d > 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; count @@ -197,61 +191,101 @@ SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; 153 (1 row) +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atstsh_idx on atstsh - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atstsh_idx on atstsh - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d <=| '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 + 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 + 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atstsh_idx on atstsh - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(4 rows) + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, d, d |=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 + 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 +(5 rows) + EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------- Limit - -> Index Scan using atstsh_idx on atstsh - Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) -(3 rows) + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh +(4 rows) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 356 | Mon May 16 15:21:22.326724 2016 | 3597.326724 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 357 | Mon May 16 16:21:22.326724 2016 | 7197.326724 + 353 | Mon May 16 12:21:22.326724 2016 | 7202.673276 +(5 rows) + EXPLAIN (costs off) SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ Sort Sort Key: d - -> Index Scan using atstsh_idx on atstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) (4 rows) SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; @@ -270,12 +304,12 @@ SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDE EXPLAIN (costs off) SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ Sort Sort Key: d - -> Index Scan using atstsh_idx on atstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Seq Scan on atstsh + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) (4 rows) SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; diff --git a/expected/array.out b/expected/array.out index 92864d95e4..4094d98492 100644 --- a/expected/array.out +++ b/expected/array.out @@ -858,20 +858,26 @@ SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> Order By: (i <=> '{51}'::smallint[]) (3 rows) -SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> '{51}'; - i | ?column? +SELECT i, + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(18,14) + END distance + FROM + (SELECT *, (i <=> '{51}') AS distance + FROM test_array_order WHERE i @> '{23,20}' ORDER BY i <=> '{51}') t; + i | distance ---------------------+------------------ {20,23,51} | 1.73205080756888 {33,51,20,77,23,65} | 2.44948974278318 - {23,76,34,23,2,20} | Infinity - {20,60,45,23,29} | Infinity - {23,89,38,20,40,95} | Infinity - {23,20,72} | Infinity - {73,23,20} | Infinity - {6,97,20,89,23} | Infinity - {20,98,30,23,1,66} | Infinity - {57,23,39,46,50,20} | Infinity - {81,20,26,22,23} | Infinity - {18,23,10,90,15,20} | Infinity + {23,76,34,23,2,20} | -1 + {20,60,45,23,29} | -1 + {23,89,38,20,40,95} | -1 + {23,20,72} | -1 + {73,23,20} | -1 + {6,97,20,89,23} | -1 + {20,98,30,23,1,66} | -1 + {57,23,39,46,50,20} | -1 + {81,20,26,22,23} | -1 + {18,23,10,90,15,20} | -1 (12 rows) diff --git a/expected/array_1.out b/expected/array_1.out index e88ae50589..ec3abfb693 100644 --- a/expected/array_1.out +++ b/expected/array_1.out @@ -851,20 +851,26 @@ SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> Order By: (i <=> '{51}'::smallint[]) (3 rows) -SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> '{51}'; - i | ?column? +SELECT i, + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(18,14) + END distance + FROM + (SELECT *, (i <=> '{51}') AS distance + FROM test_array_order WHERE i @> '{23,20}' ORDER BY i <=> '{51}') t; + i | distance ---------------------+------------------ {20,23,51} | 1.73205080756888 {33,51,20,77,23,65} | 2.44948974278318 - {23,76,34,23,2,20} | Infinity - {20,60,45,23,29} | Infinity - {23,89,38,20,40,95} | Infinity - {23,20,72} | Infinity - {73,23,20} | Infinity - {6,97,20,89,23} | Infinity - {20,98,30,23,1,66} | Infinity - {57,23,39,46,50,20} | Infinity - {81,20,26,22,23} | Infinity - {18,23,10,90,15,20} | Infinity + {23,76,34,23,2,20} | -1 + {20,60,45,23,29} | -1 + {23,89,38,20,40,95} | -1 + {23,20,72} | -1 + {73,23,20} | -1 + {6,97,20,89,23} | -1 + {20,98,30,23,1,66} | -1 + {57,23,39,46,50,20} | -1 + {81,20,26,22,23} | -1 + {18,23,10,90,15,20} | -1 (12 rows) diff --git a/expected/int8_1.out b/expected/int8_1.out index fe7a3151fb..473eef3c35 100644 --- a/expected/int8_1.out +++ b/expected/int8_1.out @@ -219,14 +219,15 @@ CREATE TABLE test_int8_a AS SELECT id::int8, t FROM tsts; CREATE INDEX test_int8_a_idx ON test_int8_a USING rum (t rum_tsvector_addon_ops, id) WITH (attach = 'id', to = 't', order_by_attach='t'); +ERROR: doesn't support order index over pass-by-reference column SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM test_int8_a WHERE id < 400::int8; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +-------------------------------------- Aggregate - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: (id < '400'::bigint) + -> Seq Scan on test_int8_a + Filter: (id < '400'::bigint) (3 rows) SELECT count(*) FROM test_int8_a WHERE id < 400::int8; @@ -237,48 +238,75 @@ SELECT count(*) FROM test_int8_a WHERE id < 400::int8; EXPLAIN (costs off) SELECT id, id <=> 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id <=> 400 LIMIT 5; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id <=> '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id <=> '400'::bigint)) + -> Seq Scan on test_int8_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id <=> 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id <=> 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 406 | 6 + 415 | 15 + 428 | 28 + 371 | 29 + 355 | 45 +(5 rows) + EXPLAIN (costs off) SELECT id, id <=| 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id <=| 400 LIMIT 5; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id <=| '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id <=| '400'::bigint)) + -> Seq Scan on test_int8_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id <=| 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id <=| 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 371 | 29 + 355 | 45 + 354 | 46 + 252 | 148 + 232 | 168 +(5 rows) + EXPLAIN (costs off) SELECT id, id |=> 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id |=> 400 LIMIT 5; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id |=> '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id |=> '400'::bigint)) + -> Seq Scan on test_int8_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id |=> 400 FROM test_int8_a WHERE t @@ 'wr&qh' ORDER BY id |=> 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 406 | 6 + 415 | 15 + 428 | 28 + 457 | 57 + 458 | 58 +(5 rows) + EXPLAIN (costs off) SELECT id FROM test_int8_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Sort Sort Key: id - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) + -> Seq Scan on test_int8_a + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) (4 rows) SELECT id FROM test_int8_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id; @@ -298,12 +326,12 @@ SELECT id FROM test_int8_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id; EXPLAIN (costs off) SELECT id FROM test_int8_a WHERE t @@ 'wr&qh' AND id >= 400::int8 ORDER BY id; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Sort Sort Key: id - -> Index Scan using test_int8_a_idx on test_int8_a - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id >= '400'::bigint)) + -> Seq Scan on test_int8_a + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id >= '400'::bigint)) (4 rows) SELECT id FROM test_int8_a WHERE t @@ 'wr&qh' AND id >= 400::int8 ORDER BY id; @@ -474,14 +502,15 @@ CREATE TABLE test_int8_h_a AS SELECT id::int8, t FROM tsts; CREATE INDEX test_int8_h_a_idx ON test_int8_h_a USING rum (t rum_tsvector_hash_addon_ops, id) WITH (attach = 'id', to = 't', order_by_attach='t'); +ERROR: doesn't support order index over pass-by-reference column SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM test_int8_h_a WHERE id < 400::int8; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +-------------------------------------- Aggregate - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: (id < '400'::bigint) + -> Seq Scan on test_int8_h_a + Filter: (id < '400'::bigint) (3 rows) SELECT count(*) FROM test_int8_h_a WHERE id < 400::int8; @@ -492,48 +521,75 @@ SELECT count(*) FROM test_int8_h_a WHERE id < 400::int8; EXPLAIN (costs off) SELECT id, id <=> 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id <=> 400 LIMIT 5; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id <=> '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id <=> '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id <=> 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id <=> 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 406 | 6 + 415 | 15 + 428 | 28 + 371 | 29 + 355 | 45 +(5 rows) + EXPLAIN (costs off) SELECT id, id <=| 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id <=| 400 LIMIT 5; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id <=| '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id <=| '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id <=| 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id <=| 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 371 | 29 + 355 | 45 + 354 | 46 + 252 | 148 + 232 | 168 +(5 rows) + EXPLAIN (costs off) SELECT id, id |=> 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id |=> 400 LIMIT 5; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------- Limit - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) - Order By: (id |=> '400'::bigint) -(4 rows) + -> Sort + Sort Key: ((id |=> '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: (t @@ '''wr'' & ''qh'''::tsquery) +(5 rows) SELECT id, id |=> 400 FROM test_int8_h_a WHERE t @@ 'wr&qh' ORDER BY id |=> 400 LIMIT 5; -ERROR: doesn't support order by over pass-by-reference column + id | ?column? +-----+---------- + 406 | 6 + 415 | 15 + 428 | 28 + 457 | 57 + 458 | 58 +(5 rows) + EXPLAIN (costs off) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Sort Sort Key: id - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) (4 rows) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id; @@ -553,12 +609,12 @@ SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id EXPLAIN (costs off) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id >= 400::int8 ORDER BY id; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------- Sort Sort Key: id - -> Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id >= '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id >= '400'::bigint)) (4 rows) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id >= 400::int8 ORDER BY id; @@ -578,12 +634,26 @@ CREATE INDEX test_int8_id_t_idx ON test_int8_o USING rum (t rum_tsvector_ops, id); EXPLAIN (costs off) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id <=> 400::int8; - QUERY PLAN ------------------------------------------------------------------------------ - Index Scan using test_int8_h_a_idx on test_int8_h_a - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) - Order By: (id <=> '400'::bigint) -(3 rows) + QUERY PLAN +------------------------------------------------------------------------------- + Sort + Sort Key: ((id <=> '400'::bigint)) + -> Seq Scan on test_int8_h_a + Filter: ((t @@ '''wr'' & ''qh'''::tsquery) AND (id <= '400'::bigint)) +(4 rows) SELECT id FROM test_int8_h_a WHERE t @@ 'wr&qh' AND id <= 400::int8 ORDER BY id <=> 400::int8; -ERROR: doesn't support order by over pass-by-reference column + id +----- + 371 + 355 + 354 + 252 + 232 + 168 + 135 + 71 + 39 + 16 +(10 rows) + diff --git a/expected/orderby.out b/expected/orderby.out index 38cda70f32..9bc421970c 100644 --- a/expected/orderby.out +++ b/expected/orderby.out @@ -2,8 +2,82 @@ CREATE TABLE tsts (id int, t tsvector, d timestamp); \copy tsts from 'data/tsts.data' CREATE INDEX tsts_idx ON tsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +SET enable_indexscan=OFF; +SET enable_indexonlyscan=OFF; +SET enable_bitmapscan=OFF; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 +(5 rows) + +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 + 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 + 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 +(5 rows) + +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 + 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 +(5 rows) + +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(9 rows) + +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 +(8 rows) + +-- Test bitmap index scan +RESET enable_bitmapscan; +SET enable_seqscan = off; +EXPLAIN (costs off) +SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; + QUERY PLAN +------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(5 rows) + SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; count ------- @@ -40,9 +114,19 @@ SELECT count(*) FROM tsts WHERE t @@ '(eq|yt)&(wr|qh)'; 39 (1 row) -SET enable_indexscan=OFF; -SET enable_indexonlyscan=OFF; -SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -53,6 +137,19 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -63,6 +160,19 @@ SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -73,6 +183,37 @@ SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + -> Index Scan using tsts_idx on tsts + Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) + +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 356 | Mon May 16 15:21:22.326724 2016 | 3597.326724 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 357 | Mon May 16 16:21:22.326724 2016 | 7197.326724 + 353 | Mon May 16 12:21:22.326724 2016 | 7202.673276 +(5 rows) + +EXPLAIN (costs off) +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tsts + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tsts_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -87,6 +228,18 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER 355 | Mon May 16 14:21:22.326724 2016 (9 rows) +EXPLAIN (costs off) +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tsts + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tsts_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -100,20 +253,18 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) +-- Test index scan RESET enable_indexscan; RESET enable_indexonlyscan; -RESET enable_bitmapscan; -SET enable_seqscan = off; +SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on tsts - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on tsts_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Index Scan using tsts_idx on tsts + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; count @@ -277,54 +428,6 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -SET enable_bitmapscan=OFF; -EXPLAIN (costs off) -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tsts_idx on tsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 16 | Mon May 02 11:21:22.326724 2016 - 39 | Tue May 03 10:21:22.326724 2016 - 71 | Wed May 04 18:21:22.326724 2016 - 135 | Sat May 07 10:21:22.326724 2016 - 168 | Sun May 08 19:21:22.326724 2016 - 232 | Wed May 11 11:21:22.326724 2016 - 252 | Thu May 12 07:21:22.326724 2016 - 354 | Mon May 16 13:21:22.326724 2016 - 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) - -EXPLAIN (costs off) -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tsts_idx on tsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 371 | Tue May 17 06:21:22.326724 2016 - 406 | Wed May 18 17:21:22.326724 2016 - 415 | Thu May 19 02:21:22.326724 2016 - 428 | Thu May 19 15:21:22.326724 2016 - 457 | Fri May 20 20:21:22.326724 2016 - 458 | Fri May 20 21:21:22.326724 2016 - 484 | Sat May 21 23:21:22.326724 2016 - 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) - SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d ASC LIMIT 3; id | d ----+--------------------------------- diff --git a/expected/orderby_1.out b/expected/orderby_1.out index 09ace4276c..a6fb68c1e3 100644 --- a/expected/orderby_1.out +++ b/expected/orderby_1.out @@ -2,8 +2,82 @@ CREATE TABLE tsts (id int, t tsvector, d timestamp); \copy tsts from 'data/tsts.data' CREATE INDEX tsts_idx ON tsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +SET enable_indexscan=OFF; +SET enable_indexonlyscan=OFF; +SET enable_bitmapscan=OFF; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 +(5 rows) + +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 + 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 + 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 +(5 rows) + +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 + 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 +(5 rows) + +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(9 rows) + +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 +(8 rows) + +-- Test bitmap index scan +RESET enable_bitmapscan; +SET enable_seqscan = off; +EXPLAIN (costs off) +SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; + QUERY PLAN +------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(5 rows) + SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; count ------- @@ -40,9 +114,19 @@ SELECT count(*) FROM tsts WHERE t @@ '(eq|yt)&(wr|qh)'; 39 (1 row) -SET enable_indexscan=OFF; -SET enable_indexonlyscan=OFF; -SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -53,6 +137,19 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -63,6 +160,19 @@ SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tsts + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tsts_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -73,6 +183,29 @@ SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + -> Index Scan using tsts_idx on tsts + Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) + +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +ERROR: doesn't support order by over pass-by-reference column +EXPLAIN (costs off) +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tsts + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tsts_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -87,6 +220,18 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER 355 | Mon May 16 14:21:22.326724 2016 (9 rows) +EXPLAIN (costs off) +SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tsts + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tsts_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -100,20 +245,18 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) +-- Test index scan RESET enable_indexscan; RESET enable_indexonlyscan; -RESET enable_bitmapscan; -SET enable_seqscan = off; +SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on tsts - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on tsts_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Index Scan using tsts_idx on tsts + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; count @@ -245,54 +388,6 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -SET enable_bitmapscan=OFF; -EXPLAIN (costs off) -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tsts_idx on tsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 16 | Mon May 02 11:21:22.326724 2016 - 39 | Tue May 03 10:21:22.326724 2016 - 71 | Wed May 04 18:21:22.326724 2016 - 135 | Sat May 07 10:21:22.326724 2016 - 168 | Sun May 08 19:21:22.326724 2016 - 232 | Wed May 11 11:21:22.326724 2016 - 252 | Thu May 12 07:21:22.326724 2016 - 354 | Mon May 16 13:21:22.326724 2016 - 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) - -EXPLAIN (costs off) -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tsts_idx on tsts - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 371 | Tue May 17 06:21:22.326724 2016 - 406 | Wed May 18 17:21:22.326724 2016 - 415 | Thu May 19 02:21:22.326724 2016 - 428 | Thu May 19 15:21:22.326724 2016 - 457 | Fri May 20 20:21:22.326724 2016 - 458 | Fri May 20 21:21:22.326724 2016 - 484 | Sat May 21 23:21:22.326724 2016 - 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) - SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d ASC LIMIT 3; id | d ----+--------------------------------- diff --git a/expected/orderby_hash.out b/expected/orderby_hash.out index 1636088fdb..7ff1794c5f 100644 --- a/expected/orderby_hash.out +++ b/expected/orderby_hash.out @@ -2,8 +2,82 @@ CREATE TABLE tstsh (id int, t tsvector, d timestamp); \copy tstsh from 'data/tsts.data' CREATE INDEX tstsh_idx ON tstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +SET enable_indexscan=OFF; +SET enable_indexonlyscan=OFF; +SET enable_bitmapscan=OFF; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 +(5 rows) + +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 + 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 + 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 +(5 rows) + +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 + 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 +(5 rows) + +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(9 rows) + +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 +(8 rows) + +-- Test bitmap index scan +RESET enable_bitmapscan; +SET enable_seqscan = off; +EXPLAIN (costs off) +SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; + QUERY PLAN +------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(5 rows) + SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; count ------- @@ -40,9 +114,19 @@ SELECT count(*) FROM tstsh WHERE t @@ '(eq|yt)&(wr|qh)'; 39 (1 row) -SET enable_indexscan=OFF; -SET enable_indexonlyscan=OFF; -SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -53,6 +137,19 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -63,6 +160,19 @@ SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -73,6 +183,37 @@ SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + -> Index Scan using tstsh_idx on tstsh + Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) + +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 356 | Mon May 16 15:21:22.326724 2016 | 3597.326724 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 357 | Mon May 16 16:21:22.326724 2016 | 7197.326724 + 353 | Mon May 16 12:21:22.326724 2016 | 7202.673276 +(5 rows) + +EXPLAIN (costs off) +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tstsh + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tstsh_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -87,6 +228,18 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER 355 | Mon May 16 14:21:22.326724 2016 (9 rows) +EXPLAIN (costs off) +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tstsh + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tstsh_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -100,20 +253,18 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) +-- Test index scan RESET enable_indexscan; RESET enable_indexonlyscan; -RESET enable_bitmapscan; -SET enable_seqscan = off; +SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on tstsh - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on tstsh_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Index Scan using tstsh_idx on tstsh + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; count @@ -277,54 +428,6 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -SET enable_bitmapscan=OFF; -EXPLAIN (costs off) -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tstsh_idx on tstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 16 | Mon May 02 11:21:22.326724 2016 - 39 | Tue May 03 10:21:22.326724 2016 - 71 | Wed May 04 18:21:22.326724 2016 - 135 | Sat May 07 10:21:22.326724 2016 - 168 | Sun May 08 19:21:22.326724 2016 - 232 | Wed May 11 11:21:22.326724 2016 - 252 | Thu May 12 07:21:22.326724 2016 - 354 | Mon May 16 13:21:22.326724 2016 - 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) - -EXPLAIN (costs off) -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tstsh_idx on tstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 371 | Tue May 17 06:21:22.326724 2016 - 406 | Wed May 18 17:21:22.326724 2016 - 415 | Thu May 19 02:21:22.326724 2016 - 428 | Thu May 19 15:21:22.326724 2016 - 457 | Fri May 20 20:21:22.326724 2016 - 458 | Fri May 20 21:21:22.326724 2016 - 484 | Sat May 21 23:21:22.326724 2016 - 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) - SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d ASC LIMIT 3; id | d ----+--------------------------------- diff --git a/expected/orderby_hash_1.out b/expected/orderby_hash_1.out index 8182aff567..f32267631c 100644 --- a/expected/orderby_hash_1.out +++ b/expected/orderby_hash_1.out @@ -2,8 +2,82 @@ CREATE TABLE tstsh (id int, t tsvector, d timestamp); \copy tstsh from 'data/tsts.data' CREATE INDEX tstsh_idx ON tstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +SET enable_indexscan=OFF; +SET enable_indexonlyscan=OFF; +SET enable_bitmapscan=OFF; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 +(5 rows) + +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 355 | Mon May 16 14:21:22.326724 2016 | 2.673276 + 354 | Mon May 16 13:21:22.326724 2016 | 3602.673276 + 252 | Thu May 12 07:21:22.326724 2016 | 370802.673276 + 232 | Wed May 11 11:21:22.326724 2016 | 442802.673276 + 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 +(5 rows) + +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + id | d | ?column? +-----+---------------------------------+--------------- + 371 | Tue May 17 06:21:22.326724 2016 | 57597.326724 + 406 | Wed May 18 17:21:22.326724 2016 | 183597.326724 + 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 + 428 | Thu May 19 15:21:22.326724 2016 | 262797.326724 + 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 +(5 rows) + +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 16 | Mon May 02 11:21:22.326724 2016 + 39 | Tue May 03 10:21:22.326724 2016 + 71 | Wed May 04 18:21:22.326724 2016 + 135 | Sat May 07 10:21:22.326724 2016 + 168 | Sun May 08 19:21:22.326724 2016 + 232 | Wed May 11 11:21:22.326724 2016 + 252 | Thu May 12 07:21:22.326724 2016 + 354 | Mon May 16 13:21:22.326724 2016 + 355 | Mon May 16 14:21:22.326724 2016 +(9 rows) + +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + id | d +-----+--------------------------------- + 371 | Tue May 17 06:21:22.326724 2016 + 406 | Wed May 18 17:21:22.326724 2016 + 415 | Thu May 19 02:21:22.326724 2016 + 428 | Thu May 19 15:21:22.326724 2016 + 457 | Fri May 20 20:21:22.326724 2016 + 458 | Fri May 20 21:21:22.326724 2016 + 484 | Sat May 21 23:21:22.326724 2016 + 496 | Sun May 22 11:21:22.326724 2016 +(8 rows) + +-- Test bitmap index scan +RESET enable_bitmapscan; +SET enable_seqscan = off; +EXPLAIN (costs off) +SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; + QUERY PLAN +------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(5 rows) + SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; count ------- @@ -40,9 +114,19 @@ SELECT count(*) FROM tstsh WHERE t @@ '(eq|yt)&(wr|qh)'; 39 (1 row) -SET enable_indexscan=OFF; -SET enable_indexonlyscan=OFF; -SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -53,6 +137,19 @@ SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 415 | Thu May 19 02:21:22.326724 2016 | 215997.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d <=| 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -63,6 +160,19 @@ SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 168 | Sun May 08 19:21:22.326724 2016 | 673202.673276 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: ((d |=> 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Heap Scan on tstsh + Recheck Cond: (t @@ '''wr'' & ''qh'''::tsquery) + -> Bitmap Index Scan on tstsh_idx + Index Cond: (t @@ '''wr'' & ''qh'''::tsquery) +(7 rows) + SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; id | d | ?column? -----+---------------------------------+--------------- @@ -73,6 +183,29 @@ SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY 457 | Fri May 20 20:21:22.326724 2016 | 367197.326724 (5 rows) +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + -> Index Scan using tstsh_idx on tstsh + Order By: (d <=> 'Mon May 16 14:21:25 2016'::timestamp without time zone) +(3 rows) + +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +ERROR: doesn't support order by over pass-by-reference column +EXPLAIN (costs off) +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tstsh + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tstsh_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -87,6 +220,18 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER 355 | Mon May 16 14:21:22.326724 2016 (9 rows) +EXPLAIN (costs off) +SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d + -> Bitmap Heap Scan on tstsh + Recheck Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) + -> Bitmap Index Scan on tstsh_idx + Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) +(6 rows) + SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; id | d -----+--------------------------------- @@ -100,20 +245,18 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) +-- Test index scan RESET enable_indexscan; RESET enable_indexonlyscan; -RESET enable_bitmapscan; -SET enable_seqscan = off; +SET enable_bitmapscan=OFF; EXPLAIN (costs off) SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------- Aggregate - -> Bitmap Heap Scan on tstsh - Recheck Cond: (t @@ '''wr'' | ''qh'''::tsquery) - -> Bitmap Index Scan on tstsh_idx - Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + -> Index Scan using tstsh_idx on tstsh + Index Cond: (t @@ '''wr'' | ''qh'''::tsquery) +(3 rows) SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; count @@ -245,54 +388,6 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER 496 | Sun May 22 11:21:22.326724 2016 (8 rows) -SET enable_bitmapscan=OFF; -EXPLAIN (costs off) -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tstsh_idx on tstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d <= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 16 | Mon May 02 11:21:22.326724 2016 - 39 | Tue May 03 10:21:22.326724 2016 - 71 | Wed May 04 18:21:22.326724 2016 - 135 | Sat May 07 10:21:22.326724 2016 - 168 | Sun May 08 19:21:22.326724 2016 - 232 | Wed May 11 11:21:22.326724 2016 - 252 | Thu May 12 07:21:22.326724 2016 - 354 | Mon May 16 13:21:22.326724 2016 - 355 | Mon May 16 14:21:22.326724 2016 -(9 rows) - -EXPLAIN (costs off) -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- - Sort - Sort Key: d - -> Index Scan using tstsh_idx on tstsh - Index Cond: ((t @@ '''wr'' & ''qh'''::tsquery) AND (d >= 'Mon May 16 14:21:25 2016'::timestamp without time zone)) -(4 rows) - -SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; - id | d ------+--------------------------------- - 371 | Tue May 17 06:21:22.326724 2016 - 406 | Wed May 18 17:21:22.326724 2016 - 415 | Thu May 19 02:21:22.326724 2016 - 428 | Thu May 19 15:21:22.326724 2016 - 457 | Fri May 20 20:21:22.326724 2016 - 458 | Fri May 20 21:21:22.326724 2016 - 484 | Sat May 21 23:21:22.326724 2016 - 496 | Sun May 22 11:21:22.326724 2016 -(8 rows) - SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d ASC LIMIT 3; id | d ----+--------------------------------- diff --git a/expected/predicate-rum-2_1.out b/expected/predicate-rum-2_1.out new file mode 100644 index 0000000000..8d3e0d173c --- /dev/null +++ b/expected/predicate-rum-2_1.out @@ -0,0 +1,501 @@ +Parsed test spec with 2 sessions + +starting permutation: rxy1 wx1 c1 rxy2 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 c1 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 wy2 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 wy2 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wx1 c1 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wx1 wy2 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wx1 wy2 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wy2 wx1 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wy2 wx1 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy1 rxy2 wy2 c2 wx1 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wx1 c1 wy2 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wx1 wy2 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wx1 wy2 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wy2 wx1 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wy2 wx1 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wy2 c2 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; + +starting permutation: rxy2 wy2 rxy1 wx1 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; +step c2: COMMIT; + +starting permutation: rxy2 wy2 rxy1 wx1 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c2: COMMIT; +step c1: COMMIT; + +starting permutation: rxy2 wy2 rxy1 c2 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; + +starting permutation: rxy2 wy2 c2 rxy1 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('xz'); +step c2: COMMIT; +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('ab'); +step c1: COMMIT; diff --git a/expected/predicate-rum_1.out b/expected/predicate-rum_1.out new file mode 100644 index 0000000000..7f7a0dc9a6 --- /dev/null +++ b/expected/predicate-rum_1.out @@ -0,0 +1,521 @@ +Parsed test spec with 2 sessions + +starting permutation: rxy1 wx1 c1 rxy2 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +677 'qh' +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 c1 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c2: COMMIT; + +starting permutation: rxy1 wx1 rxy2 wy2 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 wx1 rxy2 wy2 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 rxy2 wx1 c1 wy2 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c2: COMMIT; + +starting permutation: rxy1 rxy2 wx1 wy2 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 rxy2 wx1 wy2 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 rxy2 wy2 wx1 c1 c2 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 rxy2 wy2 wx1 c2 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy1 rxy2 wy2 c2 wx1 c1 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c1: COMMIT; + +starting permutation: rxy2 rxy1 wx1 c1 wy2 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c2: COMMIT; + +starting permutation: rxy2 rxy1 wx1 wy2 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 rxy1 wx1 wy2 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 rxy1 wy2 wx1 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 rxy1 wy2 wx1 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 rxy1 wy2 c2 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c1: COMMIT; + +starting permutation: rxy2 wy2 rxy1 wx1 c1 c2 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; +step c2: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 wy2 rxy1 wx1 c2 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c2: COMMIT; +step c1: COMMIT; +ERROR: could not serialize access due to read/write dependencies among transactions + +starting permutation: rxy2 wy2 rxy1 c2 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +step c2: COMMIT; +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +ERROR: could not serialize access due to read/write dependencies among transactions +step c1: COMMIT; + +starting permutation: rxy2 wy2 c2 rxy1 wx1 c1 +step rxy2: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'qh'; +id tsv + +424 'qh':1 'su':3 'vf':2 +238 'jd':1 'kp':6 'pm':3 'py':5 'qh':4 'ye':2 +299 'lm':1 'nh':6 'nl':3 'op':5 'pl':2 'qh':8 'un':7 'yt':4 +324 'ml':1 'oc':7 'ol':8 'ou':2 'pj':5 'qh':3 'sa':9 'uq':6 'zw':4 +413 'pw':1 'qd':3 'qh':7 'qu':8 'rm':2 'rv':4 'so':5 'sv':6 'tz':9 +147 'fq':1 'ga':2 'gg':3 'iu':9 'iz':10 'kd':5 'lf':4 'mx':7 'qh':11 'tj':6 'yj':8 +step wy2: INSERT INTO rum_tbl(tsv) values('hx'); +step c2: COMMIT; +step rxy1: SELECT id, tsv FROM rum_tbl WHERE tsv @@ 'hx'; +id tsv + +195 'hm':1 'hu':4 'hx':7 'ja':5 'jz':3 'pf':2 'yy':6 +131 'fa':1 'fo':8 'fs':4 'gq':5 'hx':6 'jh':7 'lw':2 'nx':3 +141 'fk':1 'fm':8 'ft':5 'hd':3 'hx':9 'je':2 'nm':4 'ph':7 're':6 +148 'fr':1 'gz':5 'hq':8 'hx':6 'ia':2 'jj':10 'jt':9 'lo':7 'no':4 'wm':3 +206 'hx':1 'iq':4 'ki':10 'kz':3 'lt':8 'ol':9 'pa':7 'tb':5 'ui':2 'xh':6 +45 'bs':1,5 'bu':8 'ce':7 'dm':6 'ea':9 'ej':10 'fd':2 'gj':11 'hx':4 'vo':3 +162 'gf':1,5 'gz':9 'hx':3 'ik':2 'je':11 'jk':10 'jy':4 'nz':6 'qz':7 'rw':8 +677 'hx' +step wx1: INSERT INTO rum_tbl(tsv) values('qh'); +step c1: COMMIT; diff --git a/expected/rum.out b/expected/rum.out index ad960650d2..db08b158dd 100644 --- a/expected/rum.out +++ b/expected/rum.out @@ -132,8 +132,8 @@ SELECT count(*) FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 1 (1 row) -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,7), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way') @@ -146,33 +146,33 @@ SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), 16.4493 | 0.0607927 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (4 rows) -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); rum_ts_distance | rum_ts_score | t | a -----------------+--------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 - 57.5727 | 0.0173693 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 + 8.2247 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 57.5727 | 0.017369 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) SELECT - a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'), - rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), + (a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4) AS distance, + rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), * FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)') limit 2; - ?column? | rum_ts_distance | t | a + distance | rum_ts_distance | t | a ----------+-----------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 8.22467 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 8.2247 | 8.2247 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 57.5727 | 57.5727 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) -- Check ranking normalization -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,7), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way') @@ -185,16 +185,16 @@ SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), 16.4493 | 0.0607927 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (4 rows) -SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), - rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), +SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,4), + rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,6), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); rum_ts_distance | rum_ts_score | t | a -----------------+--------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 - 57.5727 | 0.0173693 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 + 8.2247 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 57.5727 | 0.017369 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) INSERT INTO test_rum (t) VALUES ('foo bar foo the over foo qq bar'); @@ -232,65 +232,71 @@ SELECT a FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'bar') ORDER (1 row) -- Check full-index scan with order by -SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote'); - ?column? +SELECT + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(10,4) + END distance + FROM + (SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') AS distance + FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote')) t; + distance ---------- 16.4493 16.4493 - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 (56 rows) CREATE TABLE tst (i int4, t tsvector); @@ -325,15 +331,15 @@ SELECT a <=> to_tsquery('pg_catalog.english', 'w:*'), * Order By: (a <=> '''w'':*'::tsquery) (3 rows) -SELECT a <=> to_tsquery('pg_catalog.english', 'w:*'), * +SELECT (a <=> to_tsquery('pg_catalog.english', 'w:*'))::numeric(10,4) AS distance, * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'w:*') ORDER BY a <=> to_tsquery('pg_catalog.english', 'w:*'); - ?column? | t | a + distance | t | a ----------+--------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------- - 8.22467 | so well that only a fragment, as it were, gave way. It still hangs as if | 'fragment':6 'gave':10 'hang':14 'still':13 'way':11 'well':2 - 8.22467 | wine, but wouldn't you divide with your neighbors! The columns in the | 'column':11 'divid':6 'neighbor':9 'wine':1 'wouldn':3 - 8.22467 | not say, but you wrote as if you knew it by sight as well as by heart. | 'heart':17 'knew':9 'say':2 'sight':12 'well':14 'wrote':5 + 8.2247 | so well that only a fragment, as it were, gave way. It still hangs as if | 'fragment':6 'gave':10 'hang':14 'still':13 'way':11 'well':2 + 8.2247 | wine, but wouldn't you divide with your neighbors! The columns in the | 'column':11 'divid':6 'neighbor':9 'wine':1 'wouldn':3 + 8.2247 | not say, but you wrote as if you knew it by sight as well as by heart. | 'heart':17 'knew':9 'say':2 'sight':12 'well':14 'wrote':5 16.4493 | little series of pictures. Have you ever been here, I wonder? You did | 'ever':7 'littl':1 'pictur':4 'seri':2 'wonder':11 16.4493 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 16.4493 | _berg_, "the Jettenhuhl, a wooded spur of the Konigestuhl." Look at it | 'berg':1 'jettenhuhl':3 'konigestuhl':9 'look':10 'spur':6 'wood':5 @@ -347,16 +353,16 @@ SELECT a <=> to_tsquery('pg_catalog.english', 'w:*'), * 16.4493 | my appreciation of you in a more complimentary way than by sending this | 'appreci':2 'complimentari':8 'send':12 'way':9 (14 rows) -SELECT a <=> to_tsquery('pg_catalog.english', 'b:*'), * +SELECT (a <=> to_tsquery('pg_catalog.english', 'b:*'))::numeric(10,4) AS distance, * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'b:*') ORDER BY a <=> to_tsquery('pg_catalog.english', 'b:*'); - ?column? | t | a + distance | t | a ----------+--------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------- - 8.22467 | been trying my best to get all those "passes" into my brain. Now, thanks | 'best':4 'brain':12 'get':6 'pass':9 'thank':14 'tri':2 - 8.22467 | All the above information, I beg you to believe, I do not intend you | 'beg':6 'believ':9 'inform':4 'intend':13 - 8.22467 | curious spectacle, but on the whole had "the banquet-hall deserted" | 'banquet':10 'banquet-hal':9 'curious':1 'desert':12 'hall':11 'spectacl':2 'whole':6 - 8.22467 | oaks, limes and maples, bordered with flower-beds and shrubberies, and | 'bed':9 'border':5 'flower':8 'flower-b':7 'lime':2 'mapl':4 'oak':1 'shrubberi':11 + 8.2247 | been trying my best to get all those "passes" into my brain. Now, thanks | 'best':4 'brain':12 'get':6 'pass':9 'thank':14 'tri':2 + 8.2247 | All the above information, I beg you to believe, I do not intend you | 'beg':6 'believ':9 'inform':4 'intend':13 + 8.2247 | curious spectacle, but on the whole had "the banquet-hall deserted" | 'banquet':10 'banquet-hal':9 'curious':1 'desert':12 'hall':11 'spectacl':2 'whole':6 + 8.2247 | oaks, limes and maples, bordered with flower-beds and shrubberies, and | 'bed':9 'border':5 'flower':8 'flower-b':7 'lime':2 'mapl':4 'oak':1 'shrubberi':11 13.1595 | foo bar foo the over foo qq bar | 'bar':2,8 'foo':1,3,6 'qq':7 16.4493 | ornamental building, and I wish you could see it, if you have not seen | 'build':2 'could':7 'ornament':1 'see':8 'seen':14 'wish':5 16.4493 | the--nearest guide-book! | 'book':5 'guid':4 'guide-book':3 'nearest':2 @@ -375,14 +381,14 @@ SELECT a <=> to_tsquery('pg_catalog.english', 'b:*'), * 16.4493 | the few that escaped destruction in 1693. It is a beautiful, highly | '1693':7 'beauti':11 'destruct':5 'escap':4 'high':12 (20 rows) -select 'bjarn:6237 stroustrup:6238'::tsvector <=> 'bjarn <-> stroustrup'::tsquery; - ?column? +select ('bjarn:6237 stroustrup:6238'::tsvector <=> 'bjarn <-> stroustrup'::tsquery)::numeric(10,5) AS distance; + distance ---------- 8.22467 (1 row) -SELECT 'stroustrup:5508B,6233B,6238B bjarn:6235B,6237B' <=> 'bjarn <-> stroustrup'::tsquery; - ?column? +SELECT ('stroustrup:5508B,6233B,6238B bjarn:6235B,6237B' <=> 'bjarn <-> stroustrup'::tsquery)::numeric(10,5) AS distance; + distance ---------- 2.05617 (1 row) diff --git a/expected/rum_hash.out b/expected/rum_hash.out index 4838be4e93..43a9760a28 100644 --- a/expected/rum_hash.out +++ b/expected/rum_hash.out @@ -118,8 +118,8 @@ SELECT count(*) FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 1 (1 row) -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,7), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way') @@ -132,34 +132,34 @@ SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), 16.4493 | 0.0607927 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (4 rows) -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); rum_ts_distance | rum_ts_score | t | a -----------------+--------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 - 57.5727 | 0.0173693 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 + 8.2247 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 57.5727 | 0.017369 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) SELECT - a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'), - rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), + (a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4) AS distance, + rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)') limit 2; - ?column? | rum_ts_distance | rum_ts_score | t | a + distance | rum_ts_distance | rum_ts_score | t | a ----------+-----------------+--------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 8.22467 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 - 57.5727 | 57.5727 | 0.0173693 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 + 8.2247 | 8.2247 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 57.5727 | 57.5727 | 0.017369 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) -- Check ranking normalization -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,7), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way') @@ -172,16 +172,16 @@ SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), 16.4493 | 0.0607927 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (4 rows) -SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), - rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), +SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,4), + rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,6), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); rum_ts_distance | rum_ts_score | t | a -----------------+--------------+---------------------------------------------------------------------+--------------------------------------------------------- - 8.22467 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 - 57.5727 | 0.0173693 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 + 8.2247 | 0.121585 | itself. Put on your "specs" and look at the castle, half way up the | 'castl':10 'half':11 'look':7 'put':2 'spec':5 'way':12 + 57.5727 | 0.017369 | thinking--"to go or not to go?" We are this far on the way. Reached | 'far':11 'go':3,7 'reach':15 'think':1 'way':14 (2 rows) INSERT INTO test_rum_hash (t) VALUES ('foo bar foo the over foo qq bar'); @@ -219,65 +219,71 @@ SELECT a FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'bar') O (1 row) -- Check full-index scan with order by -SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote'); - ?column? +SELECT + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(10,4) + END distance + FROM + (SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') AS distance + FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote')) t; + distance ---------- 16.4493 16.4493 - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity - Infinity + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 (56 rows) CREATE TABLE tst_hash (i int4, t tsvector); diff --git a/expected/rum_validate.out b/expected/rum_validate.out index 83a312c0ed..e662615e87 100644 --- a/expected/rum_validate.out +++ b/expected/rum_validate.out @@ -90,7 +90,7 @@ FROM unnest(array['asc','desc','nulls_first','nulls_last','orderable','distance_ -- Check incorrect operator class -- DROP INDEX rumidx; --- Check incorrect operator class +-- PGPRO-1175: Check incorrect operator class, i.e. it shouldn't work correctly CREATE OPERATOR CLASS rum_tsvector_norm_ops FOR TYPE tsvector USING rum AS @@ -110,6 +110,7 @@ CREATE INDEX rum_norm_idx ON test_rum USING rum(a rum_tsvector_norm_ops); SET enable_seqscan=off; SET enable_bitmapscan=off; SET enable_indexscan=on; +-- PGPRO-1175: Select using incorrect operator class SELECT a FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'bar') diff --git a/sql/altorder.sql b/sql/altorder.sql index 85c6cdf630..86858d1fbb 100644 --- a/sql/altorder.sql +++ b/sql/altorder.sql @@ -1,13 +1,17 @@ CREATE TABLE atsts (id int, t tsvector, d timestamp); +\copy atsts from 'data/tsts.data' +-- PGPRO-2537: We need more data to test rumsort.c with logtape.c +\copy atsts from 'data/tsts.data' +\copy atsts from 'data/tsts.data' \copy atsts from 'data/tsts.data' CREATE INDEX atsts_idx ON atsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO atsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atsts WHERE t @@ 'wr|qh'; @@ -30,9 +34,8 @@ SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM atsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) @@ -52,6 +55,11 @@ EXPLAIN (costs off) SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; SELECT count(*) FROM atsts WHERE d > '2016-05-16 14:21:25'; +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; + EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; diff --git a/sql/altorder_hash.sql b/sql/altorder_hash.sql index ff07b4f769..3b723876f9 100644 --- a/sql/altorder_hash.sql +++ b/sql/altorder_hash.sql @@ -6,8 +6,8 @@ CREATE INDEX atstsh_idx ON atstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't', order_by_attach='t'); -INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO atstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO atstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); SELECT count(*) FROM atstsh WHERE t @@ 'wr|qh'; @@ -30,9 +30,8 @@ SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM atstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; -RESET enable_indexscan; -RESET enable_indexonlyscan; -RESET enable_bitmapscan; +-- Test bitmap index scan +SET enable_bitmapscan=on; SET enable_seqscan = off; EXPLAIN (costs off) @@ -52,6 +51,11 @@ EXPLAIN (costs off) SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; SELECT count(*) FROM atstsh WHERE d > '2016-05-16 14:21:25'; +-- Test index scan +SET enable_indexscan=on; +SET enable_indexonlyscan=on; +SET enable_bitmapscan=off; + EXPLAIN (costs off) SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; SELECT id, d, d <=> '2016-05-16 14:21:25' FROM atstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; diff --git a/sql/array.sql b/sql/array.sql index e3869b06d3..11defc9e07 100644 --- a/sql/array.sql +++ b/sql/array.sql @@ -210,4 +210,10 @@ CREATE INDEX idx_array_order ON test_array_order USING rum (i rum_anyarray_ops); EXPLAIN (COSTS OFF) SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> '{51}'; -SELECT *, i <=> '{51}' from test_array_order WHERE i @> '{23,20}' order by i <=> '{51}'; +SELECT i, + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(18,14) + END distance + FROM + (SELECT *, (i <=> '{51}') AS distance + FROM test_array_order WHERE i @> '{23,20}' ORDER BY i <=> '{51}') t; diff --git a/sql/orderby.sql b/sql/orderby.sql index f254483ae0..28e5b6038b 100644 --- a/sql/orderby.sql +++ b/sql/orderby.sql @@ -6,17 +6,10 @@ CREATE INDEX tsts_idx ON tsts USING rum (t rum_tsvector_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tsts VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tsts VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); -SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; -SELECT count(*) FROM tsts WHERE t @@ 'wr&qh'; -SELECT count(*) FROM tsts WHERE t @@ 'eq&yt'; -SELECT count(*) FROM tsts WHERE t @@ 'eq|yt'; -SELECT count(*) FROM tsts WHERE t @@ '(eq&yt)|(wr&qh)'; -SELECT count(*) FROM tsts WHERE t @@ '(eq|yt)&(wr|qh)'; - SET enable_indexscan=OFF; SET enable_indexonlyscan=OFF; SET enable_bitmapscan=OFF; @@ -27,8 +20,7 @@ SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; -RESET enable_indexscan; -RESET enable_indexonlyscan; +-- Test bitmap index scan RESET enable_bitmapscan; SET enable_seqscan = off; @@ -62,8 +54,34 @@ EXPLAIN (costs off) SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; +-- Test index scan +RESET enable_indexscan; +RESET enable_indexonlyscan; SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; +SELECT count(*) FROM tsts WHERE t @@ 'wr|qh'; +SELECT count(*) FROM tsts WHERE t @@ 'wr&qh'; +SELECT count(*) FROM tsts WHERE t @@ 'eq&yt'; +SELECT count(*) FROM tsts WHERE t @@ 'eq|yt'; +SELECT count(*) FROM tsts WHERE t @@ '(eq&yt)|(wr&qh)'; +SELECT count(*) FROM tsts WHERE t @@ '(eq|yt)&(wr|qh)'; + +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tsts ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + EXPLAIN (costs off) SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM tsts WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; diff --git a/sql/orderby_hash.sql b/sql/orderby_hash.sql index 66a45268ca..f7e9808538 100644 --- a/sql/orderby_hash.sql +++ b/sql/orderby_hash.sql @@ -6,17 +6,10 @@ CREATE INDEX tstsh_idx ON tstsh USING rum (t rum_tsvector_hash_addon_ops, d) WITH (attach = 'd', to = 't'); -INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); -INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); +INSERT INTO tstsh VALUES (-1, 't1 t2', '2016-05-02 02:24:22.326724'); +INSERT INTO tstsh VALUES (-2, 't1 t2 t3', '2016-05-02 02:26:22.326724'); -SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; -SELECT count(*) FROM tstsh WHERE t @@ 'wr&qh'; -SELECT count(*) FROM tstsh WHERE t @@ 'eq&yt'; -SELECT count(*) FROM tstsh WHERE t @@ 'eq|yt'; -SELECT count(*) FROM tstsh WHERE t @@ '(eq&yt)|(wr&qh)'; -SELECT count(*) FROM tstsh WHERE t @@ '(eq|yt)&(wr|qh)'; - SET enable_indexscan=OFF; SET enable_indexonlyscan=OFF; SET enable_bitmapscan=OFF; @@ -27,8 +20,7 @@ SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; -RESET enable_indexscan; -RESET enable_indexonlyscan; +-- Test bitmap index scan RESET enable_bitmapscan; SET enable_seqscan = off; @@ -62,8 +54,34 @@ EXPLAIN (costs off) SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d >= '2016-05-16 14:21:25' ORDER BY d; +-- Test index scan +RESET enable_indexscan; +RESET enable_indexonlyscan; SET enable_bitmapscan=OFF; +EXPLAIN (costs off) +SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; +SELECT count(*) FROM tstsh WHERE t @@ 'wr|qh'; +SELECT count(*) FROM tstsh WHERE t @@ 'wr&qh'; +SELECT count(*) FROM tstsh WHERE t @@ 'eq&yt'; +SELECT count(*) FROM tstsh WHERE t @@ 'eq|yt'; +SELECT count(*) FROM tstsh WHERE t @@ '(eq&yt)|(wr&qh)'; +SELECT count(*) FROM tstsh WHERE t @@ '(eq|yt)&(wr|qh)'; + +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +EXPLAIN (costs off) +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=| '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d <=| '2016-05-16 14:21:25' LIMIT 5; +EXPLAIN (costs off) +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d |=> '2016-05-16 14:21:25' FROM tstsh WHERE t @@ 'wr&qh' ORDER BY d |=> '2016-05-16 14:21:25' LIMIT 5; + +EXPLAIN (costs off) +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; +SELECT id, d, d <=> '2016-05-16 14:21:25' FROM tstsh ORDER BY d <=> '2016-05-16 14:21:25' LIMIT 5; + EXPLAIN (costs off) SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; SELECT id, d FROM tstsh WHERE t @@ 'wr&qh' AND d <= '2016-05-16 14:21:25' ORDER BY d; diff --git a/sql/rum.sql b/sql/rum.sql index 8b8607faa6..de432fde1a 100644 --- a/sql/rum.sql +++ b/sql/rum.sql @@ -47,34 +47,34 @@ SELECT count(*) FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'def <-> fgr'); SELECT count(*) FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'def <2> fgr'); -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,7), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way'); -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); SELECT - a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'), - rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), + (a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4) AS distance, + rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), * FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)') limit 2; -- Check ranking normalization -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,7), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way'); -SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), - rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), +SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,4), + rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,6), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') @@ -93,7 +93,13 @@ SELECT count(*) FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'rat') SELECT a FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'bar') ORDER BY a; -- Check full-index scan with order by -SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote'); +SELECT + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(10,4) + END distance + FROM + (SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') AS distance + FROM test_rum ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote')) t; CREATE TABLE tst (i int4, t tsvector); INSERT INTO tst SELECT i%10, to_tsvector('simple', substr(md5(i::text), 1, 1)) FROM generate_series(1,100000) i; @@ -126,14 +132,14 @@ SELECT a <=> to_tsquery('pg_catalog.english', 'w:*'), * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'w:*') ORDER BY a <=> to_tsquery('pg_catalog.english', 'w:*'); -SELECT a <=> to_tsquery('pg_catalog.english', 'w:*'), * +SELECT (a <=> to_tsquery('pg_catalog.english', 'w:*'))::numeric(10,4) AS distance, * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'w:*') ORDER BY a <=> to_tsquery('pg_catalog.english', 'w:*'); -SELECT a <=> to_tsquery('pg_catalog.english', 'b:*'), * +SELECT (a <=> to_tsquery('pg_catalog.english', 'b:*'))::numeric(10,4) AS distance, * FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'b:*') ORDER BY a <=> to_tsquery('pg_catalog.english', 'b:*'); -select 'bjarn:6237 stroustrup:6238'::tsvector <=> 'bjarn <-> stroustrup'::tsquery; -SELECT 'stroustrup:5508B,6233B,6238B bjarn:6235B,6237B' <=> 'bjarn <-> stroustrup'::tsquery; +select ('bjarn:6237 stroustrup:6238'::tsvector <=> 'bjarn <-> stroustrup'::tsquery)::numeric(10,5) AS distance; +SELECT ('stroustrup:5508B,6233B,6238B bjarn:6235B,6237B' <=> 'bjarn <-> stroustrup'::tsquery)::numeric(10,5) AS distance; diff --git a/sql/rum_hash.sql b/sql/rum_hash.sql index 511e772da5..a33b8fde31 100644 --- a/sql/rum_hash.sql +++ b/sql/rum_hash.sql @@ -35,35 +35,35 @@ SELECT count(*) FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'def <-> fgr'); SELECT count(*) FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'def <2> fgr'); -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'))::numeric(10,7), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way'); -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'); SELECT - a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'), - rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)')), + (a <=> to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4) AS distance, + rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way & (go | half)'))::numeric(10,6), * FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'way & (go | half)') limit 2; -- Check ranking normalization -SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0), - rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0), +SELECT rum_ts_distance(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,4), + rum_ts_score(a, to_tsquery('pg_catalog.english', 'way'), 0)::numeric(10,7), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way') ORDER BY a <=> to_tsquery('pg_catalog.english', 'way'); -SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), - rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query), +SELECT rum_ts_distance(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,4), + rum_ts_score(a, row(to_tsquery('pg_catalog.english', 'way & (go | half)'), 0)::rum_distance_query)::numeric(10,6), * FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'way & (go | half)') @@ -82,7 +82,13 @@ SELECT count(*) FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', ' SELECT a FROM test_rum_hash WHERE a @@ to_tsquery('pg_catalog.english', 'bar') ORDER BY a; -- Check full-index scan with order by -SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote'); +SELECT + CASE WHEN distance = 'Infinity' THEN -1 + ELSE distance::numeric(10,4) + END distance + FROM + (SELECT a <=> to_tsquery('pg_catalog.english', 'ever|wrote') AS distance + FROM test_rum_hash ORDER BY a <=> to_tsquery('pg_catalog.english', 'ever|wrote')) t; CREATE TABLE tst_hash (i int4, t tsvector); INSERT INTO tst_hash SELECT i%10, to_tsvector('simple', substr(md5(i::text), 1, 1)) FROM generate_series(1,100000) i; diff --git a/sql/rum_validate.sql b/sql/rum_validate.sql index 24bc4aa7c3..feb8e2765a 100644 --- a/sql/rum_validate.sql +++ b/sql/rum_validate.sql @@ -31,7 +31,7 @@ FROM unnest(array['asc','desc','nulls_first','nulls_last','orderable','distance_ DROP INDEX rumidx; --- Check incorrect operator class +-- PGPRO-1175: Check incorrect operator class, i.e. it shouldn't work correctly CREATE OPERATOR CLASS rum_tsvector_norm_ops FOR TYPE tsvector USING rum AS @@ -54,7 +54,8 @@ SET enable_seqscan=off; SET enable_bitmapscan=off; SET enable_indexscan=on; +-- PGPRO-1175: Select using incorrect operator class SELECT a FROM test_rum WHERE a @@ to_tsquery('pg_catalog.english', 'bar') - ORDER BY a <=> (to_tsquery('pg_catalog.english', 'bar'),0) \ No newline at end of file + ORDER BY a <=> (to_tsquery('pg_catalog.english', 'bar'),0) diff --git a/src/rum.h b/src/rum.h index 9dcb41a730..36f2e21f4b 100644 --- a/src/rum.h +++ b/src/rum.h @@ -3,7 +3,7 @@ * rum.h * Exported definitions for RUM index. * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 2006-2016, PostgreSQL Global Development Group * *------------------------------------------------------------------------- @@ -19,6 +19,8 @@ #include "access/sdir.h" #include "lib/rbtree.h" #include "storage/bufmgr.h" +#include "utils/datum.h" +#include "utils/memutils.h" #include "rumsort.h" @@ -529,7 +531,7 @@ extern void rumEntryFillRoot(RumBtree btree, Buffer root, Buffer lbuf, Buffer rb Page page, Page lpage, Page rpage); extern IndexTuple rumPageGetLinkItup(RumBtree btree, Buffer buf, Page page); extern void rumReadTuple(RumState * rumstate, OffsetNumber attnum, - IndexTuple itup, RumItem * items); + IndexTuple itup, RumItem * items, bool copyAddInfo); extern void rumReadTuplePointers(RumState * rumstate, OffsetNumber attnum, IndexTuple itup, ItemPointerData *ipd); extern void updateItemIndexes(Page page, OffsetNumber attnum, RumState * rumstate); @@ -783,7 +785,7 @@ extern IndexBulkDeleteResult *rumvacuumcleanup(IndexVacuumInfo *info, extern bool rumvalidate(Oid opclassoid); /* rumbulk.c */ -#if PG_VERSION_NUM <= 100006 +#if PG_VERSION_NUM <= 100006 || PG_VERSION_NUM == 110000 typedef RBNode RBTNode; #endif @@ -941,10 +943,14 @@ rumDataPageLeafReadItemPointer(char *ptr, ItemPointer iptr, bool *addInfoIsNull) * Reads next item pointer and additional information from leaf data page. * Replaces current item pointer with the next one. Zero item pointer should be * passed in order to read the first item pointer. + * + * It is necessary to pass copyAddInfo=true if additional information is used + * when the data page is unlocked. If the additional information is used without + * locking one can get unexpected behaviour. */ static inline Pointer rumDataPageLeafRead(Pointer ptr, OffsetNumber attnum, RumItem * item, - RumState * rumstate) + bool copyAddInfo, RumState * rumstate) { Form_pg_attribute attr; @@ -1009,8 +1015,13 @@ rumDataPageLeafRead(Pointer ptr, OffsetNumber attnum, RumItem * item, } else { - ptr = (Pointer) att_align_pointer(ptr, attr->attalign, attr->attlen, ptr); - item->addInfo = fetch_att(ptr, attr->attbyval, attr->attlen); + Datum addInfo; + + ptr = (Pointer) att_align_pointer(ptr, attr->attalign, attr->attlen, + ptr); + addInfo = fetch_att(ptr, attr->attbyval, attr->attlen); + item->addInfo = copyAddInfo ? + datumCopy(addInfo, attr->attbyval, attr->attlen) : addInfo; } ptr = (Pointer) att_addlength_pointer(ptr, attr->attlen, ptr); diff --git a/src/rum_arr_utils.c b/src/rum_arr_utils.c index 78b788eb8b..86fab36074 100644 --- a/src/rum_arr_utils.c +++ b/src/rum_arr_utils.c @@ -3,7 +3,7 @@ * rum_arr_utils.c * various anyarray-search functions * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * *------------------------------------------------------------------------- @@ -51,7 +51,11 @@ #define CHECKARRVALID(x) \ do { \ - if (x) { \ + if (x == NULL) \ + ereport(ERROR, \ + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \ + errmsg("array must not be NULL"))); \ + else if (x) { \ if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \ ereport(ERROR, \ (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \ @@ -733,6 +737,7 @@ cmpAscArrayElem(const void *a, const void *b, void *arg) { FmgrInfo *cmpFunc = (FmgrInfo*)arg; + Assert(a && b); return DatumGetInt32(FunctionCall2Coll(cmpFunc, DEFAULT_COLLATION_OID, *(Datum*)a, *(Datum*)b)); } diff --git a/src/rum_ts_utils.c b/src/rum_ts_utils.c index b43ac3b0a3..4cfda6b80a 100644 --- a/src/rum_ts_utils.c +++ b/src/rum_ts_utils.c @@ -3,7 +3,7 @@ * rum_ts_utils.c * various text-search functions * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * *------------------------------------------------------------------------- @@ -873,7 +873,7 @@ Cover(DocRepresentation *doc, uint32 len, QueryRepresentation *qr, memset(qr->operandData, 0, sizeof(qr->operandData[0]) * qr->length); - ext->p = 0x7fffffff; + ext->p = PG_INT32_MAX; ext->q = 0; ptr = doc + ext->pos; @@ -1242,7 +1242,7 @@ calc_score_docr(float4 *arrdata, DocRepresentation *doc, uint32 doclen, int new_cover_key = 0; int nitems = 0; - while (ptr <= ext.end) + while (ptr && ptr <= ext.end) { InvSum += arrdata[ptr->wclass]; /* SK: Quick and dirty hash key. Hope collisions will be not too frequent. */ diff --git a/src/rumbtree.c b/src/rumbtree.c index c2106eeab2..2e1e520df9 100644 --- a/src/rumbtree.c +++ b/src/rumbtree.c @@ -4,7 +4,7 @@ * page utilities routines for the postgres inverted index access method. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * diff --git a/src/rumbulk.c b/src/rumbulk.c index 9bbe88da6a..b9e94df375 100644 --- a/src/rumbulk.c +++ b/src/rumbulk.c @@ -4,7 +4,7 @@ * routines for fast build of inverted index * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -14,7 +14,6 @@ #include "postgres.h" #include "utils/datum.h" -#include "utils/memutils.h" #include "rum.h" @@ -22,7 +21,7 @@ #define DEF_NPTR 5 /* ItemPointer initial allocation quantum */ /* PostgreSQL pre 10 has different names for this functions */ -#if PG_VERSION_NUM <= 100006 +#if PG_VERSION_NUM <= 100006 || PG_VERSION_NUM == 110000 #define rbt_create(node_size, comparator, combiner, allocfunc, freefunc, arg) \ (rb_create(node_size, comparator, combiner, allocfunc, freefunc, arg)) #define rbt_insert(rbt, data, isNew) \ @@ -167,6 +166,7 @@ rumInsertBAEntry(BuildAccumulator *accum, eatmp.category = category; /* temporarily set up single-entry itempointer list */ eatmp.list = &item; + memset(&item, 0, sizeof(item)); item.iptr = *heapptr; item.addInfo = addInfo; item.addInfoIsNull = addInfoIsNull; @@ -280,7 +280,7 @@ qsortCompareRumItem(const void *a, const void *b, void *arg) void rumBeginBAScan(BuildAccumulator *accum) { -#if PG_VERSION_NUM > 100006 +#if (PG_VERSION_NUM > 100006 && PG_VERSION_NUM < 110000) || PG_VERSION_NUM >= 110001 rbt_begin_iterate(accum->tree, LeftRightWalk, &accum->tree_walk); #elif PG_VERSION_NUM >= 100000 rb_begin_iterate(accum->tree, LeftRightWalk, &accum->tree_walk); @@ -302,7 +302,7 @@ rumGetBAEntry(BuildAccumulator *accum, RumEntryAccumulator *entry; RumItem *list; -#if PG_VERSION_NUM > 100006 +#if (PG_VERSION_NUM > 100006 && PG_VERSION_NUM < 110000) || PG_VERSION_NUM >= 110001 entry = (RumEntryAccumulator *) rbt_iterate(&accum->tree_walk); #elif PG_VERSION_NUM >= 100000 entry = (RumEntryAccumulator *) rb_iterate(&accum->tree_walk); diff --git a/src/rumdatapage.c b/src/rumdatapage.c index 18b537a2fc..66049e8bf7 100644 --- a/src/rumdatapage.c +++ b/src/rumdatapage.c @@ -4,7 +4,7 @@ * page utilities routines for the postgres inverted index access method. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -589,7 +589,7 @@ findInLeafPage(RumBtree btree, Page page, OffsetNumber *offset, *iptrOut = item.iptr; ptr = rumDataPageLeafRead(ptr, btree->entryAttnum, &item, - btree->rumstate); + false, btree->rumstate); cmp = compareRumItem(btree->rumstate, btree->entryAttnum, &btree->items[btree->curitem], &item); @@ -899,7 +899,8 @@ dataPlaceToPage(RumBtree btree, Page page, OffsetNumber off) if (copyItemEmpty == true && off <= maxoff) { copyPtr = rumDataPageLeafRead(copyPtr, btree->entryAttnum, - ©Item, btree->rumstate); + ©Item, false, + btree->rumstate); copyItemEmpty = false; } @@ -1056,6 +1057,7 @@ dataSplitPageLeaf(RumBtree btree, Buffer lbuf, Buffer rbuf, int maxItemIndex = btree->curitem; static char lpageCopy[BLCKSZ]; + memset(&item, 0, sizeof(item)); dataPrepareData(btree, newlPage, off); maxoff = RumPageGetOpaque(newlPage)->maxoff; @@ -1090,7 +1092,7 @@ dataSplitPageLeaf(RumBtree btree, Buffer lbuf, Buffer rbuf, prevIptr = item.iptr; copyPtr = rumDataPageLeafRead(copyPtr, btree->entryAttnum, &item, - btree->rumstate); + false, btree->rumstate); prevTotalsize = totalsize; totalsize = rumCheckPlaceToDataPageLeaf(btree->entryAttnum, @@ -1168,7 +1170,7 @@ dataSplitPageLeaf(RumBtree btree, Buffer lbuf, Buffer rbuf, } copyPtr = rumDataPageLeafRead(copyPtr, btree->entryAttnum, &item, - btree->rumstate); + false, btree->rumstate); curItem = item; ptr = rumPlaceToDataPageLeaf(ptr, btree->entryAttnum, &item, @@ -1350,7 +1352,7 @@ updateItemIndexes(Page page, OffsetNumber attnum, RumState * rumstate) } j++; } - ptr = rumDataPageLeafRead(ptr, attnum, &item, rumstate); + ptr = rumDataPageLeafRead(ptr, attnum, &item, false, rumstate); } /* Fill rest of page indexes with InvalidOffsetNumber if any */ for (; j < RumDataLeafIndexCount; j++) diff --git a/src/rumentrypage.c b/src/rumentrypage.c index 7029942e78..10334ec862 100644 --- a/src/rumentrypage.c +++ b/src/rumentrypage.c @@ -4,7 +4,7 @@ * page utilities routines for the postgres inverted index access method. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -21,7 +21,7 @@ */ void rumReadTuple(RumState * rumstate, OffsetNumber attnum, - IndexTuple itup, RumItem * items) + IndexTuple itup, RumItem * items, bool copyAddInfo) { Pointer ptr = RumGetPosting(itup); RumItem item; @@ -31,7 +31,7 @@ rumReadTuple(RumState * rumstate, OffsetNumber attnum, ItemPointerSetMin(&item.iptr); for (i = 0; i < nipd; i++) { - ptr = rumDataPageLeafRead(ptr, attnum, &item, rumstate); + ptr = rumDataPageLeafRead(ptr, attnum, &item, copyAddInfo, rumstate); items[i] = item; } } diff --git a/src/rumget.c b/src/rumget.c index 2e5dd2593b..32cb13eb94 100644 --- a/src/rumget.c +++ b/src/rumget.c @@ -4,7 +4,7 @@ * fetch tuples from a RUM scan. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -22,7 +22,6 @@ #if PG_VERSION_NUM >= 120000 #include "utils/float.h" #endif -#include "utils/memutils.h" #include "rum.h" @@ -258,7 +257,8 @@ scanPostingTree(Relation index, RumScanEntry scanEntry, ptr = RumDataPageGetData(page); for (i = FirstOffsetNumber; i <= maxoff; i++) { - ptr = rumDataPageLeafRead(ptr, attnum, &item.item, rumstate); + ptr = rumDataPageLeafRead(ptr, attnum, &item.item, false, + rumstate); SCAN_ITEM_PUT_KEY(scanEntry, item, idatum, icategory); rum_tuplesort_putrumitem(scanEntry->matchSortstate, &item); } @@ -468,7 +468,7 @@ collectMatchBitmap(RumBtreeData * btree, RumBtreeStack * stack, for (i = 0; i < RumGetNPosting(itup); i++) { ptr = rumDataPageLeafRead(ptr, scanEntry->attnum, &item.item, - rumstate); + false, rumstate); SCAN_ITEM_PUT_KEY(scanEntry, item, idatum, icategory); rum_tuplesort_putrumitem(scanEntry->matchSortstate, &item); } @@ -674,7 +674,8 @@ startScanEntry(RumState * rumstate, RumScanEntry entry, Snapshot snapshot) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { - ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, rumstate); + ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, true, + rumstate); entry->list[i - FirstOffsetNumber] = item; } @@ -689,7 +690,7 @@ startScanEntry(RumState * rumstate, RumScanEntry entry, Snapshot snapshot) entry->predictNumberResult = entry->nlist; entry->list = (RumItem *) palloc(sizeof(RumItem) * entry->nlist); - rumReadTuple(rumstate, entry->attnum, itup, entry->list); + rumReadTuple(rumstate, entry->attnum, itup, entry->list, true); entry->isFinished = setListPositionScanEntry(rumstate, entry); if (!entry->isFinished) entry->curItem = entry->list[entry->offset]; @@ -935,7 +936,8 @@ entryGetNextItem(RumState * rumstate, RumScanEntry entry, Snapshot snapshot) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { - ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, rumstate); + ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, true, + rumstate); entry->list[i - FirstOffsetNumber] = item; if (searchBorder) @@ -1091,7 +1093,8 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry, Snapshot snapshot) for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) { - ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, rumstate); + ptr = rumDataPageLeafRead(ptr, entry->attnum, &item, true, + rumstate); entry->list[i - FirstOffsetNumber] = item; } @@ -1104,11 +1107,11 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry, Snapshot snapshot) entry->predictNumberResult = entry->nlist; entry->list = (RumItem *) palloc(sizeof(RumItem) * entry->nlist); - rumReadTuple(rumstate, entry->attnum, itup, entry->list); + rumReadTuple(rumstate, entry->attnum, itup, entry->list, true); entry->isFinished = setListPositionScanEntry(rumstate, entry); } - Assert(entry->nlist > 0); + Assert(entry->nlist > 0 && entry->list); entry->curItem = entry->list[entry->offset]; entry->offset += entry->scanDirection; @@ -1165,7 +1168,7 @@ entryGetItem(RumState * rumstate, RumScanEntry entry, bool *nextEntryList, Snaps if (!ItemPointerIsMin(&entry->collectRumItem.item.iptr)) collected = entry->collectRumItem; else - ItemPointerSetMin(&collected.item.iptr); + MemSet(&collected, 0, sizeof(collected)); ItemPointerSetMin(&entry->curItem.iptr); @@ -1659,7 +1662,8 @@ scanPage(RumState * rumstate, RumScanEntry entry, RumItem *item, bool equalOk) bound = -1; for (i = first; i <= maxoff; i++) { - ptr = rumDataPageLeafRead(ptr, entry->attnum, &iter_item, rumstate); + ptr = rumDataPageLeafRead(ptr, entry->attnum, &iter_item, true, + rumstate); entry->list[i - first] = iter_item; if (bound != -1) @@ -2241,8 +2245,8 @@ insertScanItem(RumScanOpaque so, bool recheck) j; item = (RumSortItem *) - MemoryContextAlloc(rum_tuplesort_get_memorycontext(so->sortstate), - RumSortItemSize(so->norderbys)); + MemoryContextAllocZero(rum_tuplesort_get_memorycontext(so->sortstate), + RumSortItemSize(so->norderbys)); item->iptr = so->item.iptr; item->recheck = recheck; @@ -2352,6 +2356,14 @@ rumgettuple(IndexScanDesc scan, ScanDirection direction) RumSortItem *item; bool should_free; +#if PG_VERSION_NUM >= 120000 +#define GET_SCAN_TID(scan) ((scan)->xs_heaptid) +#define SET_SCAN_TID(scan, tid) ((scan)->xs_heaptid = (tid)) +#else +#define GET_SCAN_TID(scan) ((scan)->xs_ctup.t_self) +#define SET_SCAN_TID(scan, tid) ((scan)->xs_ctup.t_self = (tid)) +#endif + if (so->firstCall) { /* @@ -2361,6 +2373,7 @@ rumgettuple(IndexScanDesc scan, ScanDirection direction) rumNewScanKey(scan); so->firstCall = false; + ItemPointerSetInvalid(&GET_SCAN_TID(scan)); if (RumIsVoidRes(scan)) return false; @@ -2384,7 +2397,7 @@ rumgettuple(IndexScanDesc scan, ScanDirection direction) { if (scanGetItem(scan, &so->item, &so->item, &recheck)) { - scan->xs_ctup.t_self = so->item.iptr; + SET_SCAN_TID(scan, so->item.iptr); scan->xs_recheck = recheck; scan->xs_recheckorderby = false; @@ -2406,7 +2419,7 @@ rumgettuple(IndexScanDesc scan, ScanDirection direction) uint32 i, j = 0; - if (rumCompareItemPointers(&scan->xs_ctup.t_self, &item->iptr) == 0) + if (rumCompareItemPointers(&GET_SCAN_TID(scan), &item->iptr) == 0) { if (should_free) pfree(item); @@ -2414,7 +2427,7 @@ rumgettuple(IndexScanDesc scan, ScanDirection direction) continue; } - scan->xs_ctup.t_self = item->iptr; + SET_SCAN_TID(scan, item->iptr); scan->xs_recheck = item->recheck; scan->xs_recheckorderby = false; diff --git a/src/ruminsert.c b/src/ruminsert.c index f9ce47a30d..7315f517f3 100644 --- a/src/ruminsert.c +++ b/src/ruminsert.c @@ -4,7 +4,7 @@ * insert routines for the postgres inverted index access method. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -14,10 +14,12 @@ #include "postgres.h" #include "access/generic_xlog.h" +#if PG_VERSION_NUM >= 120000 +#include "access/tableam.h" +#endif #include "storage/predicate.h" #include "catalog/index.h" #include "miscadmin.h" -#include "utils/memutils.h" #include "utils/datum.h" #include "rum.h" @@ -32,7 +34,11 @@ typedef struct BuildAccumulator accum; } RumBuildState; -#if PG_VERSION_NUM >= 110000 + +#if PG_VERSION_NUM >= 120000 +#define IndexBuildHeapScan(A, B, C, D, E, F) \ +table_index_build_scan(A, B, C, D, true, E, F, NULL) +#elif PG_VERSION_NUM >= 110000 #define IndexBuildHeapScan(A, B, C, D, E, F) \ IndexBuildHeapScan(A, B, C, D, E, F, NULL) #endif @@ -272,7 +278,7 @@ addItemPointersToLeafTuple(RumState * rumstate, newNPosting = oldNPosting + nitem; newItems = (RumItem *) palloc(sizeof(RumItem) * newNPosting); - rumReadTuple(rumstate, attnum, old, oldItems); + rumReadTuple(rumstate, attnum, old, oldItems, false); newNPosting = rumMergeRumItems(rumstate, attnum, newItems, items, nitem, oldItems, oldNPosting); @@ -544,7 +550,13 @@ rumHeapTupleBulkInsert(RumBuildState * buildstate, OffsetNumber attnum, } static void -rumBuildCallback(Relation index, HeapTuple htup, Datum *values, +rumBuildCallback(Relation index, +#if PG_VERSION_NUM < 130000 + HeapTuple htup, +#else + ItemPointer tid, +#endif + Datum *values, bool *isnull, bool tupleIsAlive, void *state) { RumBuildState *buildstate = (RumBuildState *) state; @@ -552,6 +564,9 @@ rumBuildCallback(Relation index, HeapTuple htup, Datum *values, int i; Datum outerAddInfo = (Datum) 0; bool outerAddInfoIsNull = true; +#if PG_VERSION_NUM < 130000 + ItemPointer tid = &htup->t_self; +#endif if (AttributeNumberIsValid(buildstate->rumstate.attrnAttachColumn)) { @@ -564,7 +579,7 @@ rumBuildCallback(Relation index, HeapTuple htup, Datum *values, for (i = 0; i < buildstate->rumstate.origTupdesc->natts; i++) rumHeapTupleBulkInsert(buildstate, (OffsetNumber) (i + 1), values[i], isnull[i], - &htup->t_self, + tid, outerAddInfo, outerAddInfoIsNull); /* If we've maxed out our available memory, dump everything to the index */ @@ -789,6 +804,7 @@ rumHeapTupleInsert(RumState * rumstate, OffsetNumber attnum, NameStr(attr->attname)); } + memset(&insert_item, 0, sizeof(insert_item)); insert_item.iptr = *item; insert_item.addInfo = addInfo[i]; insert_item.addInfoIsNull = addInfoIsNull[i]; diff --git a/src/rumscan.c b/src/rumscan.c index 27d7f05c2d..34de9d4fc4 100644 --- a/src/rumscan.c +++ b/src/rumscan.c @@ -4,7 +4,7 @@ * routines to manage scans of inverted index relations * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -15,7 +15,6 @@ #include "access/relscan.h" #include "pgstat.h" -#include "utils/memutils.h" #include "rum.h" @@ -42,6 +41,13 @@ rumbeginscan(Relation rel, int nkeys, int norderbys) initRumState(&so->rumstate, scan->indexRelation); +#if PG_VERSION_NUM >= 120000 + /* + * Starting from PG 12 we need to invalidate result's item pointer. Earlier + * it was done by invalidating scan->xs_ctup by RelationGetIndexScan(). + */ + ItemPointerSetInvalid(&scan->xs_heaptid); +#endif scan->opaque = so; return scan; diff --git a/src/rumsort.c b/src/rumsort.c index a47801c6b7..8aa10fef4f 100644 --- a/src/rumsort.c +++ b/src/rumsort.c @@ -3,115 +3,12 @@ * rumsort.h * Generalized tuple sorting routines. * - * This module handles sorting of heap tuples, index tuples, or single - * Datums (and could easily support other kinds of sortable objects, - * if necessary). It works efficiently for both small and large amounts - * of data. Small amounts are sorted in-memory using qsort(). Large - * amounts are sorted using temporary files and a standard external sort - * algorithm. + * This module handles sorting of RumSortItem or RumScanItem structures. + * It contains copy of static functions from + * src/backend/utils/sort/tuplesort.c. * - * See Knuth, volume 3, for more than you want to know about the external - * sorting algorithm. Historically, we divided the input into sorted runs - * using replacement selection, in the form of a priority tree implemented - * as a heap (essentially his Algorithm 5.2.3H -- although that strategy is - * often avoided altogether), but that can now only happen first the first - * run. We merge the runs using polyphase merge, Knuth's Algorithm - * 5.4.2D. The logical "tapes" used by Algorithm D are implemented by - * logtape.c, which avoids space wastage by recycling disk space as soon - * as each block is read from its "tape". * - * We never form the initial runs using Knuth's recommended replacement - * selection data structure (Algorithm 5.4.1R), because it uses a fixed - * number of records in memory at all times. Since we are dealing with - * tuples that may vary considerably in size, we want to be able to vary - * the number of records kept in memory to ensure full utilization of the - * allowed sort memory space. So, we keep the tuples in a variable-size - * heap, with the next record to go out at the top of the heap. Like - * Algorithm 5.4.1R, each record is stored with the run number that it - * must go into, and we use (run number, key) as the ordering key for the - * heap. When the run number at the top of the heap changes, we know that - * no more records of the prior run are left in the heap. Note that there - * are in practice only ever two distinct run numbers, due to the greatly - * reduced use of replacement selection in PostgreSQL 9.6. - * - * In PostgreSQL 9.6, a heap (based on Knuth's Algorithm H, with some small - * customizations) is only used with the aim of producing just one run, - * thereby avoiding all merging. Only the first run can use replacement - * selection, which is why there are now only two possible valid run - * numbers, and why heapification is customized to not distinguish between - * tuples in the second run (those will be quicksorted). We generally - * prefer a simple hybrid sort-merge strategy, where runs are sorted in much - * the same way as the entire input of an internal sort is sorted (using - * qsort()). The replacement_sort_tuples GUC controls the limited remaining - * use of replacement selection for the first run. - * - * There are several reasons to favor a hybrid sort-merge strategy. - * Maintaining a priority tree/heap has poor CPU cache characteristics. - * Furthermore, the growth in main memory sizes has greatly diminished the - * value of having runs that are larger than available memory, even in the - * case where there is partially sorted input and runs can be made far - * larger by using a heap. In most cases, a single-pass merge step is all - * that is required even when runs are no larger than available memory. - * Avoiding multiple merge passes was traditionally considered to be the - * major advantage of using replacement selection. - * - * The approximate amount of memory allowed for any one sort operation - * is specified in kilobytes by the caller (most pass work_mem). Initially, - * we absorb tuples and simply store them in an unsorted array as long as - * we haven't exceeded workMem. If we reach the end of the input without - * exceeding workMem, we sort the array using qsort() and subsequently return - * tuples just by scanning the tuple array sequentially. If we do exceed - * workMem, we begin to emit tuples into sorted runs in temporary tapes. - * When tuples are dumped in batch after quicksorting, we begin a new run - * with a new output tape (selected per Algorithm D). After the end of the - * input is reached, we dump out remaining tuples in memory into a final run - * (or two, when replacement selection is still used), then merge the runs - * using Algorithm D. - * - * When merging runs, we use a heap containing just the frontmost tuple from - * each source run; we repeatedly output the smallest tuple and insert the - * next tuple from its source tape (if any). When the heap empties, the merge - * is complete. The basic merge algorithm thus needs very little memory --- - * only M tuples for an M-way merge, and M is constrained to a small number. - * However, we can still make good use of our full workMem allocation by - * pre-reading additional tuples from each source tape. Without prereading, - * our access pattern to the temporary file would be very erratic; on average - * we'd read one block from each of M source tapes during the same time that - * we're writing M blocks to the output tape, so there is no sequentiality of - * access at all, defeating the read-ahead methods used by most Unix kernels. - * Worse, the output tape gets written into a very random sequence of blocks - * of the temp file, ensuring that things will be even worse when it comes - * time to read that tape. A straightforward merge pass thus ends up doing a - * lot of waiting for disk seeks. We can improve matters by prereading from - * each source tape sequentially, loading about workMem/M bytes from each tape - * in turn. Then we run the merge algorithm, writing but not reading until - * one of the preloaded tuple series runs out. Then we switch back to preread - * mode, fill memory again, and repeat. This approach helps to localize both - * read and write accesses. - * - * When the caller requests random access to the sort result, we form - * the final sorted run on a logical tape which is then "frozen", so - * that we can access it randomly. When the caller does not need random - * access, we return from rum_tuplesort_performsort() as soon as we are down - * to one run per logical tape. The final merge is then performed - * on-the-fly as the caller repeatedly calls rum_tuplesort_getXXX; this - * saves one cycle of writing all the data out to disk and reading it in. - * - * Before Postgres 8.2, we always used a seven-tape polyphase merge, on the - * grounds that 7 is the "sweet spot" on the tapes-to-passes curve according - * to Knuth's figure 70 (section 5.4.2). However, Knuth is assuming that - * tape drives are expensive beasts, and in particular that there will always - * be many more runs than tape drives. In our implementation a "tape drive" - * doesn't cost much more than a few Kb of memory buffers, so we can afford - * to have lots of them. In particular, if we can have as many tape drives - * as sorted runs, we can eliminate any repeated I/O at all. In the current - * code we determine the number of tapes M on the basis of workMem: we want - * workMem/M to be large enough that we read a fair amount of data each time - * we preread from a tape, so as to maintain the locality of access described - * above. Nonetheless, with large workMem we can have many tapes. - * - * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -122,22 +19,11 @@ #include "miscadmin.h" #include "rumsort.h" -#include - -#include "access/htup_details.h" -#include "access/nbtree.h" -#include "catalog/index.h" -#include "catalog/pg_am.h" #include "commands/tablespace.h" #include "executor/executor.h" -#include "utils/datum.h" +#include "utils/guc.h" #include "utils/logtape.h" -#include "utils/lsyscache.h" -#include "utils/memutils.h" #include "utils/pg_rusage.h" -#include "utils/probes.h" -#include "utils/rel.h" -#include "utils/sortsupport.h" #include "rum.h" /* RumItem */ @@ -147,59 +33,26 @@ #define DATUM_SORT 2 #define CLUSTER_SORT 3 -/* GUC variables */ -#ifdef TRACE_SORT -bool trace_sort = false; -#endif - -#ifdef DEBUG_BOUNDED_SORT -bool optimize_bounded_sort = true; -#endif - #if PG_VERSION_NUM < 100000 /* Provide fallback for old version of tape interface for 9.6 */ #define LogicalTapeRewindForRead(x, y, z) LogicalTapeRewind((x), (y), false) #define LogicalTapeRewindForWrite(x, y) LogicalTapeRewind((x), (y), true) #endif -#if PG_VERSION_NUM >= 110000 -#define RUM_SORT_START(INT1, INT2, INT3, INT4, INT5) \ -TRACE_POSTGRESQL_SORT_START(INT1, INT2, INT3, INT4, INT5, false) -#else -#define RUM_SORT_START(INT1, INT2, INT3, INT4, INT5) \ -TRACE_POSTGRESQL_SORT_START(INT1, INT2, INT3, INT4, INT5) -#endif - #if PG_VERSION_NUM >= 110000 #define LogicalTapeSetCreate(X) LogicalTapeSetCreate(X, NULL, NULL, 1) #define LogicalTapeFreeze(X, Y) LogicalTapeFreeze(X, Y, NULL) #endif /* - * The objects we actually sort are SortTuple structs. These contain - * a pointer to the tuple proper (might be a MinimalTuple or IndexTuple), - * which is a separate palloc chunk --- we assume it is just one chunk and - * can be freed by a simple pfree(). SortTuples also contain the tuple's - * first key column in Datum/nullflag format, and an index integer. - * - * Storing the first key column lets us save heap_getattr or index_getattr - * calls during tuple comparisons. We could extract and save all the key - * columns not just the first, but this would increase code complexity and - * overhead, and wouldn't actually save any comparison cycles in the common - * case where the first key determines the comparison result. Note that - * for a pass-by-reference datatype, datum1 points into the "tuple" storage. - * - * When sorting single Datums, the data value is represented directly by - * datum1/isnull1. If the datatype is pass-by-reference and isnull1 is false, - * then datum1 points to a separately palloc'd data value that is also pointed - * to by the "tuple" pointer; otherwise "tuple" is NULL. - * - * While building initial runs, tupindex holds the tuple's run number. During - * merge passes, we re-use it to hold the input tape number that each tuple in - * the heap was read from, or to hold the index of the next tuple pre-read - * from the same tape in the case of pre-read entries. tupindex goes unused - * if the sort occurs entirely in memory. + * Below are copied definitions from src/backend/utils/sort/tuplesort.c. */ + +/* GUC variables */ +#ifdef TRACE_SORT +bool trace_sort = false; +#endif + typedef struct { void *tuple; /* the tuple proper */ @@ -208,11 +61,6 @@ typedef struct int tupindex; /* see notes above */ } SortTuple; - -/* - * Possible states of a Tuplesort object. These denote the states that - * persist between calls of Tuplesort routines. - */ typedef enum { TSS_INITIAL, /* Loading tuples; still within memory limit */ @@ -223,17 +71,6 @@ typedef enum TSS_FINALMERGE /* Performing final merge on-the-fly */ } TupSortStatus; -/* - * Parameters for calculation of number of tapes to use --- see inittapes() - * and rum_tuplesort_merge_order(). - * - * In this calculation we assume that each tape will cost us about 3 blocks - * worth of buffer space (which is an underestimate for very large data - * volumes, but it's probably close enough --- see logtape.c). - * - * MERGE_BUFFER_SIZE is how much data we'd like to read from each input - * tape during a preread cycle (see discussion at top of file). - */ #define MINORDER 6 /* minimum merge order */ #define TAPE_BUFFER_OVERHEAD (BLCKSZ * 3) #define MERGE_BUFFER_SIZE (BLCKSZ * 32) @@ -242,7 +79,7 @@ typedef int (*SortTupleComparator) (const SortTuple *a, const SortTuple *b, RumTuplesortstate *state); /* - * Private state of a Tuplesort operation. + * Renamed copy of Tuplesortstate. */ struct RumTuplesortstate { @@ -453,47 +290,6 @@ struct RumTuplesortstate #define USEMEM(state,amt) ((state)->availMem -= (amt)) #define FREEMEM(state,amt) ((state)->availMem += (amt)) -/* - * NOTES about on-tape representation of tuples: - * - * We require the first "unsigned int" of a stored tuple to be the total size - * on-tape of the tuple, including itself (so it is never zero; an all-zero - * unsigned int is used to delimit runs). The remainder of the stored tuple - * may or may not match the in-memory representation of the tuple --- - * any conversion needed is the job of the writetup and readtup routines. - * - * If state->randomAccess is true, then the stored representation of the - * tuple must be followed by another "unsigned int" that is a copy of the - * length --- so the total tape space used is actually sizeof(unsigned int) - * more than the stored length value. This allows read-backwards. When - * randomAccess is not true, the write/read routines may omit the extra - * length word. - * - * writetup is expected to write both length words as well as the tuple - * data. When readtup is called, the tape is positioned just after the - * front length word; readtup must read the tuple data and advance past - * the back length word (if present). - * - * The write/read routines can make use of the tuple description data - * stored in the Tuplesortstate record, if needed. They are also expected - * to adjust state->availMem by the amount of memory space (not tape space!) - * released or consumed. There is no error return from either writetup - * or readtup; they should ereport() on failure. - * - * - * NOTES about memory consumption calculations: - * - * We count space allocated for tuples against the workMem limit, plus - * the space used by the variable-size memtuples array. Fixed-size space - * is not counted; it's small enough to not be interesting. - * - * Note that we count actual space used (as shown by GetMemoryChunkSpace) - * rather than the originally-requested size. This is important since - * palloc can add substantial overhead. It's not a complete answer since - * we won't count any wasted space in palloc allocation blocks, but it's - * a lot better than what we were doing before 7.3. - */ - /* When using this macro, beware of double evaluation of len */ #define LogicalTapeReadExact(tapeset, tapenum, ptr, len) \ do { \ @@ -519,40 +315,6 @@ static void rum_tuplesort_heap_insert(RumTuplesortstate *state, SortTuple *tuple static void rum_tuplesort_heap_siftup(RumTuplesortstate *state, bool checkIndex); static unsigned int getlen(RumTuplesortstate *state, int tapenum, bool eofOK); static void markrunend(RumTuplesortstate *state, int tapenum); -static int comparetup_heap(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state); -static void copytup_heap(RumTuplesortstate *state, SortTuple *stup, void *tup); -static void writetup_heap(RumTuplesortstate *state, int tapenum, - SortTuple *stup); -static void readtup_heap(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len); -static void reversedirection_heap(RumTuplesortstate *state); -static int comparetup_cluster(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state); -static void copytup_cluster(RumTuplesortstate *state, SortTuple *stup, void *tup); -static void writetup_cluster(RumTuplesortstate *state, int tapenum, - SortTuple *stup); -static void readtup_cluster(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len); -static int comparetup_index_btree(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state); -static int comparetup_index_hash(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state); -static void copytup_index(RumTuplesortstate *state, SortTuple *stup, void *tup); -static void writetup_index(RumTuplesortstate *state, int tapenum, - SortTuple *stup); -static void readtup_index(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len); -static void reversedirection_index_btree(RumTuplesortstate *state); -static void reversedirection_index_hash(RumTuplesortstate *state); -static int comparetup_datum(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state); -static void copytup_datum(RumTuplesortstate *state, SortTuple *stup, void *tup); -static void writetup_datum(RumTuplesortstate *state, int tapenum, - SortTuple *stup); -static void readtup_datum(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len); -static void reversedirection_datum(RumTuplesortstate *state); static void free_sort_tuple(RumTuplesortstate *state, SortTuple *stup); static int comparetup_rum(const SortTuple *a, const SortTuple *b, RumTuplesortstate *state); @@ -946,221 +708,16 @@ rum_tuplesort_begin_common(int workMem, bool randomAccess) return state; } +/* + * Get sort state memory context. Currently it is used only to allocate + * RumSortItem. + */ MemoryContext rum_tuplesort_get_memorycontext(RumTuplesortstate *state) { return state->sortcontext; } -RumTuplesortstate * -rum_tuplesort_begin_heap(TupleDesc tupDesc, - int nkeys, AttrNumber *attNums, - Oid *sortOperators, Oid *sortCollations, - bool *nullsFirstFlags, - int workMem, bool randomAccess) -{ - RumTuplesortstate *state = rum_tuplesort_begin_common(workMem, randomAccess); - MemoryContext oldcontext; - int i; - - oldcontext = MemoryContextSwitchTo(state->sortcontext); - - AssertArg(nkeys > 0); - -#ifdef TRACE_SORT - if (trace_sort) - elog(LOG, - "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", - nkeys, workMem, randomAccess ? 't' : 'f'); -#endif - - state->nKeys = nkeys; - - RUM_SORT_START(HEAP_SORT, - false, /* no unique check */ - nkeys, - workMem, - randomAccess); - - state->comparetup = comparetup_heap; - state->copytup = copytup_heap; - state->writetup = writetup_heap; - state->readtup = readtup_heap; - state->reversedirection = reversedirection_heap; - - state->tupDesc = tupDesc; /* assume we need not copy tupDesc */ - - /* Prepare SortSupport data for each column */ - state->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData)); - - for (i = 0; i < nkeys; i++) - { - SortSupport sortKey = state->sortKeys + i; - - AssertArg(attNums[i] != 0); - AssertArg(sortOperators[i] != 0); - - sortKey->ssup_cxt = CurrentMemoryContext; - sortKey->ssup_collation = sortCollations[i]; - sortKey->ssup_nulls_first = nullsFirstFlags[i]; - sortKey->ssup_attno = attNums[i]; - - PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey); - } - - if (nkeys == 1) - state->onlyKey = state->sortKeys; - - MemoryContextSwitchTo(oldcontext); - - return state; -} - -RumTuplesortstate * -rum_tuplesort_begin_cluster(TupleDesc tupDesc, - Relation indexRel, - int workMem, bool randomAccess) -{ - RumTuplesortstate *state = rum_tuplesort_begin_common(workMem, randomAccess); - MemoryContext oldcontext; - - Assert(indexRel->rd_rel->relam == BTREE_AM_OID); - - oldcontext = MemoryContextSwitchTo(state->sortcontext); - -#ifdef TRACE_SORT - if (trace_sort) - elog(LOG, - "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", - RelationGetNumberOfAttributes(indexRel), - workMem, randomAccess ? 't' : 'f'); -#endif - - state->nKeys = RelationGetNumberOfAttributes(indexRel); - - RUM_SORT_START(CLUSTER_SORT, - false, /* no unique check */ - state->nKeys, - workMem, - randomAccess); - - state->comparetup = comparetup_cluster; - state->copytup = copytup_cluster; - state->writetup = writetup_cluster; - state->readtup = readtup_cluster; - state->reversedirection = reversedirection_index_btree; - - state->indexInfo = BuildIndexInfo(indexRel); - state->indexScanKey = _bt_mkscankey_nodata(indexRel); - - state->tupDesc = tupDesc; /* assume we need not copy tupDesc */ - - if (state->indexInfo->ii_Expressions != NULL) - { - TupleTableSlot *slot; - ExprContext *econtext; - - /* - * We will need to use FormIndexDatum to evaluate the index - * expressions. To do that, we need an EState, as well as a - * TupleTableSlot to put the table tuples into. The econtext's - * scantuple has to point to that slot, too. - */ - state->estate = CreateExecutorState(); -#if PG_VERSION_NUM >= 120000 - slot = MakeSingleTupleTableSlot(tupDesc, &TTSOpsVirtual); -#else - slot = MakeSingleTupleTableSlot(tupDesc); -#endif - econtext = GetPerTupleExprContext(state->estate); - econtext->ecxt_scantuple = slot; - } - - MemoryContextSwitchTo(oldcontext); - - return state; -} - -RumTuplesortstate * -rum_tuplesort_begin_index_btree(Relation heapRel, - Relation indexRel, - bool enforceUnique, - int workMem, bool randomAccess) -{ - RumTuplesortstate *state = rum_tuplesort_begin_common(workMem, randomAccess); - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(state->sortcontext); - -#ifdef TRACE_SORT - if (trace_sort) - elog(LOG, - "begin index sort: unique = %c, workMem = %d, randomAccess = %c", - enforceUnique ? 't' : 'f', - workMem, randomAccess ? 't' : 'f'); -#endif - - state->nKeys = RelationGetNumberOfAttributes(indexRel); - - RUM_SORT_START(INDEX_SORT, - enforceUnique, - state->nKeys, - workMem, - randomAccess); - - state->comparetup = comparetup_index_btree; - state->copytup = copytup_index; - state->writetup = writetup_index; - state->readtup = readtup_index; - state->reversedirection = reversedirection_index_btree; - - state->heapRel = heapRel; - state->indexRel = indexRel; - state->indexScanKey = _bt_mkscankey_nodata(indexRel); - state->enforceUnique = enforceUnique; - - MemoryContextSwitchTo(oldcontext); - - return state; -} - -RumTuplesortstate * -rum_tuplesort_begin_index_hash(Relation heapRel, - Relation indexRel, - uint32 hash_mask, - int workMem, bool randomAccess) -{ - RumTuplesortstate *state = rum_tuplesort_begin_common(workMem, randomAccess); - MemoryContext oldcontext; - - oldcontext = MemoryContextSwitchTo(state->sortcontext); - -#ifdef TRACE_SORT - if (trace_sort) - elog(LOG, - "begin index sort: hash_mask = 0x%x, workMem = %d, randomAccess = %c", - hash_mask, - workMem, randomAccess ? 't' : 'f'); -#endif - - state->nKeys = 1; /* Only one sort column, the hash code */ - - state->comparetup = comparetup_index_hash; - state->copytup = copytup_index; - state->writetup = writetup_index; - state->readtup = readtup_index; - state->reversedirection = reversedirection_index_hash; - - state->heapRel = heapRel; - state->indexRel = indexRel; - - state->hash_mask = hash_mask; - - MemoryContextSwitchTo(oldcontext); - - return state; -} - RumTuplesortstate * rum_tuplesort_begin_rum(int workMem, int nKeys, bool randomAccess, bool compareItemPointer) @@ -1179,12 +736,6 @@ rum_tuplesort_begin_rum(int workMem, int nKeys, bool randomAccess, state->nKeys = nKeys; - RUM_SORT_START(INDEX_SORT, - false, /* no unique check */ - state->nKeys, - workMem, - randomAccess); - state->comparetup = comparetup_rum; state->copytup = copytup_rum; state->writetup = writetup_rum; @@ -1212,12 +763,6 @@ rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp) "begin rumitem sort: workMem = %d", workMem); #endif - RUM_SORT_START(INDEX_SORT, - false, /* no unique check */ - 2, - workMem, - false); - state->cmp = cmp; state->comparetup = comparetup_rumitem; state->copytup = copytup_rumitem; @@ -1232,94 +777,6 @@ rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp) return state; } -RumTuplesortstate * -rum_tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, - bool nullsFirstFlag, - int workMem, bool randomAccess) -{ - RumTuplesortstate *state = rum_tuplesort_begin_common(workMem, randomAccess); - MemoryContext oldcontext; - int16 typlen; - bool typbyval; - - oldcontext = MemoryContextSwitchTo(state->sortcontext); - -#ifdef TRACE_SORT - if (trace_sort) - elog(LOG, - "begin datum sort: workMem = %d, randomAccess = %c", - workMem, randomAccess ? 't' : 'f'); -#endif - - state->nKeys = 1; /* always a one-column sort */ - - RUM_SORT_START(DATUM_SORT, - false, /* no unique check */ - 1, - workMem, - randomAccess); - - state->comparetup = comparetup_datum; - state->copytup = copytup_datum; - state->writetup = writetup_datum; - state->readtup = readtup_datum; - state->reversedirection = reversedirection_datum; - - state->datumType = datumType; - - /* Prepare SortSupport data */ - state->onlyKey = (SortSupport) palloc0(sizeof(SortSupportData)); - - state->onlyKey->ssup_cxt = CurrentMemoryContext; - state->onlyKey->ssup_collation = sortCollation; - state->onlyKey->ssup_nulls_first = nullsFirstFlag; - - PrepareSortSupportFromOrderingOp(sortOperator, state->onlyKey); - - /* lookup necessary attributes of the datum type */ - get_typlenbyval(datumType, &typlen, &typbyval); - state->datumTypeLen = typlen; - state->datumTypeByVal = typbyval; - - MemoryContextSwitchTo(oldcontext); - - return state; -} - -/* - * rum_tuplesort_set_bound - * - * Advise tuplesort that at most the first N result tuples are required. - * - * Must be called before inserting any tuples. (Actually, we could allow it - * as long as the sort hasn't spilled to disk, but there seems no need for - * delayed calls at the moment.) - * - * This is a hint only. The tuplesort may still return more tuples than - * requested. - */ -void -rum_tuplesort_set_bound(RumTuplesortstate *state, int64 bound) -{ - /* Assert we're called before loading any tuples */ - Assert(state->status == TSS_INITIAL); - Assert(state->memtupcount == 0); - Assert(!state->bounded); - -#ifdef DEBUG_BOUNDED_SORT - /* Honor GUC setting that disables the feature (for easy testing) */ - if (!optimize_bounded_sort) - return; -#endif - - /* We want to be able to compute bound * 2, so limit the setting */ - if (bound > (int64) (INT_MAX / 2)) - return; - - state->bounded = true; - state->bound = (int) bound; -} - /* * rum_tuplesort_end * @@ -1363,15 +820,6 @@ rum_tuplesort_end(RumTuplesortstate *state) elog(LOG, "internal sort ended, %ld KB used: %s", spaceUsed, pg_rusage_show(&state->ru_start)); } - - TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, spaceUsed); -#else - - /* - * If you disabled TRACE_SORT, you can still probe sort__done, but you - * ain't getting space-used stats. - */ - TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, 0L); #endif /* Free any execution state created for CLUSTER case */ @@ -1512,35 +960,8 @@ grow_memtuples(RumTuplesortstate *state) return false; } -/* - * Accept one tuple while collecting input data for sort. - * - * Note that the input data is always copied; the caller need not save it. - */ -void -rum_tuplesort_puttupleslot(RumTuplesortstate *state, TupleTableSlot *slot) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - /* - * Copy the given tuple into memory we control, and decrease availMem. - * Then call the common code. - */ - COPYTUP(state, &stup, (void *) slot); - - puttuple_common(state, &stup); - - MemoryContextSwitchTo(oldcontext); -} - -/* - * Accept one tuple while collecting input data for sort. - * - * Note that the input data is always copied; the caller need not save it. - */ void -rum_tuplesort_putheaptuple(RumTuplesortstate *state, HeapTuple tup) +rum_tuplesort_putrum(RumTuplesortstate *state, RumSortItem * item) { MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); SortTuple stup; @@ -1549,20 +970,15 @@ rum_tuplesort_putheaptuple(RumTuplesortstate *state, HeapTuple tup) * Copy the given tuple into memory we control, and decrease availMem. * Then call the common code. */ - COPYTUP(state, &stup, (void *) tup); + COPYTUP(state, &stup, (void *) item); puttuple_common(state, &stup); MemoryContextSwitchTo(oldcontext); } -/* - * Accept one index tuple while collecting input data for sort. - * - * Note that the input tuple is always copied; the caller need not save it. - */ void -rum_tuplesort_putindextuple(RumTuplesortstate *state, IndexTuple tuple) +rum_tuplesort_putrumitem(RumTuplesortstate *state, RumScanItem * item) { MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); SortTuple stup; @@ -1571,7 +987,7 @@ rum_tuplesort_putindextuple(RumTuplesortstate *state, IndexTuple tuple) * Copy the given tuple into memory we control, and decrease availMem. * Then call the common code. */ - COPYTUP(state, &stup, (void *) tuple); + COPYTUP(state, &stup, (void *) item); puttuple_common(state, &stup); @@ -1579,82 +995,14 @@ rum_tuplesort_putindextuple(RumTuplesortstate *state, IndexTuple tuple) } /* - * Accept one Datum while collecting input data for sort. - * - * If the Datum is pass-by-ref type, the value will be copied. + * Shared code for tuple and datum cases. */ -void -rum_tuplesort_putdatum(RumTuplesortstate *state, Datum val, bool isNull) +static void +puttuple_common(RumTuplesortstate *state, SortTuple *tuple) { - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - /* - * If it's a pass-by-reference value, copy it into memory we control, and - * decrease availMem. Then call the common code. - */ - if (isNull || state->datumTypeByVal) - { - stup.datum1 = val; - stup.isnull1 = isNull; - stup.tuple = NULL; /* no separate storage */ - } - else + switch (state->status) { - stup.datum1 = datumCopy(val, false, state->datumTypeLen); - stup.isnull1 = false; - stup.tuple = DatumGetPointer(stup.datum1); - USEMEM(state, GetMemoryChunkSpace(stup.tuple)); - } - - puttuple_common(state, &stup); - - MemoryContextSwitchTo(oldcontext); -} - -void -rum_tuplesort_putrum(RumTuplesortstate *state, RumSortItem * item) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - /* - * Copy the given tuple into memory we control, and decrease availMem. - * Then call the common code. - */ - COPYTUP(state, &stup, (void *) item); - - puttuple_common(state, &stup); - - MemoryContextSwitchTo(oldcontext); -} - -void -rum_tuplesort_putrumitem(RumTuplesortstate *state, RumScanItem * item) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - /* - * Copy the given tuple into memory we control, and decrease availMem. - * Then call the common code. - */ - COPYTUP(state, &stup, (void *) item); - - puttuple_common(state, &stup); - - MemoryContextSwitchTo(oldcontext); -} - -/* - * Shared code for tuple and datum cases. - */ -static void -puttuple_common(RumTuplesortstate *state, SortTuple *tuple) -{ - switch (state->status) - { - case TSS_INITIAL: + case TSS_INITIAL: /* * Save the tuple into the unsorted array. First, grow the array @@ -2065,115 +1413,6 @@ rum_tuplesort_gettuple_common(RumTuplesortstate *state, bool forward, } } -/* - * Fetch the next tuple in either forward or back direction. - * If successful, put tuple in slot and return true; else, clear the slot - * and return false. - */ -bool -rum_tuplesort_gettupleslot(RumTuplesortstate *state, bool forward, - TupleTableSlot *slot) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - bool should_free; - - if (!rum_tuplesort_gettuple_common(state, forward, &stup, &should_free)) - stup.tuple = NULL; - - MemoryContextSwitchTo(oldcontext); - - if (stup.tuple) - { - ExecStoreMinimalTuple((MinimalTuple) stup.tuple, slot, should_free); - return true; - } - else - { - ExecClearTuple(slot); - return false; - } -} - -/* - * Fetch the next tuple in either forward or back direction. - * Returns NULL if no more tuples. If *should_free is set, the - * caller must pfree the returned tuple when done with it. - */ -HeapTuple -rum_tuplesort_getheaptuple(RumTuplesortstate *state, bool forward, bool *should_free) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - if (!rum_tuplesort_gettuple_common(state, forward, &stup, should_free)) - stup.tuple = NULL; - - MemoryContextSwitchTo(oldcontext); - - return stup.tuple; -} - -/* - * Fetch the next index tuple in either forward or back direction. - * Returns NULL if no more tuples. If *should_free is set, the - * caller must pfree the returned tuple when done with it. - */ -IndexTuple -rum_tuplesort_getindextuple(RumTuplesortstate *state, bool forward, - bool *should_free) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - - if (!rum_tuplesort_gettuple_common(state, forward, &stup, should_free)) - stup.tuple = NULL; - - MemoryContextSwitchTo(oldcontext); - - return (IndexTuple) stup.tuple; -} - -/* - * Fetch the next Datum in either forward or back direction. - * Returns false if no more datums. - * - * If the Datum is pass-by-ref type, the returned value is freshly palloc'd - * and is now owned by the caller. - */ -bool -rum_tuplesort_getdatum(RumTuplesortstate *state, bool forward, - Datum *val, bool *isNull) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - SortTuple stup; - bool should_free; - - if (!rum_tuplesort_gettuple_common(state, forward, &stup, &should_free)) - { - MemoryContextSwitchTo(oldcontext); - return false; - } - - if (stup.isnull1 || state->datumTypeByVal) - { - *val = stup.datum1; - *isNull = stup.isnull1; - } - else - { - if (should_free) - *val = stup.datum1; - else - *val = datumCopy(stup.datum1, false, state->datumTypeLen); - *isNull = false; - } - - MemoryContextSwitchTo(oldcontext); - - return true; -} - RumSortItem * rum_tuplesort_getrum(RumTuplesortstate *state, bool forward, bool *should_free) { @@ -2426,7 +1665,6 @@ mergeruns(RumTuplesortstate *state) else { numInputTapes = state->tapeRange; - numTapes = state->maxTapes; } state->read_buffer_size = Max(state->availMem / numInputTapes, 0); @@ -2847,165 +2085,6 @@ dumptuples(RumTuplesortstate *state, bool alltuples) } } -/* - * rum_tuplesort_rescan - rewind and replay the scan - */ -void -rum_tuplesort_rescan(RumTuplesortstate *state) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - - Assert(state->randomAccess); - - switch (state->status) - { - case TSS_SORTEDINMEM: - state->current = 0; - state->eof_reached = false; - state->markpos_offset = 0; - state->markpos_eof = false; - break; - case TSS_SORTEDONTAPE: - LogicalTapeRewindForRead(state->tapeset, - state->result_tape, - state->read_buffer_size); - state->eof_reached = false; - state->markpos_block = 0L; - state->markpos_offset = 0; - state->markpos_eof = false; - break; - default: - elog(ERROR, "invalid tuplesort state"); - break; - } - - MemoryContextSwitchTo(oldcontext); -} - -/* - * rum_tuplesort_markpos - saves current position in the merged sort file - */ -void -rum_tuplesort_markpos(RumTuplesortstate *state) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - - Assert(state->randomAccess); - - switch (state->status) - { - case TSS_SORTEDINMEM: - state->markpos_offset = state->current; - state->markpos_eof = state->eof_reached; - break; - case TSS_SORTEDONTAPE: - LogicalTapeTell(state->tapeset, - state->result_tape, - &state->markpos_block, - &state->markpos_offset); - state->markpos_eof = state->eof_reached; - break; - default: - elog(ERROR, "invalid tuplesort state"); - break; - } - - MemoryContextSwitchTo(oldcontext); -} - -/* - * rum_tuplesort_restorepos - restores current position in merged sort file to - * last saved position - */ -void -rum_tuplesort_restorepos(RumTuplesortstate *state) -{ - MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext); - - Assert(state->randomAccess); - - switch (state->status) - { - case TSS_SORTEDINMEM: - state->current = state->markpos_offset; - state->eof_reached = state->markpos_eof; - break; - case TSS_SORTEDONTAPE: -#if PG_VERSION_NUM < 100000 - if (!LogicalTapeSeek(state->tapeset, - state->result_tape, - state->markpos_block, - state->markpos_offset)) - elog(ERROR, "rum_tuplesort_restorepos failed"); -#else - LogicalTapeSeek(state->tapeset, - state->result_tape, - state->markpos_block, - state->markpos_offset); -#endif - state->eof_reached = state->markpos_eof; - break; - default: - elog(ERROR, "invalid tuplesort state"); - break; - } - - MemoryContextSwitchTo(oldcontext); -} - -/* - * rum_tuplesort_get_stats - extract summary statistics - * - * This can be called after rum_tuplesort_performsort() finishes to obtain - * printable summary information about how the sort was performed. - * spaceUsed is measured in kilobytes. - */ -void -rum_tuplesort_get_stats(RumTuplesortstate *state, - const char **sortMethod, - const char **spaceType, - long *spaceUsed) -{ - /* - * Note: it might seem we should provide both memory and disk usage for a - * disk-based sort. However, the current code doesn't track memory space - * accurately once we have begun to return tuples to the caller (since we - * don't account for pfree's the caller is expected to do), so we cannot - * rely on availMem in a disk sort. This does not seem worth the overhead - * to fix. Is it worth creating an API for the memory context code to - * tell us how much is actually used in sortcontext? - */ - if (state->tapeset) - { - *spaceType = "Disk"; - *spaceUsed = LogicalTapeSetBlocks(state->tapeset) * (BLCKSZ / 1024); - } - else - { - *spaceType = "Memory"; - *spaceUsed = (state->allowedMem - state->availMem + 1023) / 1024; - } - - switch (state->status) - { - case TSS_SORTEDINMEM: - if (state->boundUsed) - *sortMethod = "top-N heapsort"; - else - *sortMethod = "quicksort"; - break; - case TSS_SORTEDONTAPE: - *sortMethod = "external sort"; - break; - case TSS_FINALMERGE: - *sortMethod = "external merge"; - break; - default: - *sortMethod = "still in progress"; - break; - } -} - /* * Heap manipulation routines, per Knuth's Algorithm 5.2.3H. @@ -3224,775 +2303,6 @@ markrunend(RumTuplesortstate *state, int tapenum) } -/* - * Inline-able copy of FunctionCall2Coll() to save some cycles in sorting. - */ -static inline Datum -myFunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) -{ - FunctionCallInfoData fcinfo; - Datum result; - - InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - - result = FunctionCallInvoke(&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); - - return result; -} - -/* - * Apply a sort function (by now converted to fmgr lookup form) - * and return a 3-way comparison result. This takes care of handling - * reverse-sort and NULLs-ordering properly. We assume that DESC and - * NULLS_FIRST options are encoded in sk_flags the same way btree does it. - */ -static inline int32 -inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, Oid collation, - Datum datum1, bool isNull1, - Datum datum2, bool isNull2) -{ - int32 compare; - - if (isNull1) - { - if (isNull2) - compare = 0; /* NULL "=" NULL */ - else if (sk_flags & SK_BT_NULLS_FIRST) - compare = -1; /* NULL "<" NOT_NULL */ - else - compare = 1; /* NULL ">" NOT_NULL */ - } - else if (isNull2) - { - if (sk_flags & SK_BT_NULLS_FIRST) - compare = 1; /* NOT_NULL ">" NULL */ - else - compare = -1; /* NOT_NULL "<" NULL */ - } - else - { - compare = DatumGetInt32(myFunctionCall2Coll(sortFunction, collation, - datum1, datum2)); - - if (sk_flags & SK_BT_DESC) - compare = -compare; - } - - return compare; -} - - -/* - * Routines specialized for HeapTuple (actually MinimalTuple) case - */ - -static int -comparetup_heap(const SortTuple *a, const SortTuple *b, RumTuplesortstate *state) -{ - SortSupport sortKey = state->sortKeys; - HeapTupleData ltup; - HeapTupleData rtup; - TupleDesc tupDesc; - int nkey; - int32 compare; - - /* Compare the leading sort key */ - compare = ApplySortComparator(a->datum1, a->isnull1, - b->datum1, b->isnull1, - sortKey); - if (compare != 0) - return compare; - - /* Compare additional sort keys */ - ltup.t_len = ((MinimalTuple) a->tuple)->t_len + MINIMAL_TUPLE_OFFSET; - ltup.t_data = (HeapTupleHeader) ((char *) a->tuple - MINIMAL_TUPLE_OFFSET); - rtup.t_len = ((MinimalTuple) b->tuple)->t_len + MINIMAL_TUPLE_OFFSET; - rtup.t_data = (HeapTupleHeader) ((char *) b->tuple - MINIMAL_TUPLE_OFFSET); - tupDesc = state->tupDesc; - sortKey++; - for (nkey = 1; nkey < state->nKeys; nkey++, sortKey++) - { - AttrNumber attno = sortKey->ssup_attno; - Datum datum1, - datum2; - bool isnull1, - isnull2; - - datum1 = heap_getattr(<up, attno, tupDesc, &isnull1); - datum2 = heap_getattr(&rtup, attno, tupDesc, &isnull2); - - compare = ApplySortComparator(datum1, isnull1, - datum2, isnull2, - sortKey); - if (compare != 0) - return compare; - } - - return 0; -} - -static void -copytup_heap(RumTuplesortstate *state, SortTuple *stup, void *tup) -{ - /* - * We expect the passed "tup" to be a TupleTableSlot, and form a - * MinimalTuple using the exported interface for that. - */ - TupleTableSlot *slot = (TupleTableSlot *) tup; - MinimalTuple tuple; - HeapTupleData htup; - - /* copy the tuple into sort storage */ - tuple = ExecCopySlotMinimalTuple(slot); - stup->tuple = (void *) tuple; - USEMEM(state, GetMemoryChunkSpace(tuple)); - /* set up first-column key value */ - htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET; - htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET); - stup->datum1 = heap_getattr(&htup, - state->sortKeys[0].ssup_attno, - state->tupDesc, - &stup->isnull1); -} - -static void -writetup_heap(RumTuplesortstate *state, int tapenum, SortTuple *stup) -{ - MinimalTuple tuple = (MinimalTuple) stup->tuple; - - /* the part of the MinimalTuple we'll write: */ - char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; - unsigned int tupbodylen = tuple->t_len - MINIMAL_TUPLE_DATA_OFFSET; - - /* total on-disk footprint: */ - unsigned int tuplen = tupbodylen + sizeof(int); - - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &tuplen, sizeof(tuplen)); - LogicalTapeWrite(state->tapeset, tapenum, - (void *) tupbody, tupbodylen); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &tuplen, sizeof(tuplen)); - - FREEMEM(state, GetMemoryChunkSpace(tuple)); - heap_free_minimal_tuple(tuple); -} - -static void -readtup_heap(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len) -{ - unsigned int tupbodylen = len - sizeof(int); - unsigned int tuplen = tupbodylen + MINIMAL_TUPLE_DATA_OFFSET; - MinimalTuple tuple = (MinimalTuple) palloc(tuplen); - char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET; - HeapTupleData htup; - - USEMEM(state, GetMemoryChunkSpace(tuple)); - /* read in the tuple proper */ - tuple->t_len = tuplen; - LogicalTapeReadExact(state->tapeset, tapenum, - tupbody, tupbodylen); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeReadExact(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; - /* set up first-column key value */ - htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET; - htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET); - stup->datum1 = heap_getattr(&htup, - state->sortKeys[0].ssup_attno, - state->tupDesc, - &stup->isnull1); -} - -static void -reversedirection_heap(RumTuplesortstate *state) -{ - SortSupport sortKey = state->sortKeys; - int nkey; - - for (nkey = 0; nkey < state->nKeys; nkey++, sortKey++) - { - sortKey->ssup_reverse = !sortKey->ssup_reverse; - sortKey->ssup_nulls_first = !sortKey->ssup_nulls_first; - } -} - - -/* - * Routines specialized for the CLUSTER case (HeapTuple data, with - * comparisons per a btree index definition) - */ - -static int -comparetup_cluster(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state) -{ - ScanKey scanKey = state->indexScanKey; - HeapTuple ltup; - HeapTuple rtup; - TupleDesc tupDesc; - int nkey; - int32 compare; - - /* Compare the leading sort key, if it's simple */ -#if PG_VERSION_NUM >= 110000 - if (state->indexInfo->ii_IndexAttrNumbers[0] != 0) -#else - if (state->indexInfo->ii_KeyAttrNumbers[0] != 0) -#endif - { - compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, - scanKey->sk_collation, - a->datum1, a->isnull1, - b->datum1, b->isnull1); - if (compare != 0 || state->nKeys == 1) - return compare; - /* Compare additional columns the hard way */ - scanKey++; - nkey = 1; - } - else - { - /* Must compare all keys the hard way */ - nkey = 0; - } - - /* Compare additional sort keys */ - ltup = (HeapTuple) a->tuple; - rtup = (HeapTuple) b->tuple; - - if (state->indexInfo->ii_Expressions == NULL) - { - /* If not expression index, just compare the proper heap attrs */ - tupDesc = state->tupDesc; - - for (; nkey < state->nKeys; nkey++, scanKey++) - { -#if PG_VERSION_NUM >= 110000 - AttrNumber attno = state->indexInfo->ii_IndexAttrNumbers[nkey]; -#else - AttrNumber attno = state->indexInfo->ii_KeyAttrNumbers[nkey]; -#endif - Datum datum1, - datum2; - bool isnull1, - isnull2; - - datum1 = heap_getattr(ltup, attno, tupDesc, &isnull1); - datum2 = heap_getattr(rtup, attno, tupDesc, &isnull2); - - compare = inlineApplySortFunction(&scanKey->sk_func, - scanKey->sk_flags, - scanKey->sk_collation, - datum1, isnull1, - datum2, isnull2); - if (compare != 0) - return compare; - } - } - else - { - /* - * In the expression index case, compute the whole index tuple and - * then compare values. It would perhaps be faster to compute only as - * many columns as we need to compare, but that would require - * duplicating all the logic in FormIndexDatum. - */ - Datum l_index_values[INDEX_MAX_KEYS]; - bool l_index_isnull[INDEX_MAX_KEYS]; - Datum r_index_values[INDEX_MAX_KEYS]; - bool r_index_isnull[INDEX_MAX_KEYS]; - TupleTableSlot *ecxt_scantuple; - - /* Reset context each time to prevent memory leakage */ - ResetPerTupleExprContext(state->estate); - - ecxt_scantuple = GetPerTupleExprContext(state->estate)->ecxt_scantuple; - -#if PG_VERSION_NUM >= 120000 - ExecStoreHeapTuple(ltup, ecxt_scantuple, false); -#else - ExecStoreTuple(ltup, ecxt_scantuple, InvalidBuffer, false); -#endif - FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate, - l_index_values, l_index_isnull); - -#if PG_VERSION_NUM >= 120000 - ExecStoreHeapTuple(rtup, ecxt_scantuple, false); -#else - ExecStoreTuple(rtup, ecxt_scantuple, InvalidBuffer, false); -#endif - FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate, - r_index_values, r_index_isnull); - - for (; nkey < state->nKeys; nkey++, scanKey++) - { - compare = inlineApplySortFunction(&scanKey->sk_func, - scanKey->sk_flags, - scanKey->sk_collation, - l_index_values[nkey], - l_index_isnull[nkey], - r_index_values[nkey], - r_index_isnull[nkey]); - if (compare != 0) - return compare; - } - } - - return 0; -} - -static void -copytup_cluster(RumTuplesortstate *state, SortTuple *stup, void *tup) -{ - HeapTuple tuple = (HeapTuple) tup; -#if PG_VERSION_NUM >= 110000 - AttrNumber attno = state->indexInfo->ii_IndexAttrNumbers[0]; -#else - AttrNumber attno = state->indexInfo->ii_KeyAttrNumbers[0]; -#endif - - /* copy the tuple into sort storage */ - tuple = heap_copytuple(tuple); - stup->tuple = (void *) tuple; - USEMEM(state, GetMemoryChunkSpace(tuple)); - /* set up first-column key value, if it's a simple column */ - if (attno != 0) - stup->datum1 = heap_getattr(tuple, - attno, - state->tupDesc, - &stup->isnull1); -} - -static void -writetup_cluster(RumTuplesortstate *state, int tapenum, SortTuple *stup) -{ - HeapTuple tuple = (HeapTuple) stup->tuple; - unsigned int tuplen = tuple->t_len + sizeof(ItemPointerData) + sizeof(int); - - /* We need to store t_self, but not other fields of HeapTupleData */ - LogicalTapeWrite(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); - LogicalTapeWrite(state->tapeset, tapenum, - &tuple->t_self, sizeof(ItemPointerData)); - LogicalTapeWrite(state->tapeset, tapenum, - tuple->t_data, tuple->t_len); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeWrite(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); - - FREEMEM(state, GetMemoryChunkSpace(tuple)); - heap_freetuple(tuple); -} - -static void -readtup_cluster(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int tuplen) -{ - unsigned int t_len = tuplen - sizeof(ItemPointerData) - sizeof(int); - HeapTuple tuple = (HeapTuple) palloc(t_len + HEAPTUPLESIZE); -#if PG_VERSION_NUM >= 110000 - AttrNumber attno = state->indexInfo->ii_IndexAttrNumbers[0]; -#else - AttrNumber attno = state->indexInfo->ii_KeyAttrNumbers[0]; -#endif - - USEMEM(state, GetMemoryChunkSpace(tuple)); - /* Reconstruct the HeapTupleData header */ - tuple->t_data = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE); - tuple->t_len = t_len; - LogicalTapeReadExact(state->tapeset, tapenum, - &tuple->t_self, sizeof(ItemPointerData)); - /* We don't currently bother to reconstruct t_tableOid */ - tuple->t_tableOid = InvalidOid; - /* Read in the tuple body */ - LogicalTapeReadExact(state->tapeset, tapenum, - tuple->t_data, tuple->t_len); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeReadExact(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; - /* set up first-column key value, if it's a simple column */ - if (attno != 0) - stup->datum1 = heap_getattr(tuple, - attno, - state->tupDesc, - &stup->isnull1); -} - - -/* - * Routines specialized for IndexTuple case - * - * The btree and hash cases require separate comparison functions, but the - * IndexTuple representation is the same so the copy/write/read support - * functions can be shared. - */ - -static int -comparetup_index_btree(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state) -{ - /* - * This is similar to _bt_tuplecompare(), but we have already done the - * index_getattr calls for the first column, and we need to keep track of - * whether any null fields are present. Also see the special treatment - * for equal keys at the end. - */ - ScanKey scanKey = state->indexScanKey; - IndexTuple tuple1; - IndexTuple tuple2; - int keysz; - TupleDesc tupDes; - bool equal_hasnull = false; - int nkey; - int32 compare; - - /* Compare the leading sort key */ - compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, - scanKey->sk_collation, - a->datum1, a->isnull1, - b->datum1, b->isnull1); - if (compare != 0) - return compare; - - /* they are equal, so we only need to examine one null flag */ - if (a->isnull1) - equal_hasnull = true; - - /* Compare additional sort keys */ - tuple1 = (IndexTuple) a->tuple; - tuple2 = (IndexTuple) b->tuple; - keysz = state->nKeys; - tupDes = RelationGetDescr(state->indexRel); - scanKey++; - for (nkey = 2; nkey <= keysz; nkey++, scanKey++) - { - Datum datum1, - datum2; - bool isnull1, - isnull2; - - datum1 = index_getattr(tuple1, nkey, tupDes, &isnull1); - datum2 = index_getattr(tuple2, nkey, tupDes, &isnull2); - - compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, - scanKey->sk_collation, - datum1, isnull1, - datum2, isnull2); - if (compare != 0) - return compare; /* done when we find unequal attributes */ - - /* they are equal, so we only need to examine one null flag */ - if (isnull1) - equal_hasnull = true; - } - - /* - * If btree has asked us to enforce uniqueness, complain if two equal - * tuples are detected (unless there was at least one NULL field). - * - * It is sufficient to make the test here, because if two tuples are equal - * they *must* get compared at some stage of the sort --- otherwise the - * sort algorithm wouldn't have checked whether one must appear before the - * other. - */ - if (state->enforceUnique && !equal_hasnull) - { - Datum values[INDEX_MAX_KEYS]; - bool isnull[INDEX_MAX_KEYS]; - char *key_desc; - - /* - * Some rather brain-dead implementations of qsort (such as the one in - * QNX 4) will sometimes call the comparison routine to compare a - * value to itself, but we always use our own implementation, which - * does not. - */ - Assert(tuple1 != tuple2); - - index_deform_tuple(tuple1, tupDes, values, isnull); - - key_desc = BuildIndexValueDescription(state->indexRel, values, isnull); - - ereport(ERROR, - (errcode(ERRCODE_UNIQUE_VIOLATION), - errmsg("could not create unique index \"%s\"", - RelationGetRelationName(state->indexRel)), - key_desc ? errdetail("Key %s is duplicated.", key_desc) : - errdetail("Duplicate keys exist."), - errtableconstraint(state->heapRel, - RelationGetRelationName(state->indexRel)))); - } - - /* - * If key values are equal, we sort on ItemPointer. This does not affect - * validity of the finished index, but it may be useful to have index - * scans in physical order. - */ - { - BlockNumber blk1 = ItemPointerGetBlockNumber(&tuple1->t_tid); - BlockNumber blk2 = ItemPointerGetBlockNumber(&tuple2->t_tid); - - if (blk1 != blk2) - return (blk1 < blk2) ? -1 : 1; - } - { - OffsetNumber pos1 = ItemPointerGetOffsetNumber(&tuple1->t_tid); - OffsetNumber pos2 = ItemPointerGetOffsetNumber(&tuple2->t_tid); - - if (pos1 != pos2) - return (pos1 < pos2) ? -1 : 1; - } - - return 0; -} - -static int -comparetup_index_hash(const SortTuple *a, const SortTuple *b, - RumTuplesortstate *state) -{ - uint32 hash1; - uint32 hash2; - IndexTuple tuple1; - IndexTuple tuple2; - - /* - * Fetch hash keys and mask off bits we don't want to sort by. We know - * that the first column of the index tuple is the hash key. - */ - Assert(!a->isnull1); - hash1 = DatumGetUInt32(a->datum1) & state->hash_mask; - Assert(!b->isnull1); - hash2 = DatumGetUInt32(b->datum1) & state->hash_mask; - - if (hash1 > hash2) - return 1; - else if (hash1 < hash2) - return -1; - - /* - * If hash values are equal, we sort on ItemPointer. This does not affect - * validity of the finished index, but it may be useful to have index - * scans in physical order. - */ - tuple1 = (IndexTuple) a->tuple; - tuple2 = (IndexTuple) b->tuple; - - { - BlockNumber blk1 = ItemPointerGetBlockNumber(&tuple1->t_tid); - BlockNumber blk2 = ItemPointerGetBlockNumber(&tuple2->t_tid); - - if (blk1 != blk2) - return (blk1 < blk2) ? -1 : 1; - } - { - OffsetNumber pos1 = ItemPointerGetOffsetNumber(&tuple1->t_tid); - OffsetNumber pos2 = ItemPointerGetOffsetNumber(&tuple2->t_tid); - - if (pos1 != pos2) - return (pos1 < pos2) ? -1 : 1; - } - - return 0; -} - -static void -copytup_index(RumTuplesortstate *state, SortTuple *stup, void *tup) -{ - IndexTuple tuple = (IndexTuple) tup; - unsigned int tuplen = IndexTupleSize(tuple); - IndexTuple newtuple; - - /* copy the tuple into sort storage */ - newtuple = (IndexTuple) palloc(tuplen); - memcpy(newtuple, tuple, tuplen); - USEMEM(state, GetMemoryChunkSpace(newtuple)); - stup->tuple = (void *) newtuple; - /* set up first-column key value */ - stup->datum1 = index_getattr(newtuple, - 1, - RelationGetDescr(state->indexRel), - &stup->isnull1); -} - -static void -writetup_index(RumTuplesortstate *state, int tapenum, SortTuple *stup) -{ - IndexTuple tuple = (IndexTuple) stup->tuple; - unsigned int tuplen; - - tuplen = IndexTupleSize(tuple) + sizeof(tuplen); - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &tuplen, sizeof(tuplen)); - LogicalTapeWrite(state->tapeset, tapenum, - (void *) tuple, IndexTupleSize(tuple)); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &tuplen, sizeof(tuplen)); - - FREEMEM(state, GetMemoryChunkSpace(tuple)); - pfree(tuple); -} - -static void -readtup_index(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len) -{ - unsigned int tuplen = len - sizeof(unsigned int); - IndexTuple tuple = (IndexTuple) palloc(tuplen); - - USEMEM(state, GetMemoryChunkSpace(tuple)); - LogicalTapeReadExact(state->tapeset, tapenum, - tuple, tuplen); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeReadExact(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; - /* set up first-column key value */ - stup->datum1 = index_getattr(tuple, - 1, - RelationGetDescr(state->indexRel), - &stup->isnull1); -} - -static void -reversedirection_index_btree(RumTuplesortstate *state) -{ - ScanKey scanKey = state->indexScanKey; - int nkey; - - for (nkey = 0; nkey < state->nKeys; nkey++, scanKey++) - { - scanKey->sk_flags ^= (SK_BT_DESC | SK_BT_NULLS_FIRST); - } -} - -static void -reversedirection_index_hash(RumTuplesortstate *state) -{ - /* We don't support reversing direction in a hash index sort */ - elog(ERROR, "reversedirection_index_hash is not implemented"); -} - - -/* - * Routines specialized for DatumTuple case - */ - -static int -comparetup_datum(const SortTuple *a, const SortTuple *b, RumTuplesortstate *state) -{ - return ApplySortComparator(a->datum1, a->isnull1, - b->datum1, b->isnull1, - state->onlyKey); -} - -static void -copytup_datum(RumTuplesortstate *state, SortTuple *stup, void *tup) -{ - /* Not currently needed */ - elog(ERROR, "copytup_datum() should not be called"); -} - -static void -writetup_datum(RumTuplesortstate *state, int tapenum, SortTuple *stup) -{ - void *waddr; - unsigned int tuplen; - unsigned int writtenlen; - - if (stup->isnull1) - { - waddr = NULL; - tuplen = 0; - } - else if (state->datumTypeByVal) - { - waddr = &stup->datum1; - tuplen = sizeof(Datum); - } - else - { - waddr = DatumGetPointer(stup->datum1); - tuplen = datumGetSize(stup->datum1, false, state->datumTypeLen); - Assert(tuplen != 0); - } - - writtenlen = tuplen + sizeof(unsigned int); - - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &writtenlen, sizeof(writtenlen)); - LogicalTapeWrite(state->tapeset, tapenum, - waddr, tuplen); - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeWrite(state->tapeset, tapenum, - (void *) &writtenlen, sizeof(writtenlen)); - - if (stup->tuple) - { - FREEMEM(state, GetMemoryChunkSpace(stup->tuple)); - pfree(stup->tuple); - } -} - -static void -readtup_datum(RumTuplesortstate *state, SortTuple *stup, - int tapenum, unsigned int len) -{ - unsigned int tuplen = len - sizeof(unsigned int); - - if (tuplen == 0) - { - /* it's NULL */ - stup->datum1 = (Datum) 0; - stup->isnull1 = true; - stup->tuple = NULL; - } - else if (state->datumTypeByVal) - { - Assert(tuplen == sizeof(Datum)); - LogicalTapeReadExact(state->tapeset, tapenum, - &stup->datum1, tuplen); - stup->isnull1 = false; - stup->tuple = NULL; - } - else - { - void *raddr = palloc(tuplen); - - LogicalTapeReadExact(state->tapeset, tapenum, - raddr, tuplen); - stup->datum1 = PointerGetDatum(raddr); - stup->isnull1 = false; - stup->tuple = raddr; - USEMEM(state, GetMemoryChunkSpace(raddr)); - } - - if (state->randomAccess) /* need trailing length word? */ - LogicalTapeReadExact(state->tapeset, tapenum, - &tuplen, sizeof(tuplen)); -} - -static void -reversedirection_datum(RumTuplesortstate *state) -{ - state->onlyKey->ssup_reverse = !state->onlyKey->ssup_reverse; - state->onlyKey->ssup_nulls_first = !state->onlyKey->ssup_nulls_first; -} - /* * Convenience routine to free a tuple previously loaded into sort memory */ diff --git a/src/rumsort.h b/src/rumsort.h index 9cb74feeab..452fdfc596 100644 --- a/src/rumsort.h +++ b/src/rumsort.h @@ -3,13 +3,11 @@ * rumsort.h * Generalized tuple sorting routines. * - * This module handles sorting of heap tuples, index tuples, or single - * Datums (and could easily support other kinds of sortable objects, - * if necessary). It works efficiently for both small and large amounts - * of data. Small amounts are sorted in-memory using qsort(). Large - * amounts are sorted using temporary files and a standard external sort - * algorithm. + * This module handles sorting of RumSortItem or RumScanItem structures. + * It contains copy of static functions from + * src/backend/utils/sort/tuplesort.c. * + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -22,43 +20,14 @@ #include "postgres.h" #include "fmgr.h" -#include "access/itup.h" #include "executor/tuptable.h" -#include "utils/relcache.h" -/* Tuplesortstate is an opaque type whose details are not known outside - * tuplesort.c. +/* RumTuplesortstate is an opaque type whose details are not known outside + * rumsort.c. */ typedef struct RumTuplesortstate RumTuplesortstate; struct RumScanItem; -/* - * We provide multiple interfaces to what is essentially the same code, - * since different callers have different data to be sorted and want to - * specify the sort key information differently. There are two APIs for - * sorting HeapTuples and two more for sorting IndexTuples. Yet another - * API supports sorting bare Datums. - * - * The "heap" API actually stores/sorts MinimalTuples, which means it doesn't - * preserve the system columns (tuple identity and transaction visibility - * info). The sort keys are specified by column numbers within the tuples - * and sort operator OIDs. We save some cycles by passing and returning the - * tuples in TupleTableSlots, rather than forming actual HeapTuples (which'd - * have to be converted to MinimalTuples). This API works well for sorts - * executed as parts of plan trees. - * - * The "cluster" API stores/sorts full HeapTuples including all visibility - * info. The sort keys are specified by reference to a btree index that is - * defined on the relation to be sorted. Note that putheaptuple/getheaptuple - * go with this API, not the "begin_heap" one! - * - * The "index_btree" API stores/sorts IndexTuples (preserving all their - * header fields). The sort keys are specified by a btree index definition. - * - * The "index_hash" API is similar to index_btree, but the tuples are - * actually sorted by their hash codes not the raw data. - */ - typedef struct { ItemPointerData iptr; @@ -69,52 +38,17 @@ typedef struct #define RumSortItemSize(nKeys) (offsetof(RumSortItem,data)+(nKeys)*sizeof(float8)) extern MemoryContext rum_tuplesort_get_memorycontext(RumTuplesortstate *state); -extern RumTuplesortstate *rum_tuplesort_begin_heap(TupleDesc tupDesc, - int nkeys, AttrNumber *attNums, - Oid *sortOperators, Oid *sortCollations, - bool *nullsFirstFlags, - int workMem, bool randomAccess); -extern RumTuplesortstate *rum_tuplesort_begin_cluster(TupleDesc tupDesc, - Relation indexRel, - int workMem, bool randomAccess); -extern RumTuplesortstate *rum_tuplesort_begin_index_btree(Relation heapRel, - Relation indexRel, - bool enforceUnique, - int workMem, bool randomAccess); -extern RumTuplesortstate *rum_tuplesort_begin_index_hash(Relation heapRel, - Relation indexRel, - uint32 hash_mask, - int workMem, bool randomAccess); -extern RumTuplesortstate *rum_tuplesort_begin_datum(Oid datumType, - Oid sortOperator, Oid sortCollation, - bool nullsFirstFlag, - int workMem, bool randomAccess); + extern RumTuplesortstate *rum_tuplesort_begin_rum(int workMem, int nKeys, bool randomAccess, bool compareItemPointer); extern RumTuplesortstate *rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp); -extern void rum_tuplesort_set_bound(RumTuplesortstate *state, int64 bound); - -extern void rum_tuplesort_puttupleslot(RumTuplesortstate *state, - TupleTableSlot *slot); -extern void rum_tuplesort_putheaptuple(RumTuplesortstate *state, HeapTuple tup); -extern void rum_tuplesort_putindextuple(RumTuplesortstate *state, IndexTuple tuple); -extern void rum_tuplesort_putdatum(RumTuplesortstate *state, Datum val, - bool isNull); extern void rum_tuplesort_putrum(RumTuplesortstate *state, RumSortItem * item); extern void rum_tuplesort_putrumitem(RumTuplesortstate *state, struct RumScanItem * item); extern void rum_tuplesort_performsort(RumTuplesortstate *state); -extern bool rum_tuplesort_gettupleslot(RumTuplesortstate *state, bool forward, - TupleTableSlot *slot); -extern HeapTuple rum_tuplesort_getheaptuple(RumTuplesortstate *state, bool forward, - bool *should_free); -extern IndexTuple rum_tuplesort_getindextuple(RumTuplesortstate *state, bool forward, - bool *should_free); -extern bool rum_tuplesort_getdatum(RumTuplesortstate *state, bool forward, - Datum *val, bool *isNull); extern RumSortItem *rum_tuplesort_getrum(RumTuplesortstate *state, bool forward, bool *should_free); extern struct RumScanItem *rum_tuplesort_getrumitem(RumTuplesortstate *state, bool forward, @@ -122,21 +56,6 @@ extern struct RumScanItem *rum_tuplesort_getrumitem(RumTuplesortstate *state, bo extern void rum_tuplesort_end(RumTuplesortstate *state); -extern void rum_tuplesort_get_stats(RumTuplesortstate *state, - const char **sortMethod, - const char **spaceType, - long *spaceUsed); - extern int rum_tuplesort_merge_order(long allowedMem); -/* - * These routines may only be called if randomAccess was specified 'true'. - * Likewise, backwards scan in gettuple/getdatum is only allowed if - * randomAccess was specified. - */ - -extern void rum_tuplesort_rescan(RumTuplesortstate *state); -extern void rum_tuplesort_markpos(RumTuplesortstate *state); -extern void rum_tuplesort_restorepos(RumTuplesortstate *state); - #endif /* RUMSORT_H */ diff --git a/src/rumtsquery.c b/src/rumtsquery.c index 205526ff37..747f98f2cf 100644 --- a/src/rumtsquery.c +++ b/src/rumtsquery.c @@ -3,7 +3,7 @@ * rumtsquery.c * Inverted fulltext search: indexing tsqueries. * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * *------------------------------------------------------------------------- diff --git a/src/rumutil.c b/src/rumutil.c index bca37c892a..a24c1614ce 100644 --- a/src/rumutil.c +++ b/src/rumutil.c @@ -4,7 +4,7 @@ * utilities routines for the postgres inverted index access method. * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -83,13 +83,25 @@ _PG_init(void) add_string_reloption(rum_relopt_kind, "attach", "Column name to attach as additional info", - NULL, NULL); + NULL, NULL +#if PG_VERSION_NUM >= 130000 + , AccessExclusiveLock +#endif + ); add_string_reloption(rum_relopt_kind, "to", "Column name to add a order by column", - NULL, NULL); + NULL, NULL +#if PG_VERSION_NUM >= 130000 + , AccessExclusiveLock +#endif + ); add_bool_reloption(rum_relopt_kind, "order_by_attach", "Use (addinfo, itempointer) order instead of just itempointer", - false); + false +#if PG_VERSION_NUM >= 130000 + , AccessExclusiveLock +#endif + ); } /* @@ -875,14 +887,15 @@ rumExtractEntries(RumState * rumstate, OffsetNumber attnum, bytea * rumoptions(Datum reloptions, bool validate) { - relopt_value *options; - RumOptions *rdopts; - int numoptions; static const relopt_parse_elt tab[] = { {"attach", RELOPT_TYPE_STRING, offsetof(RumOptions, attachColumn)}, {"to", RELOPT_TYPE_STRING, offsetof(RumOptions, addToColumn)}, {"order_by_attach", RELOPT_TYPE_BOOL, offsetof(RumOptions, useAlternativeOrder)} }; +#if PG_VERSION_NUM < 130000 + relopt_value *options; + RumOptions *rdopts; + int numoptions; options = parseRelOptions(reloptions, validate, rum_relopt_kind, &numoptions); @@ -899,6 +912,10 @@ rumoptions(Datum reloptions, bool validate) pfree(options); return (bytea *) rdopts; +#else + return (bytea *) build_reloptions(reloptions, validate, rum_relopt_kind, + sizeof(RumOptions), tab, lengthof(tab)); +#endif } bool @@ -1057,8 +1074,40 @@ FunctionCall10Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg6, Datum arg7, Datum arg8, Datum arg9, Datum arg10) { - FunctionCallInfoData fcinfo; Datum result; +#if PG_VERSION_NUM >= 120000 + LOCAL_FCINFO(fcinfo, 10); + + InitFunctionCallInfoData(*fcinfo, flinfo, 10, collation, NULL, NULL); + + fcinfo->args[0].value = arg1; + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = arg2; + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = arg3; + fcinfo->args[2].isnull = false; + fcinfo->args[3].value = arg4; + fcinfo->args[3].isnull = false; + fcinfo->args[4].value = arg5; + fcinfo->args[4].isnull = false; + fcinfo->args[5].value = arg6; + fcinfo->args[5].isnull = false; + fcinfo->args[6].value = arg7; + fcinfo->args[6].isnull = false; + fcinfo->args[7].value = arg8; + fcinfo->args[7].isnull = false; + fcinfo->args[8].value = arg9; + fcinfo->args[8].isnull = false; + fcinfo->args[9].value = arg10; + fcinfo->args[9].isnull = false; + + result = FunctionCallInvoke(fcinfo); + + /* Check for null result, since caller is clearly not expecting one */ + if (fcinfo->isnull) + elog(ERROR, "function %u returned NULL", fcinfo->flinfo->fn_oid); +#else + FunctionCallInfoData fcinfo; InitFunctionCallInfoData(fcinfo, flinfo, 10, collation, NULL, NULL); @@ -1088,6 +1137,7 @@ FunctionCall10Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, /* Check for null result, since caller is clearly not expecting one */ if (fcinfo.isnull) elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid); +#endif return result; } diff --git a/src/rumvacuum.c b/src/rumvacuum.c index 32662c65f6..35cca00308 100644 --- a/src/rumvacuum.c +++ b/src/rumvacuum.c @@ -4,7 +4,7 @@ * delete & vacuum routines for the postgres RUM * * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * @@ -53,6 +53,7 @@ rumVacuumPostingList(RumVacuumState * gvs, OffsetNumber attnum, Pointer src, prev, ptr = src; + *newSize = 0; ItemPointerSetMin(&item.iptr); /* @@ -63,7 +64,7 @@ rumVacuumPostingList(RumVacuumState * gvs, OffsetNumber attnum, Pointer src, for (i = 0; i < nitem; i++) { prev = ptr; - ptr = rumDataPageLeafRead(ptr, attnum, &item, &gvs->rumstate); + ptr = rumDataPageLeafRead(ptr, attnum, &item, false, &gvs->rumstate); if (gvs->callback(&item.iptr, gvs->callback_state)) { gvs->result->tuples_removed += 1; diff --git a/src/rumvalidate.c b/src/rumvalidate.c index 39c2f5c1e1..1d73e1b73b 100644 --- a/src/rumvalidate.c +++ b/src/rumvalidate.c @@ -3,7 +3,7 @@ * rumvalidate.c * Opclass validator for RUM. * - * Portions Copyright (c) 2015-2016, Postgres Professional + * Portions Copyright (c) 2015-2019, Postgres Professional * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * diff --git a/t/001_wal.pl b/t/001_wal.pl index 6cd507da86..99415afb63 100644 --- a/t/001_wal.pl +++ b/t/001_wal.pl @@ -71,7 +71,7 @@ sub test_index_replay to_tsvector('simple', array_to_string(array( select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', trunc(random() * 52)::integer + 1, 1) FROM generate_series(i, i + 4)), '')) - FROM generate_series(1,100000) i;"); + FROM generate_series(1,16000) i;"); $node_master->psql("postgres", "CREATE INDEX rumidx ON tst USING rum (t rum_tsvector_ops);"); # Test that queries give same result diff --git a/tests/README.md b/tests/README.md index de04c4d617..77b7d78e88 100644 --- a/tests/README.md +++ b/tests/README.md @@ -3,7 +3,7 @@ Install testgres: ``` -pip install testgres +pip install testgres==0.4.0 ``` Run command: diff --git a/travis/Dockerfile.in b/travis/Dockerfile.in new file mode 100644 index 0000000000..6c839839f0 --- /dev/null +++ b/travis/Dockerfile.in @@ -0,0 +1,32 @@ +FROM postgres:${PG_VERSION}-alpine + +# Install dependencies +RUN apk add --no-cache \ + openssl curl \ + perl perl-ipc-run \ + make musl-dev gcc bison flex coreutils \ + zlib-dev libedit-dev \ + clang clang-analyzer; + +# Environment +ENV LANG=C.UTF-8 PGDATA=/pg/data + +# Make directories +RUN mkdir -p ${PGDATA} && \ + mkdir -p /pg/testdir + +COPY run_tests.sh /run.sh +RUN chmod 755 /run.sh + +COPY . /pg/testdir +WORKDIR /pg/testdir + +# Grant privileges +RUN chown postgres:postgres ${PGDATA} && \ + chown -R postgres:postgres /pg/testdir && \ + chown postgres:postgres /usr/local/include/postgresql/server/ && \ + chmod a+rwx /usr/local/lib/postgresql && \ + chmod a+rwx /usr/local/share/postgresql/extension + +USER postgres +ENTRYPOINT LEVEL=${LEVEL} /run.sh diff --git a/travis/docker-compose.yml b/travis/docker-compose.yml new file mode 100644 index 0000000000..471ab779f2 --- /dev/null +++ b/travis/docker-compose.yml @@ -0,0 +1,2 @@ +tests: + build: . diff --git a/travis/mk_dockerfile.sh b/travis/mk_dockerfile.sh new file mode 100755 index 0000000000..9108d2c68d --- /dev/null +++ b/travis/mk_dockerfile.sh @@ -0,0 +1,16 @@ +if [ -z ${PG_VERSION+x} ]; then + echo PG_VERSION is not set! + exit 1 +fi + +if [ -z ${LEVEL+x} ]; then + LEVEL=standard +fi + +echo PG_VERSION=${PG_VERSION} +echo LEVEL=${LEVEL} + +sed \ + -e 's/${PG_VERSION}/'${PG_VERSION}/g \ + -e 's/${LEVEL}/'${LEVEL}/g \ +Dockerfile.in > Dockerfile diff --git a/travis/run_tests.sh b/travis/run_tests.sh new file mode 100644 index 0000000000..c1f598a196 --- /dev/null +++ b/travis/run_tests.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +# +# Copyright (c) 2019, Postgres Professional +# +# supported levels: +# * standard +# * hardcore +# + +set -ux +status=0 + + +# rebuild PostgreSQL with cassert support +if [ "$LEVEL" = "hardcore" ]; then + + set -e + + CUSTOM_PG_BIN=$PWD/pg_bin + CUSTOM_PG_SRC=$PWD/postgresql + + # here PG_VERSION is provided by postgres:X-alpine docker image + curl "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" -o postgresql.tar.bz2 + echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - + + mkdir $CUSTOM_PG_SRC + + tar \ + --extract \ + --file postgresql.tar.bz2 \ + --directory $CUSTOM_PG_SRC \ + --strip-components 1 + + cd $CUSTOM_PG_SRC + + # enable additional options + ./configure \ + CFLAGS='-O0 -ggdb3 -fno-omit-frame-pointer' \ + --enable-cassert \ + --prefix=$CUSTOM_PG_BIN \ + --quiet + + time make -s -j$(nproc) && make -s install + + # override default PostgreSQL instance + export PATH=$CUSTOM_PG_BIN/bin:$PATH + export LD_LIBRARY_PATH=$CUSTOM_PG_BIN/lib + + # show pg_config path (just in case) + which pg_config + + cd - + + set +e +fi + +# show pg_config just in case +pg_config + +# perform code checks if asked to +if [ "$LEVEL" = "hardcore" ]; then + + # perform static analyzis + scan-build --status-bugs make USE_PGXS=1 || status=$? + + # something's wrong, exit now! + if [ $status -ne 0 ]; then exit 1; fi + + # don't forget to "make clean" + make USE_PGXS=1 clean +fi + + +# build and install extension (using PG_CPPFLAGS and SHLIB_LINK for gcov) +make USE_PGXS=1 PG_CPPFLAGS="-coverage" SHLIB_LINK="-coverage" install + +# initialize database +initdb -D $PGDATA + +# set appropriate port +export PGPORT=55435 +echo "port = $PGPORT" >> $PGDATA/postgresql.conf + +# restart cluster 'test' +pg_ctl start -l /tmp/postgres.log -w || status=$? + +# something's wrong, exit now! +if [ $status -ne 0 ]; then cat /tmp/postgres.log; exit 1; fi + +# run regression tests +export PG_REGRESS_DIFF_OPTS="-w -U3" # for alpine's diff (BusyBox) +make USE_PGXS=1 installcheck || status=$? + +# show diff if it exists +if test -f regression.diffs; then cat regression.diffs; fi + +# something's wrong, exit now! +if [ $status -ne 0 ]; then exit 1; fi + +# generate *.gcov files +gcov src/*.c src/*.h + + +set +ux + + +# send coverage stats to Codecov +bash <(curl -s https://codecov.io/bash)