Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new extensions/plugins #294

Merged
merged 2 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,98 @@ options:
default: false
type: boolean
description: Enable unaccent extension.
plugin_bloom_enable:
default: false
type: boolean
description: Enable bloom extension.
plugin_btree_gin_enable:
default: false
type: boolean
description: Enable btree_gin extension.
plugin_btree_gist_enable:
default: false
type: boolean
description: Enable btree_gist extension.
plugin_cube_enable:
default: false
type: boolean
description: Enable cube extension.
plugin_dict_int_enable:
default: false
type: boolean
description: Enable dict_int extension.
plugin_dict_xsyn_enable:
default: false
type: boolean
description: Enable dict_xsyn extension.
plugin_earthdistance_enable:
default: false
type: boolean
description: Enable earthdistance extension.
plugin_fuzzystrmatch_enable:
default: false
type: boolean
description: Enable fuzzystrmatch extension.
plugin_intarray_enable:
default: false
type: boolean
description: Enable intarray extension.
plugin_isn_enable:
default: false
type: boolean
description: Enable isn extension.
plugin_lo_enable:
default: false
type: boolean
description: Enable lo extension.
plugin_ltree_enable:
default: false
type: boolean
description: Enable ltree extension.
plugin_old_snapshot_enable:
default: false
type: boolean
description: Enable old_snapshot extension.
plugin_pg_freespacemap_enable:
default: false
type: boolean
description: Enable pg_freespacemap extension.
plugin_pgrowlocks_enable:
default: false
type: boolean
description: Enable pgrowlocks extension.
plugin_pgstattuple_enable:
default: false
type: boolean
description: Enable pgstattuple extension.
plugin_pg_visibility_enable:
default: false
type: boolean
description: Enable pg_visibility extension.
plugin_seg_enable:
default: false
type: boolean
description: Enable seg extension.
plugin_tablefunc_enable:
default: false
type: boolean
description: Enable tablefunc extension.
plugin_tcn_enable:
default: false
type: boolean
description: Enable tcn extension.
plugin_tsm_system_rows_enable:
default: false
type: boolean
description: Enable tsm_system_rows extension.
plugin_tsm_system_time_enable:
default: false
type: boolean
description: Enable tsm_system_time extension.
plugin_uuid_ossp_enable:
default: false
type: boolean
description: Enable uuid_ossp extension.
TakoB222 marked this conversation as resolved.
Show resolved Hide resolved
profile:
description: |
Profile representing the scope of deployment, and used to tune resource allocation.
Expand Down
4 changes: 4 additions & 0 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,14 @@ def enable_disable_extensions(self, database: str = None) -> None:
database: optional database where to enable/disable the extension.
"""
original_status = self.unit.status
plugins_exception = {"uuid_ossp": '"uuid-ossp"'}
for plugin in self.config.plugin_keys():
enable = self.config[plugin]

# Enable or disable the plugin/extension.
extension = "_".join(plugin.split("_")[1:-1])
if extension in plugins_exception:
extension = plugins_exception[extension]
self.unit.status = WaitingStatus(
f"{'Enabling' if enable else 'Disabling'} {extension}"
)
Expand Down
23 changes: 23 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ class CharmConfig(BaseConfigModel):
plugin_pg_trgm_enable: bool
plugin_plpython3u_enable: bool
plugin_unaccent_enable: bool
plugin_bloom_enable: bool
plugin_btree_gin_enable: bool
plugin_btree_gist_enable: bool
plugin_cube_enable: bool
plugin_dict_int_enable: bool
plugin_dict_xsyn_enable: bool
plugin_earthdistance_enable: bool
plugin_fuzzystrmatch_enable: bool
plugin_intarray_enable: bool
plugin_isn_enable: bool
plugin_lo_enable: bool
plugin_ltree_enable: bool
plugin_old_snapshot_enable: bool
plugin_pg_freespacemap_enable: bool
plugin_pgrowlocks_enable: bool
plugin_pgstattuple_enable: bool
plugin_pg_visibility_enable: bool
plugin_seg_enable: bool
plugin_tablefunc_enable: bool
plugin_tcn_enable: bool
plugin_tsm_system_rows_enable: bool
plugin_tsm_system_time_enable: bool
plugin_uuid_ossp_enable: bool
request_date_style: Optional[str]
request_standard_conforming_strings: Optional[bool]
request_time_zone: Optional[str]
Expand Down
129 changes: 79 additions & 50 deletions tests/integration/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,35 @@
PG_TRGM_EXTENSION_STATEMENT = "SELECT word_similarity('word', 'two words');"
PLPYTHON3U_EXTENSION_STATEMENT = 'CREATE FUNCTION plpython_test() RETURNS varchar[] AS $$ return "hello" $$ LANGUAGE plpython3u;'
UNACCENT_EXTENSION_STATEMENT = "SELECT ts_lexize('unaccent','Hôtel');"
BLOOM_EXTENSION_STATEMENT = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add those in a plugin: SQL test dictionary and then loop over .keys() in the config definition on L#192 and over .values() in the checks on L#74 and L#232.

"CREATE TABLE tbloom_test (i int);CREATE INDEX btreeidx ON tbloom_test USING bloom (i);"
)
BTREEGIN_EXTENSION_STATEMENT = "CREATE TABLE btree_gin_test (a int4);CREATE INDEX btreeginidx ON btree_gin_test USING GIN (a);"
BTREEGIST_EXTENSION_STATEMENT = "CREATE TABLE btree_gist_test (a int4);CREATE INDEX btreegistidx ON btree_gist_test USING GIST (a);"
CUBE_EXTENSION_STATEMENT = "SELECT cube_inter('(0,-1),(1,1)', '(-2),(2)');"
DICTINT_EXTENSION_STATEMENT = "SELECT ts_lexize('intdict', '12345678');"
DICTXSYN_EXTENSION_STATEMENT = "SELECT ts_lexize('xsyn', 'word');"
EARTHDISTANCE_EXTENSION_STATEMENT = "SELECT earth_distance(ll_to_earth(-81.3927381, 30.2918842),ll_to_earth(-87.6473133, 41.8853881));"
FUZZYSTRMATCH_EXTENSION_STATEMENT = "SELECT soundex('hello world!');"
INTARRAY_EXTENSION_STATEMENT = "CREATE TABLE intarray_test (mid INT PRIMARY KEY, sections INT[]);SELECT intarray_test.mid FROM intarray_test WHERE intarray_test.sections @> '{1,2}';"
ISN_EXTENSION_STATEMENT = "SELECT isbn('978-0-393-04002-9');"
LO_EXTENSION_STATEMENT = "CREATE TABLE lo_test (value lo);"
LTREE_EXTENSION_STATEMENT = "CREATE TABLE ltree_test (path ltree);"
OLD_SNAPSHOT_EXTENSION_STATEMENT = "SELECT * from pg_old_snapshot_time_mapping();"
PG_FREESPACEMAP_EXTENSION_STATEMENT = (
"CREATE TABLE pg_freespacemap_test (i int);SELECT * FROM pg_freespace('pg_freespacemap_test');"
)
PGROWLOCKS_EXTENSION_STATEMENT = (
"CREATE TABLE pgrowlocks_test (i int);SELECT * FROM pgrowlocks('pgrowlocks_test');"
)
PGSTATTUPLE_EXTENSION_STATEMENT = "SELECT * FROM pgstattuple('pg_catalog.pg_proc');"
PG_VISIBILITY_EXTENSION_STATEMENT = "CREATE TABLE pg_visibility_test (i int);SELECT * FROM pg_visibility('pg_visibility_test'::regclass);"
SEG_EXTENSION_STATEMENT = "SELECT '10(+-)1'::seg as seg;"
TABLEFUNC_EXTENSION_STATEMENT = "SELECT * FROM normal_rand(1000, 5, 3);"
TCN_EXTENSION_STATEMENT = "CREATE TABLE tcn_test (i int);CREATE TRIGGER tcn_test_idx AFTER INSERT OR UPDATE OR DELETE ON tcn_test FOR EACH ROW EXECUTE FUNCTION TRIGGERED_CHANGE_NOTIFICATION();"
TSM_SYSTEM_ROWS_EXTENSION_STATEMENT = "CREATE TABLE tsm_system_rows_test (i int);SELECT * FROM tsm_system_rows_test TABLESAMPLE SYSTEM_ROWS(100);"
TSM_SYSTEM_TIME_EXTENSION_STATEMENT = "CREATE TABLE tsm_system_time_test (i int);SELECT * FROM tsm_system_time_test TABLESAMPLE SYSTEM_TIME(1000);"
UUID_OSSP_EXTENSION_STATEMENT = "SELECT uuid_nil();"


@pytest.mark.abort_on_fail
Expand All @@ -33,72 +62,72 @@ async def test_plugins(ops_test: OpsTest) -> None:
async with ops_test.fast_forward():
await build_and_deploy(ops_test, 2)

sql_tests = {
"plugin_citext_enable": CITEXT_EXTENSION_STATEMENT,
"plugin_debversion_enable": DEBVERSION_EXTENSION_STATEMENT,
"plugin_hstore_enable": HSTORE_EXTENSION_STATEMENT,
"plugin_pg_trgm_enable": PG_TRGM_EXTENSION_STATEMENT,
"plugin_plpython3u_enable": PLPYTHON3U_EXTENSION_STATEMENT,
"plugin_unaccent_enable": UNACCENT_EXTENSION_STATEMENT,
"plugin_bloom_enable": BLOOM_EXTENSION_STATEMENT,
"plugin_btree_gin_enable": BTREEGIN_EXTENSION_STATEMENT,
"plugin_btree_gist_enable": BTREEGIST_EXTENSION_STATEMENT,
"plugin_cube_enable": CUBE_EXTENSION_STATEMENT,
"plugin_dict_int_enable": DICTINT_EXTENSION_STATEMENT,
"plugin_dict_xsyn_enable": DICTXSYN_EXTENSION_STATEMENT,
"plugin_earthdistance_enable": EARTHDISTANCE_EXTENSION_STATEMENT,
"plugin_fuzzystrmatch_enable": FUZZYSTRMATCH_EXTENSION_STATEMENT,
"plugin_intarray_enable": INTARRAY_EXTENSION_STATEMENT,
"plugin_isn_enable": ISN_EXTENSION_STATEMENT,
"plugin_lo_enable": LO_EXTENSION_STATEMENT,
"plugin_ltree_enable": LTREE_EXTENSION_STATEMENT,
"plugin_old_snapshot_enable": OLD_SNAPSHOT_EXTENSION_STATEMENT,
"plugin_pg_freespacemap_enable": PG_FREESPACEMAP_EXTENSION_STATEMENT,
"plugin_pgrowlocks_enable": PGROWLOCKS_EXTENSION_STATEMENT,
"plugin_pgstattuple_enable": PGSTATTUPLE_EXTENSION_STATEMENT,
"plugin_pg_visibility_enable": PG_VISIBILITY_EXTENSION_STATEMENT,
"plugin_seg_enable": SEG_EXTENSION_STATEMENT,
"plugin_tablefunc_enable": TABLEFUNC_EXTENSION_STATEMENT,
"plugin_tcn_enable": TCN_EXTENSION_STATEMENT,
"plugin_tsm_system_rows_enable": TSM_SYSTEM_ROWS_EXTENSION_STATEMENT,
"plugin_tsm_system_time_enable": TSM_SYSTEM_TIME_EXTENSION_STATEMENT,
"plugin_uuid_ossp_enable": UUID_OSSP_EXTENSION_STATEMENT,
}

def enable_disable_config(enabled: False):
config = {}
for plugin in sql_tests.keys():
config[plugin] = f"{enabled}"
return config

# Check that the available plugins are disabled.
primary = await get_primary(ops_test)
password = await get_password(ops_test)
address = await get_unit_address(ops_test, primary)

config = enable_disable_config(False)
await ops_test.model.applications[DATABASE_APP_NAME].set_config(config)
await ops_test.model.wait_for_idle(apps=[DATABASE_APP_NAME], status="active")

logger.info("checking that the plugins are disabled")
with db_connect(host=address, password=password) as connection:
connection.autocommit = True

# Test citext extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(CITEXT_EXTENSION_STATEMENT)

# Test debversion extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(DEBVERSION_EXTENSION_STATEMENT)

# Test hstore extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(HSTORE_EXTENSION_STATEMENT)

# Test pg_trgm extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(PG_TRGM_EXTENSION_STATEMENT)

# Test PL/Python extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(PLPYTHON3U_EXTENSION_STATEMENT)

# Test unaccent extension disabled.
with pytest.raises(psycopg2.Error):
connection.cursor().execute(UNACCENT_EXTENSION_STATEMENT)
for query in sql_tests.values():
with pytest.raises(psycopg2.Error):
connection.cursor().execute(query)
connection.close()

# Enable the plugins.
logger.info("enabling the plugins")
config = {
"plugin_citext_enable": "True",
"plugin_debversion_enable": "True",
"plugin_hstore_enable": "True",
"plugin_pg_trgm_enable": "True",
"plugin_plpython3u_enable": "True",
"plugin_unaccent_enable": "True",
}

config = enable_disable_config(True)
await ops_test.model.applications[DATABASE_APP_NAME].set_config(config)
await ops_test.model.wait_for_idle(apps=[DATABASE_APP_NAME], status="active")

# Check that the available plugins are enabled.
logger.info("checking that the plugins are enabled")
with db_connect(host=address, password=password) as connection:
connection.autocommit = True

# Test citext extension enabled.
connection.cursor().execute(CITEXT_EXTENSION_STATEMENT)

# Test debversion extension enabled.
connection.cursor().execute(DEBVERSION_EXTENSION_STATEMENT)

# Test hstore extension enabled.
connection.cursor().execute(HSTORE_EXTENSION_STATEMENT)

# Test pg_trgm extension enabled.
connection.cursor().execute(PG_TRGM_EXTENSION_STATEMENT)

# Test PL/Python extension enabled.
connection.cursor().execute(PLPYTHON3U_EXTENSION_STATEMENT)

# Test unaccent extension enabled.
connection.cursor().execute(UNACCENT_EXTENSION_STATEMENT)
for query in sql_tests.values():
connection.cursor().execute(query)
connection.close()
Loading