Skip to content

migrator: addColumnOptionsSpec DEFAULT-clause substring assertions fail on CockroachDB + Postgres #2661

@bpamiri

Description

@bpamiri

Describe the bug

wheels.tests.specs.migrator.addColumnOptionsSpec ("symmetric default handling for string-like types (F17)") asserts that generated SQL contains or omits a DEFAULT clause via exact-substring matching. The assertion fires on CockroachDB and Postgres on every engine — it's a portable test bug, not engine-specific.

Evidence

Compat-matrix run #25837380625 (2026-05-13).

17 occurrences total — 9 on BoxLang, 8 on Lucee 6, all on cockroachdb + postgres. Adobe/SQL Server/MySQL/SQLite pass.

Representative messages:

  • The needle [DEFAULT] was found in [DEFAULT '']
  • The needle [DEFAULT] was found in [ DEFAULT ]
  • The needle [DEFAULT] was not found in [ NULL] (MySQL — different shape)
  • The needle [DEFAULT 1] was not found in [ DEFAULT true] (PG — boolean serialization)

Root cause

Pure test problem. The spec asserts on raw generated SQL strings:

expect(sql).toInclude("DEFAULT ");           // brittle
expect(sql).toNotInclude("DEFAULT");          // brittle

But each DB adapter emits the same logical DEFAULT clause with slightly different surface syntax:

Adapter String column with default='' Boolean with default=true
MySQL DEFAULT NULL DEFAULT 1
Postgres DEFAULT '' DEFAULT true
CockroachDB DEFAULT '' (similar to PG)
SQL Server (no DEFAULT emitted) DEFAULT 1
SQLite (no DEFAULT emitted for empty string) (similar)

The spec was written against one engine's exact output and the substring match catches all of them.

Expected behavior

Either:

  1. The spec asserts on behavior (call the migrator, inspect the resulting schema via $dbinfo / native introspection), not on the SQL string — best long-term shape.
  2. The spec parameterizes the expected substring per DB adapter via an adapter-specific lookup table.

Suggested fix shape

Lowest-effort option: rewrite addColumnOptionsSpec assertions to use behavior-driven checks (does the column exist? does it have the expected default?). Or, if SQL-string assertions are intentional, add per-adapter expected-value tables.

Pure test edit — no framework changes. Will pass on every engine once fixed.

Additional context

  • Part of the Core test suite has high failure/error rate on BoxLang (35 failures, 125 errors, 3526 passing) #2649 decomposition (Tier 2). Cross-engine — these failures count against BoxLang's pass rate but the root cause is in the test spec, not engine compatibility.
  • General testing principle worth capturing in CLAUDE.md or .ai/wheels/testing/: don't assert on generated SQL strings from cross-engine adapters. The string is the wrong abstraction layer — assert on schema state or query results instead. The repo CLAUDE.md already documents many cross-engine SQL surface differences (boolean serialization, identifier quoting, etc.); this test should respect them.

Related: #2649

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions