Skip to content

Commit 89ecbbf

Browse files
authored
Merge pull request #333 from wp-cli/fix/sql-mode-compat-311
Fix SQL mode compat issues by removing the additional probe request
2 parents 6a3b1a4 + ab66c6e commit 89ecbbf

3 files changed

Lines changed: 226 additions & 107 deletions

File tree

features/db-import.feature

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,114 @@ Feature: Import a WordPress database
247247
"""
248248
🍣
249249
"""
250+
251+
# SQLite does not use the MySQL client and has no concept of SQL modes.
252+
@require-mysql-or-mariadb
253+
Scenario: `wp db import` adapts the SQL mode via --init-command by default
254+
Given a WP install
255+
256+
When I run `wp db export wp_cli_test.sql`
257+
Then the wp_cli_test.sql file should exist
258+
259+
# The WordPress-compatibility mode adaptation runs on the same import
260+
# connection via --init-command, so it is visible in the debug output and no
261+
# separate mode probe runs (which is what used to break with custom connection
262+
# options).
263+
When I try `wp db import wp_cli_test.sql --debug`
264+
Then the return code should be 0
265+
And STDERR should contain:
266+
"""
267+
SET SESSION sql_mode
268+
"""
269+
And STDERR should not contain:
270+
"""
271+
Failed to get current SQL modes
272+
"""
273+
274+
@require-mysql-or-mariadb
275+
Scenario: `wp db import --skip-sql-mode-compat` imports under the server's own SQL modes
276+
Given a WP install
277+
278+
When I run `wp db export wp_cli_test.sql`
279+
Then the wp_cli_test.sql file should exist
280+
281+
When I try `wp db import wp_cli_test.sql --skip-sql-mode-compat --debug`
282+
Then the return code should be 0
283+
And STDERR should not contain:
284+
"""
285+
SET SESSION sql_mode
286+
"""
287+
288+
# Regression test for the WordPress-compatibility behavior. WordPress schema
289+
# declares datetime columns as `DEFAULT '0000-00-00 00:00:00'`, so real dumps
290+
# carry zero-date values. On servers whose default SQL mode includes
291+
# NO_ZERO_DATE/STRICT_TRANS_TABLES (MySQL 5.7+/8.0), a raw dump without its own
292+
# SQL_MODE header would fail to import with "Invalid default value". `wp db
293+
# import` must strip those modes for the session so the import succeeds.
294+
@require-mysql-or-mariadb
295+
Scenario: `wp db import` loads a dump containing legacy zero-date values
296+
Given a WP install
297+
And a zerodate.sql file:
298+
"""
299+
CREATE TABLE `wp_cli_zerodate` (
300+
`id` int NOT NULL,
301+
`d` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
302+
);
303+
INSERT INTO `wp_cli_zerodate` (`id`, `d`) VALUES (1, '0000-00-00 00:00:00');
304+
"""
305+
306+
When I run `wp db import zerodate.sql`
307+
Then STDOUT should contain:
308+
"""
309+
Success: Imported from 'zerodate.sql'.
310+
"""
311+
312+
When I run `wp db query 'SELECT COUNT(*) FROM wp_cli_zerodate;' --skip-column-names`
313+
Then STDOUT should contain:
314+
"""
315+
1
316+
"""
317+
318+
# Regression test for https://github.com/wp-cli/db-command/issues/171
319+
# A dump streamed from STDIN must get the same WordPress SQL-mode compatibility
320+
# as a file import. This is now handled via --init-command, which applies on the
321+
# STDIN connection too (the previous prepend only covered file imports).
322+
@require-mysql-or-mariadb
323+
Scenario: `wp db import -` from STDIN loads a dump containing legacy zero-date values
324+
Given a WP install
325+
And a zerodate_stdin.sql file:
326+
"""
327+
CREATE TABLE wp_cli_zerodate_stdin (id int NOT NULL, d datetime NOT NULL DEFAULT '0000-00-00 00:00:00');
328+
INSERT INTO wp_cli_zerodate_stdin (id, d) VALUES (1, '0000-00-00 00:00:00');
329+
"""
330+
331+
When I run `wp db import - < zerodate_stdin.sql`
332+
Then STDOUT should contain:
333+
"""
334+
Success: Imported from 'STDIN'.
335+
"""
336+
337+
When I run `wp db query 'SELECT COUNT(*) FROM wp_cli_zerodate_stdin;' --skip-column-names`
338+
Then STDOUT should contain:
339+
"""
340+
1
341+
"""
342+
343+
# The compatibility statement must compose with a caller-supplied --init-command
344+
# rather than replace it. Both are sent as a single multi-statement
345+
# --init-command (compatibility statement first, caller's second), so the
346+
# caller's own init command still runs and the zero-date import still succeeds.
347+
@require-mysql-or-mariadb
348+
Scenario: `wp db import` keeps SQL-mode compatibility when the caller sets --init-command
349+
Given a WP install
350+
And a zerodate_compose.sql file:
351+
"""
352+
CREATE TABLE wp_cli_zd_compose (id int NOT NULL, d datetime NOT NULL DEFAULT '0000-00-00 00:00:00');
353+
INSERT INTO wp_cli_zd_compose (id, d) VALUES (1, '0000-00-00 00:00:00');
354+
"""
355+
356+
When I run `wp db import zerodate_compose.sql --init-command="SET @x = 1"`
357+
Then STDOUT should contain:
358+
"""
359+
Success: Imported from 'zerodate_compose.sql'.
360+
"""

features/db-query.feature

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,51 @@ Feature: Query the database with WordPress' MySQL config
9191
When I try `wp db query --no-defaults --debug`
9292
Then STDERR should match #Debug \(db\): Running shell command: /([^/]+/)+(mysql|mariadb) --no-defaults --no-auto-rehash#
9393

94-
Scenario: SQL modes do not include any of the modes incompatible with WordPress
94+
# `wp db query` adapts the session SQL mode to be WordPress-compatible the same
95+
# way `wp db import` does: via --init-command on the query's own connection, with
96+
# no separate mode probe. This keeps statements against WordPress's zero-date
97+
# schema (e.g. `ALTER TABLE wp_blogs ...`, `CREATE TABLE ... AS SELECT` from a
98+
# WordPress table) working on servers whose default SQL mode is strict.
99+
@require-mysql-or-mariadb
100+
Scenario: `wp db query` adapts the SQL mode by default without a separate mode probe
95101
Given a WP install
96102

97-
When I try `wp db query 'SELECT @@SESSION.sql_mode;' --debug`
98-
Then STDOUT should not contain:
99-
"""
100-
NO_ZERO_DATE
101-
"""
102-
And STDOUT should not contain:
103-
"""
104-
ONLY_FULL_GROUP_BY
105-
"""
106-
And STDOUT should not contain:
103+
When I try `wp db query 'SELECT 1;' --debug`
104+
Then the return code should be 0
105+
And STDERR should contain:
107106
"""
108-
STRICT_TRANS_TABLES
107+
SET SESSION sql_mode
109108
"""
110-
And STDOUT should not contain:
109+
And STDERR should not contain:
111110
"""
112-
STRICT_ALL_TABLES
111+
Failed to get current SQL modes
113112
"""
114-
And STDOUT should not contain:
113+
114+
@require-mysql-or-mariadb
115+
Scenario: `wp db query --skip-sql-mode-compat` runs under the server's own SQL modes
116+
Given a WP install
117+
118+
When I try `wp db query 'SELECT 1;' --skip-sql-mode-compat --debug`
119+
Then the return code should be 0
120+
And STDERR should not contain:
115121
"""
116-
TRADITIONAL
122+
SET SESSION sql_mode
117123
"""
118-
And STDOUT should not contain:
124+
125+
# Regression test for https://github.com/wp-cli/db-command/issues/311
126+
# Passing connection options alongside an inline query used to fail, because the
127+
# old SQL-mode probe opened a *second* connection that ignored those very options
128+
# (custom --host, --defaults, SSL/TLS, sockets, ...) and then aborted the whole
129+
# command with "Failed to get current SQL modes". The probe is gone -- the
130+
# compatibility mode is now applied via --init-command on the query's own
131+
# connection -- so the inline query runs directly under the given options.
132+
Scenario: `wp db query` with an inline query and connection options does not trigger a failing mode probe
133+
Given a WP install
134+
135+
When I try `wp db query 'SELECT 1;' --defaults --debug`
136+
Then STDERR should not contain:
119137
"""
120-
ANSI
138+
Failed to get current SQL modes
121139
"""
122140

123141
# Regression test for https://github.com/wp-cli/db-command/issues/309

0 commit comments

Comments
 (0)