Skip to content

Commit

Permalink
DPE-2764 Add new extensions/plugins (#251)
Browse files Browse the repository at this point in the history
* Add new extensions/plugins

* fix tests
  • Loading branch information
TakoB222 authored Nov 21, 2023
1 parent c672b6e commit 199e53b
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 54 deletions.
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
profile:
description: |
Profile representing the scope of deployment, and used to tune resource allocation.
Expand Down
3 changes: 3 additions & 0 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,13 +948,16 @@ 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"'}
extensions = {}
# collect extensions
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]
extensions[extension] = enable
self.unit.status = WaitingStatus("Updating extensions")
try:
Expand Down
23 changes: 23 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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 = (
"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 @@ -40,72 +69,72 @@ async def test_plugins(ops_test: OpsTest) -> None:
)
await ops_test.model.wait_for_idle(apps=[DATABASE_APP_NAME], status="active", timeout=1000)

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, f"{DATABASE_APP_NAME}/0")
password = await get_password(ops_test, primary)
address = 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()
77 changes: 73 additions & 4 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,81 @@ def test_enable_disable_extensions(self, _):
plugin_unaccent_enable:
default: false
type: boolean
profile:
default: production
type: string
plugin_debversion_enable:
default: false
type: boolean"""
type: boolean
plugin_bloom_enable:
default: false
type: boolean
plugin_btree_gin_enable:
default: false
type: boolean
plugin_btree_gist_enable:
default: false
type: boolean
plugin_cube_enable:
default: false
type: boolean
plugin_dict_int_enable:
default: false
type: boolean
plugin_dict_xsyn_enable:
default: false
type: boolean
plugin_earthdistance_enable:
default: false
type: boolean
plugin_fuzzystrmatch_enable:
default: false
type: boolean
plugin_intarray_enable:
default: false
type: boolean
plugin_isn_enable:
default: false
type: boolean
plugin_lo_enable:
default: false
type: boolean
plugin_ltree_enable:
default: false
type: boolean
plugin_old_snapshot_enable:
default: false
type: boolean
plugin_pg_freespacemap_enable:
default: false
type: boolean
plugin_pgrowlocks_enable:
default: false
type: boolean
plugin_pgstattuple_enable:
default: false
type: boolean
plugin_pg_visibility_enable:
default: false
type: boolean
plugin_seg_enable:
default: false
type: boolean
plugin_tablefunc_enable:
default: false
type: boolean
plugin_tcn_enable:
default: false
type: boolean
plugin_tsm_system_rows_enable:
default: false
type: boolean
plugin_tsm_system_time_enable:
default: false
type: boolean
plugin_uuid_ossp_enable:
default: false
type: boolean
profile:
default: production
type: string"""
harness = Harness(PostgresqlOperatorCharm, config=config)
self.addCleanup(harness.cleanup)
harness.begin()
Expand Down

0 comments on commit 199e53b

Please sign in to comment.