mirror of
https://github.com/HypoPG/hypopg
synced 2026-05-24 09:38:21 +00:00
Merge tag '1.4.0' into debian
This commit is contained in:
commit
4d256101a3
31 changed files with 1107 additions and 77 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -1,6 +1,21 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
2023-05-27 version 1.4.0:
|
||||
-------------------------
|
||||
|
||||
**New features**:
|
||||
|
||||
- Support hypothetically hiding existing indexes, hypothetical or not (github
|
||||
user nutvii and Julien Rouhaud)
|
||||
|
||||
**Miscellaneous**:
|
||||
|
||||
- Have hypopg_relation_size() error out rather than returning 0 if called for
|
||||
an oid that isn't a hypothetical index oid
|
||||
- Slighthly reduce memory usage for hypothetical btree indexes without
|
||||
INCLUDE keys
|
||||
|
||||
2021-06-21 version 1.3.1:
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -17,3 +17,6 @@ People who contributed to hypopg:
|
|||
* nagaraju11
|
||||
* ibrahim edib kokdemir
|
||||
* github user nikhil-postgres
|
||||
* Xiaozhe Yao
|
||||
* Krzysztof Szularz
|
||||
* NutVII
|
||||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Portions Copyright (c) 2015-2021, PostgreSQL GLobal Development Group
|
||||
Portions Copyright (c) 2015-2023, PostgreSQL GLobal Development Group
|
||||
|
||||
Portions Copyright (c) 1994, The Regents of the University of California
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -51,6 +51,8 @@ ifneq ($(MAJORVERSION),$(filter $(MAJORVERSION), 9.2 9.3 9.4 9.5 9.6))
|
|||
REGRESS += hypo_hash
|
||||
endif
|
||||
|
||||
REGRESS += hypo_hide_index
|
||||
|
||||
DEBUILD_ROOT = /tmp/$(EXTENSION)
|
||||
|
||||
deb: release-zip
|
||||
|
|
|
|||
91
README.md
91
README.md
|
|
@ -63,7 +63,7 @@ a future release.
|
|||
|
||||
You can check the available hypothetical indexes in your own backend:
|
||||
|
||||
rjuju=# SELECT * FROM hypopg_list_indexes();
|
||||
rjuju=# SELECT * FROM hypopg_list_indexes ;
|
||||
indexrelid | indexname | nspname | relname | amname
|
||||
-----------+-------------------------------------------+---------+---------+--------
|
||||
205101 | <41072>btree_hypo_id | public | hypo | btree
|
||||
|
|
@ -96,6 +96,91 @@ Of course, only `EXPLAIN` without `ANALYZE` will use hypothetical indexes:
|
|||
(5 rows)
|
||||
|
||||
To remove your backend's hypothetical indexes, you can use the function
|
||||
`hypopg_drop_index(indexrelid)` with the OID that the `hypopg_list_indexes()`
|
||||
function returns and call `hypopg_reset()` to remove all at once, or just close
|
||||
`hypopg_drop_index(indexrelid)` with the OID that the `hypopg_list_indexes`
|
||||
view returns and call `hypopg_reset()` to remove all at once, or just close
|
||||
your current connection.
|
||||
|
||||
Continuing with the above case, you can `hide existing indexes`,
|
||||
but should be use `hypopg_reset()` to clear the previous effects of other indexes at first.
|
||||
|
||||
Create two real indexes and run `EXPLAIN`:
|
||||
|
||||
rjuju=# SELECT hypopg_reset();
|
||||
rjuju=# CREATE INDEX ON hypo(id);
|
||||
rjuju=# CREATE INDEX ON hypo(id, val);
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------
|
||||
Index Only Scan using hypo_id_val_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
The query plan is using the `hypo_id_val_idx` index. Use `hypopg_hide_index(oid)` to hide one of the indexes:
|
||||
|
||||
rjuju=# SELECT hypopg_hide_index('hypo_id_val_idx'::REGCLASS);
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------
|
||||
Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
The query plan is using the other index `hypo_id_idx` now. Use `hypopg_hide_index(oid)` to hide it:
|
||||
|
||||
rjuju=# SELECT hypopg_hide_index('hypo_id_idx'::REGCLASS);
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Seq Scan on hypo (cost=0.00..180.00 rows=1 width=13)
|
||||
Filter: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
And now the query plan changes back to `Seq Scan`. Use `hypopg_unhide_index(oid)` to restore index:
|
||||
|
||||
rjuju=# SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------
|
||||
Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
Of course, you can also hide hypothetical indexes:
|
||||
|
||||
rjuju=# SELECT hypopg_create_index('CREATE INDEX ON hypo(id)');
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------
|
||||
Index Scan using "<12659>btree_hypo_id" on hypo (cost=0.04..8.05 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
rjuju=# SELECT hypopg_hide_index(12659);
|
||||
rjuju=# EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Seq Scan on hypo (cost=0.00..180.00 rows=1 width=13)
|
||||
Filter: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
You can check which indexes are hidden using `hypopg_hidden_indexes()` or the `hypopg_hidden_indexes` view:
|
||||
|
||||
rjuju=# SELECT * FROM hypopg_hidden_indexes();
|
||||
indexid
|
||||
---------
|
||||
526604
|
||||
526603
|
||||
12659
|
||||
(3 rows)
|
||||
|
||||
rjuju=# SELECT * FROM hypopg_hidden_indexes;
|
||||
indexrelid | index_name | schema_name | table_name | am_name | is_hypo
|
||||
------------+----------------------+-------------+------------+---------+---------
|
||||
12659 | <12659>btree_hypo_id | public | hypo | btree | t
|
||||
526603 | hypo_id_idx | public | hypo | btree | f
|
||||
526604 | hypo_id_val_idx | public | hypo | btree | f
|
||||
(3 rows)
|
||||
|
||||
To restore all existing indexes, you can use the function `hypopg_unhide_all_indexes()`.
|
||||
Note that the functionality to hide existing indexes only applies to the EXPLAIN command in the current session
|
||||
and will not affect other sessions.
|
||||
|
|
|
|||
6
debian/changelog
vendored
6
debian/changelog
vendored
|
|
@ -1,3 +1,9 @@
|
|||
hypopg (1.4.0-1) unstable; urgency=medium
|
||||
|
||||
* New upstream version.
|
||||
|
||||
-- Julien Rouhaud <rjuju123@gmail.com> Mon, 31 Jul 2023 12:28:46 +0200
|
||||
|
||||
hypopg (1.3.1-2) unstable; urgency=medium
|
||||
|
||||
* Upload for PostgreSQL 15.
|
||||
|
|
|
|||
2
debian/copyright
vendored
2
debian/copyright
vendored
|
|
@ -1,4 +1,4 @@
|
|||
Portions Copyright (c) 2015-2021, PostgreSQL GLobal Development Group
|
||||
Portions Copyright (c) 2015-2023, PostgreSQL GLobal Development Group
|
||||
|
||||
Portions Copyright (c) 1994, The Regents of the University of California
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = 'HypoPG'
|
||||
copyright = '2015-2021, Julien Rouhaud'
|
||||
copyright = '2015-2023, Julien Rouhaud'
|
||||
author = 'Julien Rouhaud'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.. title:: HypoPG: Hypothetical indexes for PostgreSQL
|
||||
.. title:: HypoPG: Hypothetical indexes for PostgreSQL
|
||||
|
||||
HypoPG
|
||||
======
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Packages
|
|||
|
||||
Hypopg is available as a package on some GNU/Linux distributions:
|
||||
|
||||
- RHEL/Centos
|
||||
- RHEL/Rocky Linux
|
||||
|
||||
HypoPG is available as a package using `the PGDG packages
|
||||
<https://yum.postgresql.org>`_.
|
||||
|
|
@ -25,6 +25,20 @@ Hypopg is available as a package on some GNU/Linux distributions:
|
|||
|
||||
yum install hypopg
|
||||
|
||||
- Debian / Ubuntu
|
||||
|
||||
HypoPG is available as a package using `the PGDG packages
|
||||
<https://apt.postgresql.org>`_.
|
||||
|
||||
Once the PGDG repository is setup, you just need to install the package. As
|
||||
root:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
apt install postgresql-XY-hypopg
|
||||
|
||||
where XY is the major version for which you want to install hypopg.
|
||||
|
||||
- Archlinux
|
||||
|
||||
Hypopg is available on the `AUR repository
|
||||
|
|
|
|||
204
docs/usage.rst
204
docs/usage.rst
|
|
@ -174,41 +174,219 @@ use such indexes.
|
|||
Manipulate hypothetical indexes
|
||||
-------------------------------
|
||||
|
||||
Some other convenience functions are available:
|
||||
Some other convenience functions and views are available:
|
||||
|
||||
- **hypopg_list_indexes()**: list all hypothetical indexes that have been
|
||||
created
|
||||
- **hypopg_list_indexes**: view that lists all hypothetical indexes that have
|
||||
been created
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT * FROM hypopg_list_indexes()
|
||||
SELECT * FROM hypopg_list_indexes ;
|
||||
indexrelid | indexname | nspname | relname | amname
|
||||
------------+----------------------+---------+---------+--------
|
||||
18284 | <18284>btree_hypo_id | public | hypo | btree
|
||||
(1 row)
|
||||
|
||||
- **hypopg_get_indexdef(oid)**: get the CREATE INDEX statement that would
|
||||
recreate a stored hypothetical index
|
||||
- **hypopg()**: function that lists all hypothetical indexes that have
|
||||
been created with the same format as **pg_index**
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT indexname, hypopg_get_indexdef(indexrelid) FROM hypopg_list_indexes() ;
|
||||
indexname | hypopg_get_indexdef
|
||||
SELECT * FROM hypopg() ;
|
||||
indexname | indexrelid | indrelid | innatts | indisunique | indkey | indcollation | indclass | indoption | indexprs | indpred | amid
|
||||
----------------------+------------+----------+---------+-------------+--------+--------------+----------+-----------+----------+---------+------
|
||||
<18284>btree_hypo_id | 13543 | 18122 | 1 | f | 1 | 0 | 1978 | <NULL> | <NULL> | <NULL> | 403
|
||||
(1 row)
|
||||
|
||||
- **hypopg_get_indexdef(oid)**: function that lists the CREATE INDEX statement
|
||||
that would recreate a stored hypothetical index
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT indexname, hypopg_get_indexdef(indexrelid) FROM hypopg_list_indexes ;
|
||||
indexname | hypopg_get_indexdef
|
||||
----------------------+----------------------------------------------
|
||||
<18284>btree_hypo_id | CREATE INDEX ON public.hypo USING btree (id)
|
||||
(1 row)
|
||||
|
||||
- **hypopg_relation_size(oid)**: estimate how big a hypothetical index would
|
||||
be:
|
||||
- **hypopg_relation_size(oid)**: function that estimates how big a hypothetical
|
||||
index would be:
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT indexname, pg_size_pretty(hypopg_relation_size(indexrelid))
|
||||
FROM hypopg_list_indexes() ;
|
||||
FROM hypopg_list_indexes ;
|
||||
indexname | pg_size_pretty
|
||||
----------------------+----------------
|
||||
<18284>btree_hypo_id | 2544 kB
|
||||
(1 row)
|
||||
|
||||
- **hypopg_drop_index(oid)**: remove the given hypothetical index
|
||||
- **hypopg_reset()**: remove all hypothetical indexes
|
||||
- **hypopg_drop_index(oid)**: function that removes the given hypothetical
|
||||
index
|
||||
- **hypopg_reset()**: function that removes all hypothetical indexes
|
||||
|
||||
Hypothetically hide existing indexes
|
||||
------------------------------------
|
||||
|
||||
You can hide both existing and hypothetical indexes hypothetically.
|
||||
If you want to test it as described in the documentation,
|
||||
you should first use **hypopg_reset()** to clear the effects of any other hypothetical indexes.
|
||||
|
||||
As a simple case, let's consider two indexes:
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT hypopg_reset();
|
||||
CREATE INDEX ON hypo(id);
|
||||
CREATE INDEX ON hypo(id, val);
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 4
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------
|
||||
Index Only Scan using hypo_id_val_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
The query plan is using the **hypo_id_val_idx** index now.
|
||||
|
||||
- **hypopg_hide_index(oid)**: function that allows you to hide an index in the EXPLAIN output by using its OID.
|
||||
It returns `true` if the index was successfully hidden, and `false` otherwise.
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 10
|
||||
|
||||
SELECT hypopg_hide_index('hypo_id_val_idx'::REGCLASS);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------
|
||||
Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
As an example, let's assume that the query plan is currently using the **hypo_id_val_idx** index.
|
||||
To continue testing, use the **hypopg_hide_index(oid)** function to hide another index.
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 10
|
||||
|
||||
SELECT hypopg_hide_index('hypo_id_idx'::REGCLASS);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Seq Scan on hypo (cost=0.00..180.00 rows=1 width=13)
|
||||
Filter: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
- **hypopg_unhide_index(oid)**: function that restore a previously hidden index in the EXPLAIN output by using its OID.
|
||||
It returns `true` if the index was successfully restored, and `false` otherwise.
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 10
|
||||
|
||||
SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
hypopg_unhide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------
|
||||
Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
- **hypopg_unhide_all_index()**: function that restore all hidden indexes and returns void.
|
||||
|
||||
- **hypopg_hidden_indexes()**: function that returns a list of OIDs for all hidden indexes.
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT * FROM hypopg_hidden_indexes();
|
||||
indexid
|
||||
---------
|
||||
526604
|
||||
(1 rows)
|
||||
|
||||
- **hypopg_hidden_indexes**: view that returns a formatted list of all hidden indexes.
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT * FROM hypopg_hidden_indexes;
|
||||
indexrelid | index_name | schema_name | table_name | am_name | is_hypo
|
||||
-------------+----------------------+-------------+------------+---------+---------
|
||||
526604 | hypo_id_val_idx | public | hypo | btree | f
|
||||
(1 rows)
|
||||
|
||||
.. note::
|
||||
|
||||
Hypothetical indexes can be hidden as well.
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 10
|
||||
|
||||
SELECT hypopg_create_index('CREATE INDEX ON hypo(id)');
|
||||
hypopg_create_index
|
||||
------------------------------
|
||||
(12659,<12659>btree_hypo_id)
|
||||
(1 row)
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------
|
||||
Index Scan using "<12659>btree_hypo_id" on hypo (cost=0.04..8.05 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
Now that the hypothetical index is being used, we can try hiding it to see the change:
|
||||
|
||||
.. code-block:: psql
|
||||
:emphasize-lines: 10
|
||||
|
||||
SELECT hypopg_hide_index(12659);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
EXPLAIN SELECT * FROM hypo WHERE id = 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------
|
||||
Index Scan using hypo_id_idx on hypo (cost=0.29..8.30 rows=1 width=13)
|
||||
Index Cond: (id = 1)
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM hypopg_hidden_indexes;
|
||||
indexrelid | index_name | schema_name | table_name | am_name | is_hypo
|
||||
-------------+----------------------+-------------+------------+---------+---------
|
||||
12659 | <12659>btree_hypo_id | public | hypo | btree | t
|
||||
526604 | hypo_id_val_idx | public | hypo | btree | f
|
||||
(2 rows)
|
||||
|
||||
.. note::
|
||||
|
||||
If a hypothetical index has been hidden, it will be automatically unhidden
|
||||
when it is deleted using **hypopg_drop_index(oid)** or **hypopg_reset()**.
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
SELECT hypopg_drop_index(12659);
|
||||
|
||||
SELECT * FROM hypopg_hidden_indexes;
|
||||
indexrelid | index_name | schema_name | table_name | am_name | is_hypo
|
||||
-------------+----------------------+-------------+------------+---------+---------
|
||||
526604 | hypo_id_val_idx | public | hypo | btree | f
|
||||
(2 rows)
|
||||
|
|
|
|||
268
expected/hypo_hide_index.out
Normal file
268
expected/hypo_hide_index.out
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
-- Hypothetically hiding existing indexes tests
|
||||
-- Remove all the hypothetical indexes if any
|
||||
SELECT hypopg_reset();
|
||||
hypopg_reset
|
||||
--------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- The EXPLAIN initial state
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- Create real index in hypo and use this index
|
||||
CREATE INDEX hypo_id_idx ON hypo(id);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- Should be zero
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- The hypo_id_idx index should not be used
|
||||
SELECT hypopg_hide_index('hypo_id_idx'::regclass);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- Should be only one record
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
table_name | index_name
|
||||
------------+-------------
|
||||
hypo | hypo_id_idx
|
||||
(1 row)
|
||||
|
||||
-- Create the real index again and
|
||||
-- EXPLAIN should use this index instead of the previous one
|
||||
CREATE index hypo_id_val_idx ON hypo(id, val);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_val_idx';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- Shouldn't use any index
|
||||
SELECT hypopg_hide_index('hypo_id_val_idx'::regclass);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_val_idx';
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- Should be two records
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
table_name | index_name
|
||||
------------+-----------------
|
||||
hypo | hypo_id_idx
|
||||
hypo | hypo_id_val_idx
|
||||
(2 rows)
|
||||
|
||||
-- Try to add one repeatedly or add another wrong index oid
|
||||
SELECT hypopg_hide_index('hypo_id_idx'::regclass);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_hide_index('hypo'::regclass);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_hide_index(0);
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
-- Also of course can be used to hide hypothetical indexes
|
||||
SELECT COUNT(*) FROM hypopg_create_index('create index on hypo(id,val);');
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_hide_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- Should be only three records
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
count
|
||||
-------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
-- Hypothetical indexes should be unhidden when deleting
|
||||
SELECT hypopg_drop_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
hypopg_drop_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- Should become two records
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
-- Hypopg_reset can also unhidden the hidden indexes
|
||||
-- due to the deletion of hypothetical indexes.
|
||||
SELECT COUNT(*) FROM hypopg_create_index('create index on hypo(id,val);');
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_hide_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
hypopg_hide_index
|
||||
-------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- Changed from three records to two records.
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
count
|
||||
-------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_reset();
|
||||
hypopg_reset
|
||||
--------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
-- Unhide an index
|
||||
SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
hypopg_unhide_index
|
||||
---------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
count
|
||||
-------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- Should become one record
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
table_name | index_name
|
||||
------------+-----------------
|
||||
hypo | hypo_id_val_idx
|
||||
(1 row)
|
||||
|
||||
-- Try to delete one repeatedly or delete another wrong index oid
|
||||
SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
hypopg_unhide_index
|
||||
---------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_unhide_index('hypo'::regclass);
|
||||
hypopg_unhide_index
|
||||
---------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT hypopg_unhide_index(0);
|
||||
hypopg_unhide_index
|
||||
---------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
-- Should still have one record
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
table_name | index_name
|
||||
------------+-----------------
|
||||
hypo | hypo_id_val_idx
|
||||
(1 row)
|
||||
|
||||
-- Unhide all indexes
|
||||
SELECT hypopg_unhide_all_indexes();
|
||||
hypopg_unhide_all_indexes
|
||||
---------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- Should change back to the original zero
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
count
|
||||
-------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- Clean real indexes and hypothetical indexes
|
||||
DROP INDEX hypo_id_idx;
|
||||
DROP INDEX hypo_id_val_idx;
|
||||
SELECT hypopg_reset();
|
||||
hypopg_reset
|
||||
--------------
|
||||
|
||||
(1 row)
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
-- Hypothetical on partitioned tables
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
-- Hypothetical on partitioned tables
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
CREATE TABLE hypo_part_1
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ ORDER BY indexrelid;
|
|||
f
|
||||
(3 rows)
|
||||
|
||||
-- Should detect invalid argument
|
||||
SELECT hypopg_relation_size(1);
|
||||
ERROR: oid 1 is not a hypothetical index
|
||||
-- locally disable hypoopg
|
||||
SET hypopg.enabled to false;
|
||||
-- no hypothetical index should be used
|
||||
|
|
|
|||
50
hypopg--1.3.1--1.4.0.sql
Normal file
50
hypopg--1.3.1--1.4.0.sql
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
-- This program is open source, licensed under the PostgreSQL License.
|
||||
-- For license terms, see the LICENSE file.
|
||||
--
|
||||
-- Copyright (C) 2015-2023: Julien Rouhaud
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "ALTER EXTENSION hypopg" to load this file. \quit
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_hide_index(IN indexid oid)
|
||||
RETURNS bool
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_hide_index';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_unhide_index(IN indexid oid)
|
||||
RETURNS bool
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_unhide_index';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_unhide_all_indexes()
|
||||
RETURNS void
|
||||
LANGUAGE C VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_unhide_all_indexes';
|
||||
|
||||
CREATE FUNCTION hypopg_hidden_indexes()
|
||||
RETURNS TABLE (indexid oid)
|
||||
LANGUAGE C STRICT VOLATILE
|
||||
AS '$libdir/hypopg', 'hypopg_hidden_indexes';
|
||||
|
||||
CREATE VIEW hypopg_hidden_indexes
|
||||
AS
|
||||
SELECT h.indexid AS indexrelid,
|
||||
i.relname AS index_name,
|
||||
n.nspname AS schema_name,
|
||||
t.relname AS table_name,
|
||||
m.amname AS am_name,
|
||||
false AS is_hypo
|
||||
FROM hypopg_hidden_indexes() h
|
||||
JOIN pg_index x ON x.indexrelid = h.indexid
|
||||
JOIN pg_class i ON i.oid = h.indexid
|
||||
JOIN pg_namespace n ON n.oid = i.relnamespace
|
||||
JOIN pg_class t ON t.oid = x.indrelid
|
||||
JOIN pg_am m ON m.oid = i.relam
|
||||
UNION ALL
|
||||
SELECT hl.*, true AS is_hypo
|
||||
FROM hypopg_hidden_indexes() hi
|
||||
JOIN hypopg_list_indexes hl on hl.indexrelid = hi.indexid
|
||||
ORDER BY index_name;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
-- This program is open source, licensed under the PostgreSQL License.
|
||||
-- For license terms, see the LICENSE file.
|
||||
--
|
||||
-- Copyright (C) 2015-2021: Julien Rouhaud
|
||||
-- Copyright (C) 2015-2023: Julien Rouhaud
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION hypopg" to load this file. \quit
|
||||
|
|
|
|||
105
hypopg--1.4.0.sql
Normal file
105
hypopg--1.4.0.sql
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
-- This program is open source, licensed under the PostgreSQL License.
|
||||
-- For license terms, see the LICENSE file.
|
||||
--
|
||||
-- Copyright (C) 2015-2023: Julien Rouhaud
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION hypopg" to load this file. \quit
|
||||
|
||||
SET LOCAL client_encoding = 'UTF8';
|
||||
|
||||
CREATE FUNCTION hypopg_reset_index()
|
||||
RETURNS void
|
||||
LANGUAGE C VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_reset_index';
|
||||
|
||||
CREATE FUNCTION hypopg_reset()
|
||||
RETURNS void
|
||||
LANGUAGE C VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_reset';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_create_index(IN sql_order text, OUT indexrelid oid, OUT indexname text)
|
||||
RETURNS SETOF record
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_create_index';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_drop_index(IN indexid oid)
|
||||
RETURNS bool
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_drop_index';
|
||||
|
||||
CREATE FUNCTION hypopg(OUT indexname text, OUT indexrelid oid,
|
||||
OUT indrelid oid, OUT innatts integer,
|
||||
OUT indisunique boolean, OUT indkey int2vector,
|
||||
OUT indcollation oidvector, OUT indclass oidvector,
|
||||
OUT indoption oidvector, OUT indexprs pg_node_tree,
|
||||
OUT indpred pg_node_tree, OUT amid oid)
|
||||
RETURNS SETOF record
|
||||
LANGUAGE c COST 100
|
||||
AS '$libdir/hypopg', 'hypopg';
|
||||
|
||||
CREATE VIEW hypopg_list_indexes
|
||||
AS
|
||||
SELECT h.indexrelid, h.indexname AS index_name, n.nspname AS schema_name,
|
||||
coalesce(c.relname, '<dropped>') AS table_name, am.amname AS am_name
|
||||
FROM hypopg() h
|
||||
LEFT JOIN pg_catalog.pg_class c ON c.oid = h.indrelid
|
||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||
LEFT JOIN pg_catalog.pg_am am ON am.oid = h.amid;
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_relation_size(IN indexid oid)
|
||||
RETURNS bigint
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_relation_size';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_get_indexdef(IN indexid oid)
|
||||
RETURNS text
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_get_indexdef';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_hide_index(IN indexid oid)
|
||||
RETURNS bool
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_hide_index';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_unhide_index(IN indexid oid)
|
||||
RETURNS bool
|
||||
LANGUAGE C STRICT VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_unhide_index';
|
||||
|
||||
CREATE FUNCTION
|
||||
hypopg_unhide_all_indexes()
|
||||
RETURNS void
|
||||
LANGUAGE C VOLATILE COST 100
|
||||
AS '$libdir/hypopg', 'hypopg_unhide_all_indexes';
|
||||
|
||||
CREATE FUNCTION hypopg_hidden_indexes()
|
||||
RETURNS TABLE (indexid oid)
|
||||
LANGUAGE C STRICT VOLATILE
|
||||
AS '$libdir/hypopg', 'hypopg_hidden_indexes';
|
||||
|
||||
CREATE VIEW hypopg_hidden_indexes
|
||||
AS
|
||||
SELECT h.indexid AS indexrelid,
|
||||
i.relname AS index_name,
|
||||
n.nspname AS schema_name,
|
||||
t.relname AS table_name,
|
||||
m.amname AS am_name,
|
||||
false AS is_hypo
|
||||
FROM hypopg_hidden_indexes() h
|
||||
JOIN pg_index x ON x.indexrelid = h.indexid
|
||||
JOIN pg_class i ON i.oid = h.indexid
|
||||
JOIN pg_namespace n ON n.oid = i.relnamespace
|
||||
JOIN pg_class t ON t.oid = x.indrelid
|
||||
JOIN pg_am m ON m.oid = i.relam
|
||||
UNION ALL
|
||||
SELECT hl.*, true AS is_hypo
|
||||
FROM hypopg_hidden_indexes() hi
|
||||
JOIN hypopg_list_indexes hl on hl.indexrelid = hi.indexid
|
||||
ORDER BY index_name;
|
||||
31
hypopg.c
31
hypopg.c
|
|
@ -8,7 +8,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (C) 2015-2021: Julien Rouhaud
|
||||
* Copyright (C) 2015-2023: Julien Rouhaud
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -55,7 +55,6 @@ static bool oid_wraparound = false;
|
|||
/*--- Functions --- */
|
||||
|
||||
PGDLLEXPORT void _PG_init(void);
|
||||
PGDLLEXPORT void _PG_fini(void);
|
||||
|
||||
PGDLLEXPORT Datum hypopg_reset(PG_FUNCTION_ARGS);
|
||||
|
||||
|
|
@ -103,7 +102,7 @@ static void hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
static get_relation_info_hook_type prev_get_relation_info_hook = NULL;
|
||||
|
||||
static bool hypo_index_match_table(hypoIndex *entry, Oid relid);
|
||||
static bool hypo_query_walker(Node *node);
|
||||
static bool hypo_is_simple_explain(Node *node);
|
||||
|
||||
void
|
||||
_PG_init(void)
|
||||
|
|
@ -123,6 +122,7 @@ _PG_init(void)
|
|||
|
||||
isExplain = false;
|
||||
hypoIndexes = NIL;
|
||||
hypoHiddenIndexes = NIL;
|
||||
|
||||
HypoMemoryContext = AllocSetContextCreate(TopMemoryContext,
|
||||
"HypoPG context",
|
||||
|
|
@ -160,17 +160,6 @@ _PG_init(void)
|
|||
EmitWarningsOnPlaceholders("hypopg");
|
||||
}
|
||||
|
||||
void
|
||||
_PG_fini(void)
|
||||
{
|
||||
/* uninstall hooks */
|
||||
ProcessUtility_hook = prev_utility_hook;
|
||||
ExecutorEnd_hook = prev_ExecutorEnd_hook;
|
||||
get_relation_info_hook = prev_get_relation_info_hook;
|
||||
explain_get_index_name_hook = prev_explain_get_index_name_hook;
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------
|
||||
* Return a new OID for an hypothetical index.
|
||||
*
|
||||
|
|
@ -315,14 +304,13 @@ hypo_utility_hook(
|
|||
#endif
|
||||
)
|
||||
{
|
||||
isExplain = query_or_expression_tree_walker(
|
||||
isExplain = hypo_is_simple_explain(
|
||||
#if PG_VERSION_NUM >= 100000
|
||||
(Node *) pstmt,
|
||||
(Node *) pstmt
|
||||
#else
|
||||
parsetree,
|
||||
parsetree
|
||||
#endif
|
||||
hypo_query_walker,
|
||||
NULL, 0);
|
||||
);
|
||||
|
||||
if (prev_utility_hook)
|
||||
prev_utility_hook(
|
||||
|
|
@ -416,7 +404,7 @@ hypo_index_match_table(hypoIndex *entry, Oid relid)
|
|||
* i.e. an EXPLAIN, no ANALYZE
|
||||
*/
|
||||
static bool
|
||||
hypo_query_walker(Node *parsetree)
|
||||
hypo_is_simple_explain(Node *parsetree)
|
||||
{
|
||||
if (parsetree == NULL)
|
||||
return false;
|
||||
|
|
@ -426,6 +414,7 @@ hypo_query_walker(Node *parsetree)
|
|||
if (parsetree == NULL)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
switch (nodeTag(parsetree))
|
||||
{
|
||||
case T_ExplainStmt:
|
||||
|
|
@ -540,6 +529,8 @@ hypo_get_relation_info_hook(PlannerInfo *root,
|
|||
inhparent, rel, relation, entry);
|
||||
}
|
||||
}
|
||||
|
||||
hypo_hideIndexes(rel);
|
||||
}
|
||||
|
||||
/* Close the relation release the lock now */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# hypopg extension
|
||||
comment = 'Hypothetical indexes for PostgreSQL'
|
||||
default_version = '1.3.1'
|
||||
default_version = '1.4.0'
|
||||
module_pathname = '$libdir/hypopg'
|
||||
relocatable = true
|
||||
|
||||
|
|
|
|||
245
hypopg_index.c
245
hypopg_index.c
|
|
@ -8,7 +8,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (C) 2015-2021: Julien Rouhaud
|
||||
* Copyright (C) 2015-2023: Julien Rouhaud
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -81,6 +81,7 @@ static Oid BLOOM_AM_OID = InvalidOid;
|
|||
|
||||
explain_get_index_name_hook_type prev_explain_get_index_name_hook;
|
||||
List *hypoIndexes;
|
||||
List *hypoHiddenIndexes;
|
||||
|
||||
/*--- Functions --- */
|
||||
|
||||
|
|
@ -90,6 +91,10 @@ PG_FUNCTION_INFO_V1(hypopg_drop_index);
|
|||
PG_FUNCTION_INFO_V1(hypopg_relation_size);
|
||||
PG_FUNCTION_INFO_V1(hypopg_get_indexdef);
|
||||
PG_FUNCTION_INFO_V1(hypopg_reset_index);
|
||||
PG_FUNCTION_INFO_V1(hypopg_hide_index);
|
||||
PG_FUNCTION_INFO_V1(hypopg_unhide_index);
|
||||
PG_FUNCTION_INFO_V1(hypopg_unhide_all_indexes);
|
||||
PG_FUNCTION_INFO_V1(hypopg_hidden_indexes);
|
||||
|
||||
|
||||
static void hypo_addIndex(hypoIndex * entry);
|
||||
|
|
@ -101,6 +106,7 @@ static void hypo_estimate_index(hypoIndex * entry, RelOptInfo *rel);
|
|||
static int hypo_estimate_index_colsize(hypoIndex * entry, int col);
|
||||
static void hypo_index_pfree(hypoIndex * entry);
|
||||
static bool hypo_index_remove(Oid indexid);
|
||||
static bool hypo_index_unhide(Oid indexid);
|
||||
static const hypoIndex *hypo_index_store_parsetree(IndexStmt *node,
|
||||
const char *queryString);
|
||||
static hypoIndex * hypo_newIndex(Oid relid, char *accessMethod, int nkeycolumns,
|
||||
|
|
@ -350,7 +356,7 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
/*
|
||||
* Support for hypothetical BRIN indexes is broken in some minor versions
|
||||
* of pg10, pg11 and pg12. For simplicity, check PG_VERSION_NUM rather
|
||||
* than the real instance version, which should should be right most of the
|
||||
* than the real instance version, which should be right most of the
|
||||
* time. When it's not, the only effect is to have a less user-friendly
|
||||
* error message.
|
||||
*/
|
||||
|
|
@ -395,12 +401,13 @@ hypo_index_store_parsetree(IndexStmt *node, const char *queryString)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
elog(ERROR, "hypopg: \"%s\" is not a table"
|
||||
#if PG_VERSION_NUM >= 90300
|
||||
" or materialized view"
|
||||
#endif
|
||||
,
|
||||
elog(ERROR, "hypopg: \"%s\" is not a table or materialized view",
|
||||
node->relation->relname);
|
||||
#else
|
||||
elog(ERROR, "hypopg: \"%s\" is not a table",
|
||||
node->relation->relname);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Run parse analysis ... */
|
||||
|
|
@ -921,6 +928,9 @@ hypo_index_remove(Oid indexid)
|
|||
{
|
||||
ListCell *lc;
|
||||
|
||||
/* remove this index from the list of hidden indexes if present */
|
||||
hypo_index_unhide(indexid);
|
||||
|
||||
foreach(lc, hypoIndexes)
|
||||
{
|
||||
hypoIndex *entry = (hypoIndex *) lfirst(lc);
|
||||
|
|
@ -932,6 +942,7 @@ hypo_index_remove(Oid indexid)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1012,21 +1023,17 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
#endif
|
||||
|
||||
index->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
|
||||
index->indexcollations = (Oid *) palloc(sizeof(int) * ncolumns);
|
||||
index->opfamily = (Oid *) palloc(sizeof(int) * ncolumns);
|
||||
index->opcintype = (Oid *) palloc(sizeof(int) * ncolumns);
|
||||
|
||||
#if PG_VERSION_NUM >= 90500
|
||||
index->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
|
||||
#endif
|
||||
index->indexcollations = (Oid *) palloc(sizeof(int) * nkeycolumns);
|
||||
index->opfamily = (Oid *) palloc(sizeof(int) * nkeycolumns);
|
||||
index->opcintype = (Oid *) palloc(sizeof(int) * nkeycolumns);
|
||||
|
||||
if ((index->relam == BTREE_AM_OID) || entry->amcanorder)
|
||||
{
|
||||
if (index->relam != BTREE_AM_OID)
|
||||
index->sortopfamily = palloc0(sizeof(Oid) * ncolumns);
|
||||
index->sortopfamily = palloc0(sizeof(Oid) * nkeycolumns);
|
||||
|
||||
index->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
|
||||
index->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
|
||||
index->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
|
||||
index->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1035,6 +1042,10 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
index->nulls_first = NULL;
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM >= 90500
|
||||
index->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ncolumns; i++)
|
||||
{
|
||||
index->indexkeys[i] = entry->indexkeys[i];
|
||||
|
|
@ -1045,9 +1056,9 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
|
||||
for (i = 0; i < nkeycolumns; i++)
|
||||
{
|
||||
index->indexcollations[i] = entry->indexcollations[i];
|
||||
index->opfamily[i] = entry->opfamily[i];
|
||||
index->opcintype[i] = entry->opcintype[i];
|
||||
index->indexcollations[i] = entry->indexcollations[i];
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1063,7 +1074,7 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
*/
|
||||
index->sortopfamily = index->opfamily;
|
||||
|
||||
for (i = 0; i < ncolumns; i++)
|
||||
for (i = 0; i < nkeycolumns; i++)
|
||||
{
|
||||
index->reverse_sort[i] = entry->reverse_sort[i];
|
||||
index->nulls_first[i] = entry->nulls_first[i];
|
||||
|
|
@ -1073,7 +1084,7 @@ hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
{
|
||||
if (entry->sortopfamily)
|
||||
{
|
||||
for (i = 0; i < ncolumns; i++)
|
||||
for (i = 0; i < nkeycolumns; i++)
|
||||
{
|
||||
index->sortopfamily[i] = entry->sortopfamily[i];
|
||||
index->reverse_sort[i] = entry->reverse_sort[i];
|
||||
|
|
@ -1290,7 +1301,7 @@ hypopg(PG_FUNCTION_ARGS)
|
|||
Datum
|
||||
hypopg_create_index(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *sql = TextDatumGetCString(PG_GETARG_TEXT_PP(0));
|
||||
char *sql = TextDatumGetCString(PG_GETARG_DATUM(0));
|
||||
List *parsetree_list;
|
||||
ListCell *parsetree_item;
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
|
|
@ -1387,6 +1398,7 @@ hypopg_relation_size(PG_FUNCTION_ARGS)
|
|||
double tuples;
|
||||
Oid indexid = PG_GETARG_OID(0);
|
||||
ListCell *lc;
|
||||
bool found = false;
|
||||
|
||||
pages = 0;
|
||||
tuples = 0;
|
||||
|
|
@ -1397,9 +1409,14 @@ hypopg_relation_size(PG_FUNCTION_ARGS)
|
|||
if (entry->oid == indexid)
|
||||
{
|
||||
hypo_estimate_index_simple(entry, &pages, &tuples);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
elog(ERROR, "oid %u is not a hypothetical index", indexid);
|
||||
|
||||
PG_RETURN_INT64(pages * 1.0L * BLCKSZ);
|
||||
}
|
||||
|
||||
|
|
@ -1419,8 +1436,7 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
hypoIndex *entry = NULL;
|
||||
ListCell *lc;
|
||||
List *context;
|
||||
int keyno,
|
||||
cpt = 0;
|
||||
int keyno;
|
||||
|
||||
foreach(lc, hypoIndexes)
|
||||
{
|
||||
|
|
@ -1491,8 +1507,6 @@ hypopg_get_indexdef(PG_FUNCTION_ARGS)
|
|||
|
||||
keycoltype = exprType(indexkey);
|
||||
keycolcollation = exprCollation(indexkey);
|
||||
|
||||
cpt++;
|
||||
}
|
||||
|
||||
/* Add collation, if not default for column */
|
||||
|
|
@ -1585,6 +1599,189 @@ hypopg_reset_index(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given oid for the list of hidden indexes
|
||||
* if it's a valid index (hypothetical or real), and if not hidden already.
|
||||
* Return true if the oid is added to the list, false otherwise.
|
||||
*/
|
||||
Datum
|
||||
hypopg_hide_index(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid indexid = PG_GETARG_OID(0);
|
||||
MemoryContext old_context;
|
||||
bool is_hypo = false;
|
||||
ListCell *lc;
|
||||
|
||||
/* first check if it is in hypoIndexes */
|
||||
foreach(lc, hypoIndexes)
|
||||
{
|
||||
hypoIndex *entry = (hypoIndex *) lfirst(lc);
|
||||
|
||||
if (entry->oid == indexid)
|
||||
{
|
||||
is_hypo = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_hypo)
|
||||
{
|
||||
HeapTuple index_tup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexid));
|
||||
|
||||
if (!HeapTupleIsValid(index_tup))
|
||||
return false;
|
||||
|
||||
ReleaseSysCache(index_tup);
|
||||
}
|
||||
|
||||
if (list_member_oid(hypoHiddenIndexes, indexid))
|
||||
return false;
|
||||
|
||||
old_context = MemoryContextSwitchTo(HypoMemoryContext);
|
||||
hypoHiddenIndexes = lappend_oid(hypoHiddenIndexes, indexid);
|
||||
MemoryContextSwitchTo(old_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unhide the given index oid (hypothetical or not) to make it visible to
|
||||
* the planner again.
|
||||
*/
|
||||
Datum
|
||||
hypopg_unhide_index(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid indexid = PG_GETARG_OID(0);
|
||||
|
||||
PG_RETURN_BOOL(hypo_index_unhide(indexid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore all hidden index.
|
||||
*/
|
||||
Datum
|
||||
hypopg_unhide_all_indexes(PG_FUNCTION_ARGS)
|
||||
{
|
||||
list_free(hypoHiddenIndexes);
|
||||
hypoHiddenIndexes = NIL;
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all hidden index oid.
|
||||
*/
|
||||
Datum
|
||||
hypopg_hidden_indexes(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
MemoryContext oldcontext;
|
||||
TupleDesc tupdesc;
|
||||
Tuplestorestate *tupstore;
|
||||
ListCell *lc;
|
||||
|
||||
/* check to see if caller supports us returning a tuplestore */
|
||||
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("set-valued function called in context that cannot accept a set")));
|
||||
if (!(rsinfo->allowedModes & SFRM_Materialize))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("materialize mode required, but it is not " \
|
||||
"allowed in this context")));
|
||||
|
||||
oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
|
||||
|
||||
tupdesc = CreateTemplateTupleDesc(1
|
||||
#if PG_VERSION_NUM < 120000
|
||||
, false
|
||||
#endif
|
||||
);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "indexid", OIDOID, -1, 0);
|
||||
|
||||
tupstore = tuplestore_begin_heap(true, false, work_mem);
|
||||
rsinfo->returnMode = SFRM_Materialize;
|
||||
rsinfo->setResult = tupstore;
|
||||
rsinfo->setDesc = tupdesc;
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
foreach(lc, hypoHiddenIndexes)
|
||||
{
|
||||
Oid indexid = lfirst_oid(lc);
|
||||
Datum values[HYPO_HIDDEN_INDEX_COLS];
|
||||
bool nulls[HYPO_HIDDEN_INDEX_COLS];
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(nulls, 0, sizeof(nulls));
|
||||
|
||||
values[0] = ObjectIdGetDatum(indexid);
|
||||
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
||||
}
|
||||
|
||||
/* clean up and return the tuplestore */
|
||||
tuplestore_donestoring(tupstore);
|
||||
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the oid to restore this index on EXPLAIN.
|
||||
*/
|
||||
bool
|
||||
hypo_index_unhide(Oid indexid)
|
||||
{
|
||||
int prev_length = list_length(hypoHiddenIndexes);
|
||||
|
||||
hypoHiddenIndexes = list_delete_oid(hypoHiddenIndexes, indexid);
|
||||
return prev_length > list_length(hypoHiddenIndexes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check rel and delete the same oid index as hypoHiddenIndexes
|
||||
* in rel->indexlist.
|
||||
*/
|
||||
void
|
||||
hypo_hideIndexes(RelOptInfo *rel)
|
||||
{
|
||||
ListCell *cell = NULL;
|
||||
|
||||
if (rel == NULL)
|
||||
return;
|
||||
|
||||
if (list_length(rel->indexlist) == 0 || list_length(hypoHiddenIndexes) == 0)
|
||||
return;
|
||||
|
||||
foreach(cell, hypoHiddenIndexes)
|
||||
{
|
||||
Oid oid = lfirst_oid(cell);
|
||||
ListCell *lc = NULL;
|
||||
|
||||
#if PG_VERSION_NUM >= 130000
|
||||
foreach(lc, rel->indexlist)
|
||||
{
|
||||
IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
|
||||
|
||||
if (index->indexoid == oid)
|
||||
rel->indexlist = foreach_delete_current(rel->indexlist, lc);
|
||||
}
|
||||
#else
|
||||
ListCell *next;
|
||||
ListCell *prev = NULL;
|
||||
|
||||
for (lc = list_head(rel->indexlist); lc != NULL; lc = next)
|
||||
{
|
||||
IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
|
||||
|
||||
next = lnext(lc);
|
||||
if (index->indexoid == oid)
|
||||
rel->indexlist = list_delete_cell(rel->indexlist, lc, prev);
|
||||
else
|
||||
prev = lc;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Simple function to set the indexname, dealing with max name length, and the
|
||||
* ending \0
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (c) 2008-2021, PostgreSQL Global Development Group
|
||||
* Copyright (c) 2008-2023, PostgreSQL Global Development Group
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (c) 2008-2021, PostgreSQL Global Development Group
|
||||
* Copyright (c) 2008-2023, PostgreSQL Global Development Group
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (C) 2015-2021: Julien Rouhaud
|
||||
* Copyright (C) 2015-2023: Julien Rouhaud
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (c) 2008-2021, PostgreSQL Global Development Group
|
||||
* Copyright (c) 2008-2023, PostgreSQL Global Development Group
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (c) 2008-2021, PostgreSQL Global Development Group
|
||||
* Copyright (c) 2008-2023, PostgreSQL Global Development Group
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* This program is open source, licensed under the PostgreSQL license.
|
||||
* For license terms, see the LICENSE file.
|
||||
*
|
||||
* Copyright (C) 2015-2021: Julien Rouhaud
|
||||
* Copyright (C) 2015-2023: Julien Rouhaud
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
#define HYPO_INDEX_NB_COLS 12 /* # of column hypopg() returns */
|
||||
#define HYPO_INDEX_CREATE_COLS 2 /* # of column hypopg_create_index()
|
||||
* returns */
|
||||
#define HYPO_HIDDEN_INDEX_COLS 1 /* # of column hypopg_hidden_indexes()
|
||||
* returns */
|
||||
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
/* hardcode some bloom values, bloom.h is not exported */
|
||||
|
|
@ -110,6 +112,9 @@ typedef struct hypoIndex
|
|||
/* List of hypothetic indexes for current backend */
|
||||
extern List *hypoIndexes;
|
||||
|
||||
/* List of hypothetical hidden existing indexes for current backend */
|
||||
extern List *hypoHiddenIndexes;
|
||||
|
||||
/*--- Functions --- */
|
||||
|
||||
void hypo_index_reset(void);
|
||||
|
|
@ -120,6 +125,10 @@ PGDLLEXPORT Datum hypopg_drop_index(PG_FUNCTION_ARGS);
|
|||
PGDLLEXPORT Datum hypopg_relation_size(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_get_indexdef(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_reset_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_hide_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_unhide_index(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_unhide_all_indexes(PG_FUNCTION_ARGS);
|
||||
PGDLLEXPORT Datum hypopg_hidden_indexes(PG_FUNCTION_ARGS);
|
||||
|
||||
extern explain_get_index_name_hook_type prev_explain_get_index_name_hook;
|
||||
hypoIndex *hypo_get_index(Oid indexId);
|
||||
|
|
@ -131,5 +140,6 @@ void hypo_injectHypotheticalIndex(PlannerInfo *root,
|
|||
RelOptInfo *rel,
|
||||
Relation relation,
|
||||
hypoIndex * entry);
|
||||
void hypo_hideIndexes(RelOptInfo *rel);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
100
test/sql/hypo_hide_index.sql
Normal file
100
test/sql/hypo_hide_index.sql
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
-- Hypothetically hiding existing indexes tests
|
||||
|
||||
-- Remove all the hypothetical indexes if any
|
||||
SELECT hypopg_reset();
|
||||
|
||||
-- The EXPLAIN initial state
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
|
||||
-- Create real index in hypo and use this index
|
||||
CREATE INDEX hypo_id_idx ON hypo(id);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
|
||||
-- Should be zero
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
|
||||
-- The hypo_id_idx index should not be used
|
||||
SELECT hypopg_hide_index('hypo_id_idx'::regclass);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
|
||||
-- Should be only one record
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Create the real index again and
|
||||
-- EXPLAIN should use this index instead of the previous one
|
||||
CREATE index hypo_id_val_idx ON hypo(id, val);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_val_idx';
|
||||
|
||||
-- Shouldn't use any index
|
||||
SELECT hypopg_hide_index('hypo_id_val_idx'::regclass);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_val_idx';
|
||||
|
||||
-- Should be two records
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Try to add one repeatedly or add another wrong index oid
|
||||
SELECT hypopg_hide_index('hypo_id_idx'::regclass);
|
||||
SELECT hypopg_hide_index('hypo'::regclass);
|
||||
SELECT hypopg_hide_index(0);
|
||||
|
||||
-- Also of course can be used to hide hypothetical indexes
|
||||
SELECT COUNT(*) FROM hypopg_create_index('create index on hypo(id,val);');
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
SELECT hypopg_hide_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
|
||||
-- Should be only three records
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Hypothetical indexes should be unhidden when deleting
|
||||
SELECT hypopg_drop_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
|
||||
-- Should become two records
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Hypopg_reset can also unhidden the hidden indexes
|
||||
-- due to the deletion of hypothetical indexes.
|
||||
SELECT COUNT(*) FROM hypopg_create_index('create index on hypo(id,val);');
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'Index.*<\d+>btree_hypo.*';
|
||||
SELECT hypopg_hide_index((SELECT indexrelid FROM hypopg_list_indexes LIMIT 1));
|
||||
|
||||
-- Changed from three records to two records.
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
SELECT hypopg_reset();
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Unhide an index
|
||||
SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
SELECT COUNT(*) FROM do_explain('SELECT * FROM hypo WHERE id = 1') e
|
||||
WHERE e ~ 'hypo_id_idx';
|
||||
|
||||
-- Should become one record
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Try to delete one repeatedly or delete another wrong index oid
|
||||
SELECT hypopg_unhide_index('hypo_id_idx'::regclass);
|
||||
SELECT hypopg_unhide_index('hypo'::regclass);
|
||||
SELECT hypopg_unhide_index(0);
|
||||
|
||||
-- Should still have one record
|
||||
SELECT table_name,index_name FROM hypopg_hidden_indexes;
|
||||
|
||||
-- Unhide all indexes
|
||||
SELECT hypopg_unhide_all_indexes();
|
||||
|
||||
-- Should change back to the original zero
|
||||
SELECT COUNT(*) FROM hypopg_hidden_indexes();
|
||||
|
||||
-- Clean real indexes and hypothetical indexes
|
||||
DROP INDEX hypo_id_idx;
|
||||
DROP INDEX hypo_id_val_idx;
|
||||
SELECT hypopg_reset();
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
-- Hypothetical on partitioned tables
|
||||
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- Hypothetical on partitioned tabled
|
||||
-- Hypothetical on partitioned tables
|
||||
|
||||
CREATE TABLE hypo_part(id1 integer, id2 integer, id3 integer)
|
||||
PARTITION BY LIST (id1);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ SELECT hypopg_relation_size(indexrelid) = current_setting('block_size')::bigint
|
|||
FROM hypopg()
|
||||
ORDER BY indexrelid;
|
||||
|
||||
-- Should detect invalid argument
|
||||
SELECT hypopg_relation_size(1);
|
||||
|
||||
-- locally disable hypoopg
|
||||
SET hypopg.enabled to false;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue