Skip to content

Integer length option renders the display width after NOT NULL #178

Description

@simon-mundy

Package Version

0.5.0 (also 0.6.x-dev @ e037464a and the 0.6.x head)

Php Version

8.4

Database Engine

MySQL

Basic Information

Integer.php#L18-L19 appends ' (' . $options['length'] . ')' to the spec string after Column::getExpressionData() has already added NOT NULL / DEFAULT, so the display width lands after the column attributes and MySQL rejects the statement. It is also the only attribute under Column/* that reaches SQL by string concatenation rather than as an Argument, so the option value goes out raw (Index prefix lengths do the same at Index.php#L53-L54; that one is covered by the literal-slots RFC, #181).

test/unit/Sql/Ddl/Column/IntegerTest.php lines 51-59 assert assertStringContainsString('(11)', $spec) (L58) and so pass on the broken output; lines 61-68 are the companion "excludes length when not set" test.

Steps to Reproduce

  1. $table = new CreateTable('x');
    $table->addColumn(new Column\Integer('i', false, null, ['length' => '11']));
  2. $table->getSqlString($mysqlPlatform) and execute it.

Expected Behavior

CREATE TABLE `x` (
    `i` INTEGER(11) NOT NULL
)

MySQL accepts this (with deprecation warning 1681 — display width is deprecated since 8.0.17).

I have a local fix (not pushed) that works, including BIGINT NULL DEFAULT '7':

  1. Spec becomes %s %s(%s) ..., value spliced at index 2 as a Literal built from an int (cast to string — Argument\Literal takes a string).
  2. Accept int for the option. setOption() is typed bool|string, so setOption('length', 11) is a TypeError under strict_types, while the constructor $options array and setOptions() take an int without complaint, and docs/book/sql-ddl/columns.md documents length as int. Widen setOption() to bool|int|string. Overlaps Untyped array boundaries (AbstractConnection::$connectionParameters, ColumnInterface::getOptions()) cause mixed-* fallout downstream #169.
  3. Document that MySQL deprecated integer display width in 8.0.17 and that the MySQL decorator will drop the attribute (phpdb-mysql#81); other platforms keep rendering it.

Test plan:

  • new Integer('i', false, null, ['length' => 11]) renders `i` INTEGER(11) NOT NULL; BigInteger/SmallInteger inherit the fix.
  • setOption('length', 11) is accepted.
  • IntegerTest asserts the full rendered string, not containment.
  • No Integer code path concatenates an option value into the spec.

Actual behavior?

CREATE TABLE `x` (
    `i` INTEGER NOT NULL (11)
)

MySQL 8.4.10 (reproduced on 8.0.46): ERROR 1064 ... near '(11)'.

Additional Info

Reproduced on 0.5.x, e037464a and the 0.6.x head. From an internal DDL audit (not published — the finding is reproduced above). Related: #169.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions