Skip to content

Add support for NO_AUTO_VALUE_ON_ZERO SQL mode#366

Open
JanJakes wants to merge 1 commit intotrunkfrom
zero-value-auto-increment
Open

Add support for NO_AUTO_VALUE_ON_ZERO SQL mode#366
JanJakes wants to merge 1 commit intotrunkfrom
zero-value-auto-increment

Conversation

@JanJakes
Copy link
Copy Markdown
Member

@JanJakes JanJakes commented Apr 20, 2026

Summary

Emulates MySQL's NO_AUTO_VALUE_ON_ZERO SQL mode behavior on SQLite.

MySQL treats a literal 0 in an AUTO_INCREMENT column the same as NULL and generates the next sequence value. This can be suppressed by the NO_AUTO_VALUE_ON_ZERO SQL mode, which is not part of MySQL's default modes.

Some legacy WordPress versions rely on the default behavior — e.g. WP 1.0's post.php emits:

INSERT INTO wp_posts (ID, post_author, post_title, post_status)
VALUES ('0', '1', 'Hello', 'publish');

On MySQL this stores ID = 1. The current SQLite driver stored ID = 0, which fails with legacy WP.

Scope

  • Affects: INSERT / REPLACE value lists (including VALUES, SET, and SELECT forms).
  • Does not affect: UPDATE (and the UPDATE half of INSERT ... ON DUPLICATE KEY UPDATE). MySQL never auto-generates AUTO_INCREMENT values on UPDATE — zeros are stored literally.

The default sql_mode was already correct — NO_AUTO_VALUE_ON_ZERO is absent, matching MySQL 8.0 defaults.

Tests

  • testDefaultSqlModeDoesNotIncludeNoAutoValueOnZero — asserts the default modes.
  • testAutoIncrementZeroAdvancesSequenceByDefault0, '0', and NULL all generate new ids.
  • testAutoIncrementZeroAdvancesSequenceForAllInsertShapes — covers INSERT ... SET, INSERT ... SELECT, and REPLACE.
  • testNoAutoValueOnZeroSqlMode — with the mode on, literal 0 is stored as-is; only NULL advances the sequence.

See: https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html#sqlmode_no_auto_value_on_zero

By default, MySQL treats a literal 0 in an AUTO_INCREMENT column the
same as NULL and generates the next sequence value. This behavior is
suppressed by the NO_AUTO_VALUE_ON_ZERO SQL mode, which is not part of
the default modes.

To emulate this on SQLite, rewrite the value to NULL via
NULLIF(CAST(... AS INTEGER), 0). The explicit CAST is required because
SQLite compares storage classes strictly, so NULLIF('0', 0) returns
'0', not NULL — and WordPress 1.0 emits the string form.

Also exclude AUTO_INCREMENT columns from the non-strict IMPLICIT
DEFAULT COALESCE wrapping, so a NULL (original or rewritten from 0)
always advances the sequence.

See: https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html#sqlmode_no_auto_value_on_zero
@JanJakes JanJakes marked this pull request as ready for review April 20, 2026 09:15
@JanJakes JanJakes requested review from a team, brandonpayton and zaerl and removed request for a team and zaerl April 20, 2026 09:16
@JanJakes JanJakes changed the title Handle NO_AUTO_VALUE_ON_ZERO in the INSERT translator Add support for NO_AUTO_VALUE_ON_ZERO SQL mode Apr 21, 2026
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.

1 participant