PG.L9.DOC_MISSING_COMMENT — A table or column with no comment
- Category: convention
- Level: 9
- Confidence: deterministic
- Downtime class: none
- Stability: stable
- Suites: audit
- Applies to: PostgreSQL 18 and newer
What it checks
A table or column in the live schema carrying no comment — once the project has asked for one.
Reported:
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->string('reference');
});
Not reported:
Schema::create('invoices', function (Blueprint $table) {
$table->id()->comment('the surrogate key');
$table->string('reference')->comment('the number printed on the document');
})->comment('one issued invoice, immutable once sent');
Two opt-ins, and the second one is the point
Level 9 already keeps this out of an ordinary run. That is not its gate. A project that raised its level to see the pedantic band asked to be shown opinionated findings — not to be told, in the same breath, that every table it owns is undocumented.
// config/sqlens.php
'audit' => [
'documentation' => [
'require_table_comments' => true, // ships false
'require_column_comments' => false, // ships false
'exempt' => null, // null = the shipped framework list
],
],
The two switches are separate because they are different amounts of work. Documenting tables is something a team can finish; requiring the same of every column is a decision of its own, and one switch would have made the cheaper half unreachable.
The framework tables are exempt, and that is not a courtesy
Every Laravel application ships tables it did not write: migrations, jobs, job_batches,
failed_jobs, cache, cache_locks, sessions, password_reset_tokens,
personal_access_tokens, and Telescope's three. None will ever carry a comment and none should.
Without the exemption this rule reports double digits on a brand-new application — the fastest way to have it switched off along with everything near it.
Three details decide whether the exemption actually works:
- A column is judged by the exemption of the TABLE that owns it. Exempting
migrationsexemptsmigrations.batchtoo. Otherwise the table switch would be honored and the column switch would report the framework anyway, one level down — which reads exactly like the exemption not working. - Names are matched WHOLE. A project's own
job_applicationsis not the framework'sjobs, and a prefix match would exempt it. - A configured list REPLACES the shipped one rather than adding to it, so a team that names its own set is not silently still carrying ours.
Extension-owned objects need no exemption here: the catalog reader already filters them out of the object stream, and answering that question twice would be two answers to keep in step.
What "no comment" is on this engine
Measured on PostgreSQL 18.4: obj_description and col_description return NULL when there is
no comment, so the absent and the empty state do not need to be told apart here.
Its MySQL twin has two normalizations to make, and one of them would have been silent — see
MY.L9.DOC_MISSING_COMMENT.
Audit only
A migration's ->comment() becomes a separate COMMENT ON statement on PostgreSQL, so a lint run
could in principle see one. It still cannot answer the question: a lint run sees the pending
migrations, and a table documented two years ago carries its comment in the catalog and in no
pending migration. A lint half would report almost every table in the schema as undocumented — a
rule wrong on exactly the schemas it was written for.
Suppressing it
It is off unless you turned it on. If a subset is what you want, name it in
audit.documentation.exempt rather than switching the rule off — the exemption is the dial.
Sources
- PostgreSQL 18 — COMMENT — comments are stored per object, and setting one to NULL removes it
- PostgreSQL 18 — System information functions
—
obj_descriptionandcol_description, which is what the reader asks