diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index fc81133f07..1714fd6b08 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -8228,6 +8228,11 @@ SCRAM-SHA-256$<iteration count>:&l time zone names + + pg_ts_shared_dictionaries + dictionaries currently in shared memory + + pg_user database users @@ -10983,6 +10988,63 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + <structname>pg_ts_shared_dictionaries</structname> + + + pg_ts_shared_dictionaries + + + + The pg_ts_shared_dictionaries view provides a + listing of all text search dictionaries that currently allocated in the + shared memory. The size of available space in shared memory is controlled by + . A dictionary may have an option which + controls allocation in shared memory (see ). + + + + <structname>pg_ts_shared_dictionaries</structname> Columns + + + + + Name + Type + References + Description + + + + + dictoid + oid + pg_ts_dict.oid + The OID of the text search dictionary located in shared memory + + + schemaname + name + pg_namespace.nspname + The name of schema containing the text search dictionary + + + dictname + name + pg_ts_dict.dictname + The text search dictionary name + + + size + bigint + + Size of the text search dictionary in bytes + + + +
+
+ <structname>pg_user</structname> diff --git a/doc/src/sgml/textsearch.sgml b/doc/src/sgml/textsearch.sgml index f3288fbb3f..02e8e8aa90 100644 --- a/doc/src/sgml/textsearch.sgml +++ b/doc/src/sgml/textsearch.sgml @@ -3047,6 +3047,12 @@ CREATE TEXT SEARCH DICTIONARY english_stem ( parameter to a value greater than zero or to a value -1. + + List of dictionaries currently located in shared memory can be retreived by + pg_ts_shared_dictionaries + view. + + diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 5e6e8a64f6..ab7ee973d9 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -506,6 +506,9 @@ CREATE VIEW pg_config AS REVOKE ALL on pg_config FROM PUBLIC; REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC; +CREATE VIEW pg_ts_shared_dictionaries AS + SELECT * FROM pg_ts_shared_dictionaries(); + -- Statistics views CREATE VIEW pg_stat_all_tables AS diff --git a/src/backend/tsearch/ts_shared.c b/src/backend/tsearch/ts_shared.c index 2a8b80bce8..fe632ecf6f 100644 --- a/src/backend/tsearch/ts_shared.c +++ b/src/backend/tsearch/ts_shared.c @@ -13,11 +13,18 @@ */ #include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" + +#include "access/htup_details.h" +#include "catalog/pg_ts_dict.h" #include "lib/dshash.h" #include "storage/lwlock.h" #include "storage/shmem.h" #include "tsearch/ts_shared.h" +#include "utils/builtins.h" #include "utils/hashutils.h" +#include "utils/lsyscache.h" #include "utils/memutils.h" @@ -377,3 +384,100 @@ recheck_table: MemoryContextSwitchTo(old_context); } + +/* + * pg_ts_shared_dictionaries - SQL SRF showing dictionaries currently in + * shared memory. + */ +Datum +pg_ts_shared_dictionaries(PG_FUNCTION_ARGS) +{ + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + MemoryContext oldcontext; + TupleDesc tupdesc; + Tuplestorestate *tupstore; + Relation rel; + HeapTuple tuple; + SysScanDesc scan; + + /* 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"))); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + /* Build tuplestore to hold the result rows */ + oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory); + + tupstore = tuplestore_begin_heap(true, false, work_mem); + rsinfo->returnMode = SFRM_Materialize; + rsinfo->setResult = tupstore; + rsinfo->setDesc = tupdesc; + + MemoryContextSwitchTo(oldcontext); + + init_dict_table(); + + /* + * If a hash table wasn't created return zero records. + */ + if (!DsaPointerIsValid(tsearch_ctl->dict_table_handle)) + { + tuplestore_donestoring(tupstore); + + PG_RETURN_VOID(); + } + + /* Start to scan pg_ts_dict */ + rel = heap_open(TSDictionaryRelationId, AccessShareLock); + scan = systable_beginscan(rel, InvalidOid, false, NULL, 0, NULL); + + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Datum values[4]; + bool nulls[4]; + Form_pg_ts_dict dict = (Form_pg_ts_dict) GETSTRUCT(tuple); + Oid dictid = HeapTupleGetOid(tuple); + TsearchDictEntry *entry; + NameData dict_name; + + /* If dictionary isn't located in shared memory try following */ + entry = (TsearchDictEntry *) dshash_find(dict_table, &dictid, false); + if (!entry) + continue; + + namecpy(&dict_name, &dict->dictname); + + memset(nulls, 0, sizeof(nulls)); + + values[0] = ObjectIdGetDatum(dictid); + + if (OidIsValid(dict->dictnamespace)) + values[1] = CStringGetDatum(get_namespace_name(dict->dictnamespace)); + else + nulls[1] = true; + + values[2] = NameGetDatum(&dict_name); + values[3] = Int64GetDatum(entry->dict_size); + + dshash_release_lock(dict_table, entry); + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } + + systable_endscan(scan); + heap_close(rel, AccessShareLock); + + tuplestore_donestoring(tupstore); + + PG_RETURN_VOID(); +} diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index bfc90098f8..6cd60f7110 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -4975,6 +4975,9 @@ DESCR("trigger for automatic update of tsvector column"); DATA(insert OID = 3759 ( get_current_ts_config PGNSP PGUID 12 1 0 0 0 f f f t f s s 0 0 3734 "" _null_ _null_ _null_ _null_ _null_ get_current_ts_config _null_ _null_ _null_ )); DESCR("get current tsearch configuration"); +DATA(insert OID = 4213 ( pg_ts_shared_dictionaries PGNSP PGUID 12 1 10 0 0 f f f f t s s 0 0 2249 "" "{26,19,19,20}" "{o,o,o,o}" "{dictoid,schemaname,dictname,size}" _null_ _null_ pg_ts_shared_dictionaries _null_ _null_ _null_ )); +DESCR("information about text search dictionaries currently in shared memory"); + DATA(insert OID = 3736 ( regconfigin PGNSP PGUID 12 1 0 0 0 f f f t f s s 1 0 3734 "2275" _null_ _null_ _null_ _null_ _null_ regconfigin _null_ _null_ _null_ )); DESCR("I/O"); DATA(insert OID = 3737 ( regconfigout PGNSP PGUID 12 1 0 0 0 f f f t f s s 1 0 2275 "3734" _null_ _null_ _null_ _null_ _null_ regconfigout _null_ _null_ _null_ )); diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 5149b72fe9..7e61b46419 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2211,6 +2211,11 @@ pg_timezone_names| SELECT pg_timezone_names.name, pg_timezone_names.utc_offset, pg_timezone_names.is_dst FROM pg_timezone_names() pg_timezone_names(name, abbrev, utc_offset, is_dst); +pg_ts_shared_dictionaries| SELECT pg_ts_shared_dictionaries.dictoid, + pg_ts_shared_dictionaries.schemaname, + pg_ts_shared_dictionaries.dictname, + pg_ts_shared_dictionaries.size + FROM pg_ts_shared_dictionaries() pg_ts_shared_dictionaries(dictoid, schemaname, dictname, size); pg_user| SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb,