Skip to content

Use '0' column defaults in non-strict INSERT statements - #569

Merged
JanJakes merged 2 commits into
WordPress:trunkfrom
noruzzamans:fix/552-non-strict-insert-zero-default
Oct 27, 2026
Merged

JanJakes merged 2 commits into
WordPress:trunkfrom
noruzzamans:fix/552-non-strict-insert-zero-default

Conversation

@noruzzamans

@noruzzamans noruzzamans commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Fixes #552.

Description

In MySQL non-strict mode, omitted columns during INSERT are filtered out from the synthetic wrapper subquery if they have a default value defined, allowing SQLite to populate their schema default.

Previously, translate_insert_or_replace_body() evaluated $column['COLUMN_DEFAULT'] with a loose truthiness check ($has_default = $column['COLUMN_DEFAULT']). In PHP, string '0' evaluates to false, treating the column as having no default value and incorrectly populating it with an implicit default empty string ('').

This PR:

  • Updates the check to null !== $column['COLUMN_DEFAULT'], consistent with other default checks in the driver.
  • Adds regression test assertions in testNonStrictSqlModeNotNullWithDefault covering DEFAULT '0' and DEFAULT 0.

Testing instructions

Run unit tests in packages/mysql-on-sqlite:

cd packages/mysql-on-sqlite
composer run test -- --filter testNonStrictSqlModeNotNullWithDefault

Summary by CodeRabbit

  • Bug Fixes
    • Corrected handling of columns with a default value of 0 when inserting rows without explicitly providing those columns. Omitted values now receive their configured defaults rather than being treated as though no default were set.
  • Tests
    • Added coverage confirming that omitted values in columns with text or numeric zero defaults are populated as expected.

In non-strict mode, omitted columns are filtered from synthetic subqueries when they have a default value. A loose truthiness check previously caused string '0' to be evaluated as false, substituting an implicit default empty string instead of preserving the column default.

Use strict null check consistent with the rest of the codebase, and add regression assertions in testNonStrictSqlModeNotNullWithDefault.
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 678797a5-78d7-4956-85a8-e9c76e89746b
Commits

Reviewing files that changed from the base of the PR and between 285bebf and 0923948.

Files selected for processing: 1
  • packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Walkthrough

The omitted-column filter now treats any non-null COLUMN_DEFAULT as a default, including string and integer zero. The test inserts a row without those columns and checks that both values are '0'.

Changes: Non-strict INSERT defaults

Layer / File(s) Summary
Recognize zero defaults
packages/mysql-on-sqlite/src/sqlite/class-wp-mysql-on-sqlite.php, packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php
The omitted-column filter checks whether COLUMN_DEFAULT is non-null. The test covers omitted string and integer columns with zero defaults.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related issues

Possibly related PRs

Suggested reviewers: janjakes

Merge Risk: Minimal · up to 09239

No actionable merge-blocking risk is established for this change.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preserving a '0' column default during non-strict INSERT operations.
Linked Issues check Passed Issue #552 requires non-strict INSERT to preserve a defined default of '0'. The driver now checks null !== $column['COLUMN_DEFAULT'] in translate_insert_or_replace_body(). The regression test …
Out of Scope Changes check Passed The driver condition change and the added assertions in testNonStrictSqlModeNotNullWithDefault directly support issue #552. The supplied change summary shows no unrelated product behavior or files.
Docstring Coverage Passed Docstring coverage is inconclusive: files from earlier reviews still need to be rechecked within the check's analysis limits. Not blocking.
Full details: Linked Issues check

Explanation

Issue #552 requires non-strict INSERT to preserve a defined default of '0'. The driver now checks null !== $column['COLUMN_DEFAULT'] in translate_insert_or_replace_body(). The regression test covers both DEFAULT '0' and DEFAULT 0 and expects both values to remain '0'. The supplied evidence does not include test execution, but it shows the required automated coverage.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

PHPStan (2.3.0)

PHPStan reported 1 non-file analysis error(s); analysis is incomplete

PHPMD (3.0.0)
packages/mysql-on-sqlite/tests/WP_MySQL_On_SQLite_Tests.php

PHPMD could not process this file (exit code 255): 0/1 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2097152 bytes) in phar:///usr/bin/phpmd/vendor/pdepend/pdepend/src/Util/Cache/Driver/FileCacheDriver.php on line 183

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@noruzzamans
noruzzamans marked this pull request as ready for review October 24, 2026 11:37
The `INT DEFAULT 0` assertion also passed without the fix, because the
implicit default of `INT` columns is `0` as well. Use a `VARCHAR`
column with an unquoted `DEFAULT 0` instead. Like `DEFAULT '0'`, it
saved `''` before the fix.

Also drop the issue reference from the test comment.
@JanJakes

Copy link
Copy Markdown
Member

Thanks for the contribution, @noruzzamans! I just pushed a small fix to the test. The INT DEFAULT 0 assertion also passed without your change, because INT columns get 0 as the implicit default anyway. I replaced it with a VARCHAR column with an unquoted DEFAULT 0, which now fails without the fix.

@noruzzamans

Copy link
Copy Markdown
Member Author

Thanks for the review, @JanJakes. Good catch on the implicit INT default, and appreciate you updating the test directly.

@JanJakes
JanJakes merged commit 7a01ec4 into WordPress:trunk Oct 27, 2026
16 of 17 checks passed
@JanJakes JanJakes changed the title Fix '0' column default preservation during non-strict INSERT Use '0' column defaults in non-strict INSERT statements Oct 28, 2026
@JanJakes JanJakes mentioned this pull request Oct 28, 2026
JanJakes added a commit that referenced this pull request Oct 28, 2026
## Release `3.1.2`

Version bump and changelog update for release `3.1.2`.

**Changelog draft:**
* Allow configuring the SQLite busy timeout with `SQLITE_BUSY_TIMEOUT`
([#558](#558))
* Keep the user transaction active after a failed statement
([#536](#536))
* Support odd-length `0x` hexadecimal literals
([#573](#573))
* Fix rebuilds of legacy text and binary columns
([#565](#565))
* Use `'0'` column defaults in non-strict `INSERT` statements
([#569](#569))
* Roll back failed `OPTIMIZE TABLE` and `REPAIR TABLE` rebuilds
([#567](#567))
* Remove the Rust parser extension
([#566](#566))
* Preserve `AUTO_INCREMENT` counters when rebuilding tables
([#561](#561))
* Fix `ALTER TABLE ... ADD (...)` for columns, indexes, and constraints
([#557](#557))
* Fix `ON UPDATE CURRENT_TIMESTAMP` for explicit values and unchanged
rows
([#560](#560))
* Normalize zero defaults in date and time columns
([#542](#542))
* Add support for `ALTER COLUMN` with `SET DEFAULT` and `DROP DEFAULT`
([#555](#555))

**Full changelog:**
v3.1.1...release/v3.1.2

## Next steps

1. **Review** the changes in this pull request.
2. **Push** any additional edits to this branch (`release/v3.1.2`).
3. **Merge** this pull request to complete the release.

Merging will automatically build the plugin ZIP, create a [GitHub
release](https://github.com/WordPress/sqlite-database-integration/releases),
and deploy to
[WordPress.org](https://wordpress.org/plugins/sqlite-database-integration/).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

* **Release**
  * Updated the SQLite database integration to version 3.1.2.

* **New Features**
* Added support for more `ALTER TABLE` operations and configurable
SQLite busy timeouts.

* **Bug Fixes**
* Improved transaction handling after failed statements and addressed
SQL compatibility, table rebuild, and default-value handling issues.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

INSERT in non-strict mode stores '' instead of the column default '0'

2 participants