Skip to main content

MY.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: MySQL 8.4 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 migrations exempts migrations.batch too. 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_applications is not the framework's jobs, 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 — two traps

Measured on MySQL 8.4.10:

SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES;
no_c -> '' -- the empty string, where PostgreSQL returns NULL
v -> 'VIEW' -- the SERVER puts that there. Nobody wrote it.
with_c -> 'documented'

The reader normalizes both to "no comment". The second is the one that would have been silent: a rule reading VIEW as documentation reports every view in every MySQL schema as documented, in the direction nobody checks.

Audit only

MySQL puts a comment inline in the CREATE TABLE, so a lint run could read one off the statement that creates a table. It still cannot answer the question, for the same reason as its PostgreSQL sibling: 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.

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

Not transferable to MariaDB. Its information_schema shapes are its own, and this package targets MySQL 8.4 semantics — advice derived from them and applied elsewhere would be confident, specific and about another product.