---
pg_extension_name: pg_readme
pg_extension_version: 0.5.3
pg_readme_generated_at: 2023-01-24 14:31:22.071904+00
pg_readme_version: 0.5.3
---
# The `pg_readme` PostgreSQL extension
The `pg_readme` PostgreSQL extension provides functions to generate
a `README.md` document for a database extension or schema, based on
[`COMMENT`](https://www.postgresql.org/docs/current/sql-comment.html) objects
found in the
[`pg_description`](https://www.postgresql.org/docs/current/catalog-pg-description.html)
system catalog.
## Usage
To use `pg_readme` in your extension, the most self-documenting way to do it is
to create a function that calls the `readme.pg_extension_readme(name)`
function. Here is an example take from the
[`pg_rowalesce`](https://github.com/bigsmoke/pg_rowalesce) extension:
```sql
create function pg_rowalesce_readme()
returns text
volatile
set search_path from current
set pg_readme.include_view_definitions to 'true'
set pg_readme.include_routine_definition_like to '{test__%}'
language plpgsql
as $plpgsql$
declare
_readme text;
begin
create extension if not exists pg_readme
with version '0.1.0';
_readme := pg_extension_readme('pg_rowalesce'::name);
raise transaction_rollback; -- to drop extension if we happened to `CREATE EXTENSION` for just this.
exception
when transaction_rollback then
return _readme;
end;
$plpgsql$;
```
In the above example, the `pg_readme.*` settings are (quite redundantly) set to
their default values. There is no need to add `pg_readme` to the list of
requirements in your extension's control file; after all, the extension is only
intermittently required, _by you_, when you need to update your extension's
`README.md`.
To make it easy (and self-documenting) to update the readme, add something like
the following recipe to the bottom of your extension's `Makefile`:
```sql
README.md: README.sql install
psql --quiet postgres < $< > $@
```
And turn the `README.sql` into something like this (again an example from `pg_rowalesce`):
```sql
\pset tuples_only
\pset format unaligned
begin;
create schema rowalesce;
create extension pg_rowalesce
with schema rowalesce
cascade;
select rowalesce.pg_rowalesce_readme();
rollback;
```
Now you can update your `README.md` by running:
```
make README.md
```
`COMMENT` (also on your extension), play with it, and never go back. And don't
forget to send me the pull requests for you enhancements.
## Markdown
The `pg_readme` author has made the choice for Markdown, not out of love for
Markdown, but out of practicality: Markdown, in all its neo-formal
interprations, has become ubiquitous. Also, it has a straight-forward
fall-through to (X)HTML. And we're not creating tech. books here (where TEI or
DocBook would have been the superior choice); we're merely generating
online/digital documentation on the basis of inline `COMMENT`s.
To make the pain of Markdown's many competing extensions and implementations
_somewhat_ bearable, `pg_readme` attempts to stick to those Markdown constructs
that are valid both according to:
* [GitHub Flavored Markdown](https://github.github.com/gfm/) (GFM), and
* [CommonMark](https://commonmark.org/).
“Attempts to”, because `pg_readme` relies heavily on MarkDown tables, which
_are_ supported by GFM, but _not_ by CommonMark.
## Processing instructions
`pg_readme` has support for a bunch of special XML processing instructions that
you can include in the Markdown `COMMENT ON EXTENSION` or `COMMENT ON SCHEMA`
objects:
* <?pg-readme-reference?>
will be replaced with a full
reference with all the objects found by `pg_readme` that belong to the
schema or extension (when
[`pg_schema_readme()`](#function-pg_schema_readme-regnamespace) or
[`pg_extension_readme()`](#function-pg_extension_readme-name) are run
respectively.
* <?pg-readme-colophon?>
adds a colophon with information
about `pg_readme` to the text.
The following pseudo-attributes are supported for these processing instructions:
| Pseudo-attribute | Coerced to | Default value |
| -------------------------- | ---------- | ------------------------------------ |
| `context-division-depth` | `smallint` | `1` |
| `context-division-is-self` | `boolean` | `false` |
| `division-title` | `text` | `'Object reference'` / `'Colophon'` |
(These attributes are called _pseudo-attributes_, because the XML spec does not
prescribe any particular structure for a processing instruction's content.
## Extension-specific settings
| Setting | Default |
| -------------------------------------------- | --------------------------------------------------------------- |
| `pg_readme.include_view_definitions` | `true` |
| `pg_readme.readme_url` | `'https://github.com/bigsmoke/pg_readme/blob/master/README.md'` |
| `pg_readme.include_routine_definitions_like` | `'{test__%}'` |
| `pg_readme.include_this_routine_definition` | `null` |
`pg_readme.include_this_routine_definition` is meant to be only used on a
routine-local level to make sure that the definition for that particular
routine is either _always_ or _never_ included in the reference, regardless of
the `pg_readme.include_routine_definitions_like` setting.
For `pg_readme` version 0.3.0, `pg_readme.include_routine_definitions` has been
deprecated in favor of `pg_readme.include_routine_definitions_like`, and
`pg_readme.include_routine_definitions` is now interpreted as:
| Legacy setting | Deduced setting |
| ----------------------------------------------- | --------------------------------------------------------------- |
| `pg_readme.include_routine_definitions is null` | `pg_readme.include_routine_definitions_like = array['test__%']` |
| `pg_readme.include_routine_definitions = true` | `pg_readme.include_routine_definitions_like = array['%']` |
| `pg_readme.include_routine_definitions = false` | `pg_readme.include_routine_definitions_like = array[]::text[]` |
## To-dos and to-maybes
### Missing features
* Table synopsis is not generated yet.
### Ideas for improvement
* Support for `` PI could be nice.
* Support for a `` PI in the `COMMENT` of specific
tables could be a nice addition for extensions/schemas that have type-type
tables.
* Automatically turning references to objects from other/builtin extensions or
schemas into links could be a plus. But this might also render the raw markup
unreadable. That, at least, would be a good argument against doing the same
for extension-local object references.
## The origins of the `pg_readme` extension
`pg_readme`, together with a decent number of other PostgreSQL extensions, was
developed as part of the backend for the super-scalable [FlashMQ MQTT SaaS
service](https://www.flashmq.com). Bundling and releasing this code publically
has:
- made the PostgreSQL schema architecture cleaner, with fewer
interdependencies;
- made the documentation more complete and up-to-date;
- increased the amount of polish; and
- reduced the number of rough edges.
The public gaze does improve quality!
## Object reference
### Routines
#### Function: `pg_extension_readme (name)`
`pg_extension_readme()` automatically generates a `README.md` for the given extension, taking the `COMMENT ON EXTENSION` as the prelude, and optionally adding a full reference (with neatly layed out object characteristics from the `pg_catalog`) in the place where a `<?pg-readme-reference?>` processing instruction is encountered in the `COMMENT ON EXTENSION'.
See the [_Processing instructions_](#processing-instructions) section for details about the processing instructions that are recognized and which pseudo-attributes they support.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | | `name` | |
Function return type: `text`
Function attributes: `STABLE`
Function-local settings:
* `SET search_path TO readme, public, pg_temp`
#### Function: `pg_readme_colophon (pg_readme_collection_type, name, smallint, boolean, text)`
`pg_readme_colophon()` is a function internal to `pg_readme` that is used by `pg_readme_pis_process()` to replace `<?pg-readme-colophon?>` processing instructions with a standard colophon indicating that `pg_readme` was used to generate a schema or extension README.
See the [_Processing instructions_](#processing-instructions) section for an overview of the processing instructions and their pseudo-attributes.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | `collection_type$` | `pg_readme_collection_type` | |
| `$2` | `IN` | `collection_name$` | `name` | |
| `$3` | `IN` | `context_division_depth$` | `smallint` | `1` |
| `$4` | `IN` | `context_division_is_self$` | `boolean` | `false` |
| `$5` | `IN` | `division_title$` | `text` | `'Colophon'::text` |
Function return type: `text`
Function attributes: `IMMUTABLE`, `LEAKPROOF`, `PARALLEL SAFE`
#### Function: `pg_readme_meta_pgxn()`
Returns the JSON meta data that has to go into the `META.json` file needed for [PGXN—PostgreSQL Extension Network](https://pgxn.org/) packages.
The `Makefile` includes a recipe to allow the developer to: `make META.json` to
refresh the meta file with the function's current output, including the
`default_version`.
Function return type: `jsonb`
Function attributes: `STABLE`
#### Function: `pg_readme_object_reference (pg_readme_objects_for_reference, pg_readme_collection_type, name, smallint, boolean, text)`
`pg_readme_object_reference()` is a function internal to `pg_readme` that is delegated to by `pg_readme_pis_process()` to replace `<?pg-readme-reference?>` processing instructions with a standard colophon indicating that `pg_readme` was used to generate a schema or extension README.
See the [_Processing instructions_](#processing-instructions) section for an overview of the processing instructions and their pseudo-attributes.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | `objects$` | `pg_readme_objects_for_reference` | |
| `$2` | `IN` | `collection_type$` | `pg_readme_collection_type` | |
| `$3` | `IN` | `collection_name$` | `name` | |
| `$4` | `IN` | `context_division_depth$` | `smallint` | `1` |
| `$5` | `IN` | `context_division_is_self$` | `boolean` | `false` |
| `$6` | `IN` | `division_title$` | `text` | `'Object reference'::text` |
Function return type: `text`
Function attributes: `STABLE`
Function-local settings:
* `SET search_path TO readme, public, pg_temp`
#### Function: `pg_readme_object_reference__rel_attr_list (pg_class)`
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | | `pg_class` | |
Function return type: `text`
Function attributes: `STABLE`
#### Function: `pg_readme_pi_pseudo_attrs (text, text)`
`pg_readme_pi_pseudo_attrs()` extracts the pseudo-attributes from the XML processing instruction with the given `pi_target$` found in the given`haystack$` argument.
See the `test__pg_readme_pi_pseudo_attrs()` procedure source for examples.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | `haystack$` | `text` | |
| `$2` | `IN` | `pi_target$` | `text` | |
Function return type: `hstore`
Function attributes: `IMMUTABLE`, `LEAKPROOF`, `RETURNS NULL ON NULL INPUT`, `PARALLEL SAFE`
#### Function: `pg_readme_pis_process (text, pg_readme_collection_type, name, pg_readme_objects_for_reference)`
`pg_readme_object_reference()` is a function internal to `pg_readme` that is responsible for replacing processing instructions in the source text with generated content.
See the [_Processing instructions_](#processing-instructions) section for an overview of the processing instructions and their pseudo-attributes.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | `unprocessed$` | `text` | |
| `$2` | `IN` | `collection_type$` | `pg_readme_collection_type` | |
| `$3` | `IN` | `collection_name$` | `name` | |
| `$4` | `IN` | `objects$` | `pg_readme_objects_for_reference` | |
Function return type: `text`
Function attributes: `STABLE`, `LEAKPROOF`, `RETURNS NULL ON NULL INPUT`, `PARALLEL SAFE`
Function-local settings:
* `SET search_path TO readme, public, pg_temp`
#### Function: `pg_schema_readme (regnamespace)`
`pg_schema_readme()` automatically generates a `README.md` for the given schema, taking the `COMMENT ON SCHEMA` as the prelude, and optionally adding a full reference (with neatly layed out object characteristics from the `pg_catalog`) in the place where a `<?pg-readme-reference?>` processing instruction is encountered in the `COMMENT ON SCHEMA'.
See the [_Processing instructions_](#processing-instructions) section for details about the processing instructions that are recognized and which pseudo-attributes they support.
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | | `regnamespace` | |
Function return type: `text`
Function attributes: `STABLE`
Function-local settings:
* `SET search_path TO readme, public, pg_temp`
#### Function: `string_diff (text, text)`
Function arguments:
| Arg. # | Arg. mode | Argument name | Argument type | Default expression |
| ------ | ---------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------- |
| `$1` | `IN` | | `text` | |
| `$2` | `IN` | | `text` | |
Function return type: `text`
Function attributes: `IMMUTABLE`, `LEAKPROOF`, `RETURNS NULL ON NULL INPUT`
#### Procedure: `test__pg_readme()`
This routine tests the `pg_readme` extension.
The routine name is compliant with the `pg_tst` extension. An intentional choice has been made to not _depend_ on the `pg_tst` extension its test runner or developer-friendly assertions to keep the number of inter-extension dependencies to a minimum.
Procedure-local settings:
* `SET search_path TO readme, public, pg_temp`
* `SET pg_readme.include_this_routine_definition TO false`
* `SET plpgsql.check_asserts TO true`
#### Procedure: `test__pg_readme_pi_pseudo_attrs()`
This routine tests the `pg_readme_pi_pseudo_attrs()` function.
The routine name is compliant with the `pg_tst` extension. An intentional choice has been made to not _depend_ on the `pg_tst` extension its test runner or developer-friendly assertions to keep the number of inter-extension dependencies to a minimum.
Procedure-local settings:
* `SET search_path TO readme, public, pg_temp`
```sql
CREATE OR REPLACE PROCEDURE readme.test__pg_readme_pi_pseudo_attrs()
LANGUAGE plpgsql
SET search_path TO 'readme', 'public', 'pg_temp'
AS $procedure$
begin
assert pg_readme_pi_pseudo_attrs(
'',
'muizen-stapje'
) = hstore('soort=>woelmuis, hem-of-haar=>piep, a1=>4');
assert pg_readme_pi_pseudo_attrs(
'Blabla bla Frotsepots',
'muizen-stapje'
) = hstore('soort=>woelmuis, hem-of-haar=>piep');
assert pg_readme_pi_pseudo_attrs(
'Blabla bla Frotsepots',
'muizen-stapje'
) is null;
end;
$procedure$
```
### Types
The following extra types have been defined _besides_ the implicit composite types of the [tables](#tables) and [views](#views) in this extension.
#### Composite type: `pg_readme_objects_for_reference`
```sql
CREATE TYPE pg_readme_objects_for_reference AS (
table_objects regclass[],
view_objects regclass[],
procedure_objects regprocedure[],
operator_objects regoperator[],
type_objects regtype[]
);
```
#### Domain: `pg_readme_collection_type`
```sql
CREATE DOMAIN pg_readme_collection_type AS text
CHECK ((VALUE = ANY (ARRAY['extension'::text, 'schema'::text])));
```
## Colophon
This `README.md` for the `pg_readme` extension was automatically generated using the [`pg_readme`](https://github.com/bigsmoke/pg_readme) PostgreSQL extension.