Skip to content

Build plugin tables through createTableSql(), so optional columns get defaults - #23

Merged
mastacontrola merged 1 commit into
mainfrom
plugin-table-column-defaults
Aug 22, 2026
Merged

Build plugin tables through createTableSql(), so optional columns get defaults#23
mastacontrola merged 1 commit into
mainfrom
plugin-table-column-defaults

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Companion to fogproject #1275 (merged), which added the seam. GH-1245.

The problem

A column declared NOT NULL with no DEFAULT is only mandatory if something enforces it. For nine years nothing did — PDODB cleared sql_mode on every connection, so the server downgraded the error to a warning and substituted an implicit zero. Removing the clear turned every one of those declarations into a real constraint, and an INSERT that omits one now fails with error 1364.

FOG's schema step 348 repairs the tables an install already has. It cannot repair ours: createSql() runs as step 0 of each plugin's own schema(), so a plugin installed after the migration gets a table built the old way — every optional column mandatory again.

The change

FOGManagerController::createTableSql() takes the identical arguments and fills a default into every NOT NULL column that has none, leaving bare only:

  • the primary key and auto-increment column,
  • anything the model declares required,
  • anything whose name ends in ID — an INSERT that forgets the row it hangs off should fail, not make a silent orphan.

A default a manager passes explicitly always wins, so nothing already stated here changes. 25 call sites, one token each.

Verification

Against the live 1.6 install (prove_plugin_table_defaults_16.php in the fogproject scripts calls every manager's createSql(), creates the table under a scratch name, and reads the result back out of information_schema):

before after
tables built, DDL accepted 23/23 23/23
columns carrying a default 29 60
columns left bare 83 52

Each of the 52 is bare for one of the three stated reasons. Negative control — the wrapper filling nothing — puts 31 columns back to optional-and-still-mandatory.

WolbroadcastManager builds its table inside install() rather than createSql(), so the probe can't call it; its call site is switched the same way and is covered by the new test.

Tests

New tests/tables-carry-column-defaults.test.php — asserts no manager calls Schema::createTable() directly and every table-builder goes through the wrapper. It strips comments first, because two managers mention Schema::createTable() in prose explaining how it names its indexes. 49 checks; two mutations, two caught (a reverted manager, and a scan that reaches nothing).

The stub gains a pass-through createTableSql(). It deliberately does not reimplement the rule: the real one only adds defaults, so a pass-through cannot mask an assertion about a default a manager sets deliberately — which is exactly what oidc-provider-safety checks (opEnabled, opJITProvision, opAllowAPI must ship off) — and a copy of the rule would only give it somewhere to drift from.

Suite: 8/8.

Shipping

Needs a release, and then FOG_PLUGINS_VERSION bumped in fogproject to match. fogproject #1275 is already merged, so the seam is present on working-1.6.

🤖 Generated with Claude Code

… defaults

GH-1245. A column declared NOT NULL with no DEFAULT is only mandatory if
something enforces it, and for nine years nothing did: PDODB cleared sql_mode
on every connection, so the server downgraded the error to a warning and
substituted an implicit zero. Removing the clear turned every one of those
declarations into a real constraint, and an INSERT that omits one now fails
with error 1364.

FOG's schema step 348 repairs the tables an install already has. It cannot
repair ours: createSql() runs as step 0 of each plugin's own schema(), so a
plugin installed AFTER the migration gets a table built the old way -- every
optional column mandatory again.

FOGManagerController::createTableSql() (fogproject #1275) takes the identical
arguments and fills a default into every NOT NULL column that has none,
leaving bare only the primary key and auto-increment column, anything the
model declares required, and anything whose name ends in ID. A default a
manager passes explicitly always wins, so nothing stated here changes.

Measured against the live 1.6 install, across all 23 tables the probe can
build: 60 columns now carry a default where 29 did, and the 52 left bare are
each bare for one of those three stated reasons. Every CREATE TABLE is still
accepted by the server.

The test stub gains a pass-through createTableSql(). It deliberately does not
reimplement the rule: the real one only ADDS defaults, so a pass-through
cannot mask an assertion about a default a manager sets deliberately -- which
is what oidc-provider-safety checks -- and a copy of the rule would only give
it somewhere to drift from.

Requires fogproject FOG_PLUGINS_VERSION to be bumped to the release carrying
this, and that release requires #1275.

Co-Authored-By: Claude <noreply@anthropic.com>
@mastacontrola
mastacontrola merged commit bf9b18a into main Aug 22, 2026
2 checks passed
@mastacontrola
mastacontrola deleted the plugin-table-column-defaults branch August 22, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants