Skip to content

--statement rewrites column default expression without parentheses #542

@kolbe

Description

@kolbe

Using --statement instead of --table and --alter requires that Spirit parse and reconstruct the statement. In some cases, the reconstructed statement can omit parentheses for a column default value expression, which can cause errors.

CREATE TABLE `t1` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
)
go run ./cmd/spirit/ --username=root --password= --database=test --statement="alter table t1 add column j json default ('{}')"
2025/12/18 14:28:02 INFO Starting spirit migration concurrency=4 target-chunk-size=500ms
2025/12/18 14:28:02 INFO attempting to acquire metadata lock
2025/12/18 14:28:02 INFO acquired metadata lock lock_name=test.t1-23037d07
2025/12/18 14:28:02 INFO unable to use INPLACE error="statement contains operations that are not safe for INPLACE algorithm"
2025/12/18 14:28:02 INFO could not resume from checkpoint reason="could not read from table '_t1_chkpnt', err:Error 1146 (42S02): Table 'test._t1_chkpnt' doesn't exist"
2025/12/18 14:28:02 INFO releasing metadata lock lock_name=test.t1-23037d07
spirit: error: failed to alter new table: Error 1101 (42000): BLOB, TEXT, GEOMETRY or JSON column 'j' can't have a default value
exit status 1

Workaround: use --table and --alter instead of --statement:

go run ./cmd/spirit/ --username=root --password= --database=test --table=t1 --alter="add column j json default ('{}')"
2025/12/18 14:29:48 INFO Starting spirit migration concurrency=4 target-chunk-size=500ms
2025/12/18 14:29:48 INFO attempting to acquire metadata lock
2025/12/18 14:29:48 INFO acquired metadata lock lock_name=test.t1-23037d07
2025/12/18 14:29:48 INFO unable to use INPLACE error="statement contains operations that are not safe for INPLACE algorithm"
2025/12/18 14:29:48 INFO could not resume from checkpoint reason="could not read from table '_t1_chkpnt', err:Error 1146 (42S02): Table 'test._t1_chkpnt' doesn't exist"
2025/12/18 14:29:48 INFO create BinlogSyncer config="{ServerID:1592 Flavor:mysql Host:127.0.0.1 Port:3306 User:root Password: Localhost: Charset: SemiSyncEnabled:false RawModeEnabled:false TLSConfig:0x14000650000 ParseTime:false TimestampStringLocation:UTC UseDecimal:false UseFloatWithTrailingZero:false RecvBufferSize:0 HeartbeatPeriod:0s ReadTimeout:0s MaxReconnectAttempts:0 DisableRetrySync:false VerifyChecksum:false DumpCommandFlag:0 Option:<nil> Logger:0x14000126290 Dialer:0x102c45f40 RowsEventDecodeFunc:<nil> TableMapOptionalMetaDecodeFunc:<nil> DiscardGTIDSet:false EventCacheCount:10240 FillZeroLogPos:false SynchronousEventHandler:<nil>}"
...

This is probably an issue in how the TiDB parser restores statement syntax at

if err = alterStmt.Restore(rCtx); err != nil {

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions