Postern 0.3.0
- A documentation site at willibrandon.github.io/postern, which ExDoc builds from the README,
the changelog, the editor notes and the module docs, a workflow publishes from main, and
every pull request builds with warnings as errors. - The server installs from a Homebrew tap,
brew install willibrandon/tap/postern, from a
Scoop bucket,scoop install posternonce willibrandon's bucket is added, and with winget,
winget install willibrandon.postern, whose MSI puts it in Program Files and on the PATH.
Each release bumps the tap and the bucket and opens the winget pull request itself. An
action,willibrandon/postern@v0, fetches the release for the runner and runscheckwith
an annotation on every line the server would refuse, and a pre-commit hook in this repository
checks the four files before they are committed. - Every package can get the server without the releases page.
scripts/install.shand
scripts/install.ps1fetch the binary for the platform from a release, check it against the
checksums the release carries and put it on the path, and each release attaches them. The
Neovim plugin's:PosternInstalland the Emacs mode'spostgresql-conf-ts-mode-install-server
do the same into their editor's own directory and use the binary from then on,posternon
thePATHcoming first; the Helix and Fresh notes point at the script. The Neovim plugin is
also published on its own aswillibrandon/postern.nvim, which a plugin manager takes by name,
and a release pushes it there. - The server halts the moment its editor is gone, whichever way it goes. A write that
failed because the editor had closed its end of stdout took OTP's tty driver and the
userprocess down with it, so the read waiting on stdin was never answered and the
server ran until something killed it, which is also why the stdio test that closes the
pipe failed now and then in CI. The transport now watchesuserand halts the moment it
is gone, which is what a failed write comes to, and halts on a failed read as it does at
end of file. postern checktakes--pgfor the version to check against,--connection-stringor
--liveto compare the files with a running server the way the editor does, and
--stdin-filenameto read a file from stdin as if it stood at that path, which is how an
editor's linter framework hands over an unsaved buffer.--format githubwrites one
workflow command per diagnostic, which GitHub Actions turns into an annotation on the line,
--format sarifa run that code scanning shows on the pull request, and--strictexits 1
on a warning as well as an error. The JSON output carries each diagnostic's code.- A file the open document's tree reads while it is closed, one under
conf.dor the
postgresql.auto.confbeside the root, gets diagnostics of its own under its own name, as
pg_file_settings reports every file at once, so the editor's problem view shows the bad
value in the included file from the root, and clears it when no open document reads that
file any more. - A change on the disk to a file a check reads, an include, the
postgresql.auto.confthat
ALTER SYSTEM rewrites, or the file beside the open one, checks the open documents again:
the server asks a client that can watch files to report changes to any.conffile, and a
save checks the saved document and the ones that share its tree, with a fresh look at the
server when one is connected. - Quick fixes for what the checks already know: the closest catalog name or the name that
took a setting's place, a unit spelled the way the server takes it,128MBfor128mb, a
value quoted where the scanner refused it bare, and the line an override or an internal
setting makes useless removed or kept as a comment. Each is an edit rather than a command,
so it works in every client, and the server finds the fixes in the range itself for a
client that sends no diagnostics with its request. - Document symbols, so the outline, the breadcrumbs and the symbol picker have something to
show: postgresql.conf as the sections the sample marks with a line of dashes above and
below and the subsections it marks with a dash on either side, with the settings under
each and the value as the detail; pg_hba.conf as one symbol per rule, named by its fields
and detailed by its method; pg_ident.conf as one symbol per map with its mappings under it;
and an include as a symbol of its own. - A live diagnostic is placed on the document the server's rows describe, line by line, rather
than on any file with the same name: a postgresql.conf is the server's when every row of a
file has the document's setting and value on its line, and pg_hba.conf and pg_ident.conf
the same with their rules and maps. A file the server reads through a mount is found that
way, another cluster's file is not, and a document with unsaved edits above a line keeps
the offline diagnostics alone until it is saved. - The live code action writes one setting, the one under the cursor, with ALTER SYSTEM SET,
and its title is the statement, so it is read before it runs; what the server answered
comes back as a message the editor shows, with what applies the value in the words of the
setting's context, or the server's own refusal with its hint. Before, the action ran ALTER
SYSTEM SET for every assignment in the file and nothing showed the result. The reload
action reports the same way, and the action that returned a snapshot nothing displayed is
gone. map=on a pg_hba.conf rule and the map in pg_ident.conf are one name to the editor now: go
to definition goes from the option to the map's first line and from a map to it, find
references lists the lines that define the map and the rules that name it across both
trees, rename changes every one of them, and completion offers the map names aftermap=
and on a new pg_ident.conf line, a map named in pg_hba.conf but not yet defined among them.
With a live connection the third field of pg_ident.conf completes to the server's roles.- Hover on pg_hba.conf and pg_ident.conf, with the manual's own words for the target
version: what a connection type matches, what the database, user and address fields take,
what a method does and under which section the manual treats it, and what an option means
for its method; on pg_ident.conf, which field the token stands in and how the file is read.
The text comes from client-auth.sgml at each version's release branch, generated by
mix postern.docs --source ~/src/postgresintopriv/docs, under the PostgreSQL License. - A regular expression the server compiles when a file loads, a pg_ident.conf system user name
that starts with a slash on every version, and a pg_hba.conf database or user or a
pg_ident.conf PostgreSQL user name that does from 16, is compiled, and one the engine refuses
is the line's error on the token, in the engine's words:invalid regular expression "^(.*": parentheses () not balanced. The server's engine is not PCRE, so only what both refuse is
reported. - A database or user field of pg_hba.conf that starts with
@names a file of names, read
relative to the file the rule is in, separated by white space or commas, with comments and
nested files as the server reads them. The names stand in for the token, so a later rule
is weighed against the names that count, a file the server could not open is the rule's
error in the version's words, and the field links to the file. - The value checks are compared with a running server in CI, on every version from 13 to 18,
the way the include resolver already was. Each line of a fixture goes through ALTER SYSTEM
SET, which validates a value as the file does and answers with the words the log would
carry, and through a file the server's postgresql.conf includes, where pg_file_settings
says whether the server read the line, refused its value or refused the line; from 16 the
pg_hba.conf rules go through an included file the same way. The comparison found the list
syntax ofsearch_pathandtemp_tablespaces, which the file checks where SET quotes
the value as one name, and both are checked now. - What the postmaster refuses at start is reported before the restart, in the version's words:
wal_level = minimalwith WAL archiving on,max_wal_sendersabove zero, which it is by
default, orsummarize_walon, and more than one recovery target;track_counts
off with autovacuum on gets the warning autovacuum logs, with its hint. Each check weighs the
value that counts across the tree, or the default without one, and marks the last of the
lines in the file that take part. - A setting the target version does not have says what became of it, on the second line of
the server'sunrecognized configuration parametererror, which is what such a name is to
the server, since it refuses the whole file for one:It arrives in PostgreSQL 17.for
summarize_walon 13,PostgreSQL 16 replaced it with "debug_parallel_query".for
force_parallel_modeon 18,PostgreSQL 15 removed it.forstats_temp_directory, and for
names from before 13 that still turn up in copied files,checkpoint_segmentsor
wal_keep_segmentssay, the release that dropped each and the name that took its place. - The catalogs know the settings of the contrib modules and plpgsql, pg_stat_statements,
auto_explain, pg_prewarm, pg_trgm, auth_delay and, on the versions that have them,
postgres_fdw, basic_archive, basebackup_to_shell, isn, passwordcheck and pgcrypto, so
pg_stat_statements.max = 50is out of range the way any setting is, the hover names the
module, and completion offers the names. A placeholder under a module's prefix that the
module does not define gets the warning the server logs when the module loads, in the words
of the version. The catalog task loads each module before it selects, and the servers it
reads must be started with pg_stat_statements and pg_prewarm inshared_preload_libraries. - A string setting with a check hook is checked the way the hook checks it, in its words:
the DateStyle words and the two of them that may not disagree, the log destinations a
version has, the resource managerswal_consistency_checkingcan mask, the encodings and
their aliases, the time zone names the server knows and the POSIX specification a name can
fall back to, the recovery targets, and the grammar ofsynchronous_standby_names, with
syntax error at or near "b"where the server's parser would stop. The catalog carries the
server's time zone names and encodings for it, and completion offers them. What the server
checks only when it uses a value,shared_preload_librariesorprimary_conninfosay, is
taken as it is. - The spellings
pg_settingshides are taken:wal_level = archiveandhot_standbyfrom
beforereplicawas the name, andtrue,false,yes,no,1and0on the enum
settings that used to be booleans. The catalog task reads them from the enum tables in a
git checkout of PostgreSQL,mix postern.catalog --source ~/src/postgres, and records each
with the visible value it stands for, which the hover names; completion keeps offering the
visible values only. The hover's default is nowboot_val, what the server assumes without
a line for the setting, rather than whatever the catalog's server was running with. - The postgresql.conf checks say what the server logs, as the pg_hba.conf checks already
did:unrecognized configuration parameter "shared_buffrs", with the closest catalog name
on a second line the way the server phrases a hint, andinvalid value for parameter "wal_level": "nope"withAvailable values: minimal, replica, logical.below it. A line
the server cannot read is now scanned the way guc-file.l scans it, so it is refused on the
token the scanner stops at,syntax error near token "GB"forwork_mem = 1.5GB, since a
real takes no unit letters and the quotes are what make'1.5GB'a value, and a path, a
*or an unquoted"is refused where it stands. A quoted value takes the escapes the
server takes, andincludeis recognised in any case.postern checkprints a hint
indented under its message. - A setting with a dot in its name,
pg_stat_statements.maxsay, is no longer an unknown
setting. The server keeps such a value as a placeholder until the module that owns it loads
and checks it, and says nothing before then, so neither does Postern. - A setting with the internal context,
block_sizeordata_checksumssay, is an error on its
name in the server's words,parameter "block_size" cannot be changed, whatever its value.
The build, initdb or the server itself fixed it, which the hover now says, and completion no
longer offers it. - A number, its unit and a boolean are read the way guc.c reads them. A leading
0is octal
and0xis hex, solog_file_mode = 0600andunix_socket_permissions = 0777are the
values the manual gives rather than errors; a fraction rounds to the nearest integer; white
space may stand between the number and its unit; the unit is matched as written, so128mb
is refused with the server's hint naming the units the parameter takes; a fraction of a unit
rounds to a multiple of the next smaller one; and a boolean needs two letters ofonor
off, soois refused. A value out of range is reported in the server's words, in the
base unit and, from 17, with the unit on the bounds too. - An enum value with a space in it,
default_transaction_isolation = 'read committed'say, is
one of the values again. The catalog holds the array literalpg_settingsprints, in which
such a value is double-quoted, and the quotes were being compared as part of the value. The
literal is decoded when the catalog loads, so the check, the hover and completion all see the
bare value, and completion inserts a value that needs quoting in the file with its quotes.