Support inserting NULL values for strict DB mode (#39396)
* Support inserting NULL values for strict DB mode * Set default date for placeholder order to support strict MySQL. * Add unit test to verify strict mode also works. * Make HPOS behavior of modified date consistent with WP_Post. In HPOS we were leaving modified date to be empty, while WP_Post set it to the created date if modified date is null.
This commit is contained in:
parent
58dfbd2c4e
commit
9b7570f8b2
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Support inserting NULL values for strict DB mode for DataBase Util's insert_on_duplicate_key_update method.
|
|
@ -1659,6 +1659,7 @@ FROM $order_meta_table
|
|||
'post_type' => $data_sync->data_sync_is_enabled() ? $order->get_type() : $data_sync::PLACEHOLDER_ORDER_POST_TYPE,
|
||||
'post_status' => 'draft',
|
||||
'post_parent' => $order->get_changes()['parent_id'] ?? $order->get_data()['parent_id'] ?? 0,
|
||||
'post_date_gmt' => current_time( 'mysql', 1 ), // We set the date to prevent invalid date errors when using MySQL strict mode.
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -2287,6 +2288,10 @@ FROM $order_meta_table
|
|||
$order->set_date_created( time() );
|
||||
}
|
||||
|
||||
if ( ! $order->get_date_modified( 'edit' ) ) {
|
||||
$order->set_date_modified( current_time( 'mysql' ) );
|
||||
}
|
||||
|
||||
$this->update_order_meta( $order );
|
||||
|
||||
$this->persist_order_to_db( $order, $force_all_fields );
|
||||
|
@ -2370,7 +2375,7 @@ FROM $order_meta_table
|
|||
$changes = $order->get_changes();
|
||||
|
||||
if ( ! isset( $changes['date_modified'] ) ) {
|
||||
$order->set_date_modified( time() );
|
||||
$order->set_date_modified( current_time( 'mysql' ) );
|
||||
}
|
||||
|
||||
$this->persist_order_to_db( $order );
|
||||
|
|
|
@ -233,19 +233,35 @@ class DatabaseUtil {
|
|||
*/
|
||||
public function insert_on_duplicate_key_update( $table_name, $data, $format ) : int {
|
||||
global $wpdb;
|
||||
if ( empty( $data ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$columns = array_keys( $data );
|
||||
$value_format = array();
|
||||
$values = array();
|
||||
$index = 0;
|
||||
// Directly use NULL for placeholder if the value is NULL, since otherwise $wpdb->prepare will convert it to empty string.
|
||||
foreach ( $data as $key => $value ) {
|
||||
if ( is_null( $value ) ) {
|
||||
$value_format[] = 'NULL';
|
||||
} else {
|
||||
$values[] = $value;
|
||||
$value_format[] = $format[ $index ];
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
$column_clause = '`' . implode( '`, `', $columns ) . '`';
|
||||
$value_placeholders = implode( ', ', array_values( $format ) );
|
||||
$value_format_clause = implode( ', ', $value_format );
|
||||
$on_duplicate_clause = $this->generate_on_duplicate_statement_clause( $columns );
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- Values are escaped in $wpdb->prepare.
|
||||
$sql = $wpdb->prepare(
|
||||
"
|
||||
INSERT INTO $table_name ( $column_clause )
|
||||
VALUES ( $value_placeholders )
|
||||
VALUES ( $value_format_clause )
|
||||
$on_duplicate_clause
|
||||
",
|
||||
array_values( $data )
|
||||
$values
|
||||
);
|
||||
// phpcs:enable
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $sql is prepared.
|
||||
|
|
|
@ -68,6 +68,7 @@ class OrdersTableDataStoreTests extends HposTestCase {
|
|||
* Destroys system under test.
|
||||
*/
|
||||
public function tearDown(): void {
|
||||
global $wpdb;
|
||||
//phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set -- We need to change the timezone to test the date sync fields.
|
||||
update_option( 'timezone_string', $this->original_time_zone );
|
||||
$this->toggle_cot_feature_and_usage( $this->cot_state );
|
||||
|
@ -1996,6 +1997,37 @@ class OrdersTableDataStoreTests extends HposTestCase {
|
|||
$this->assertEquals( $modified_date->format( 'Y-m-d H:i:s' ), $post->post_modified_gmt );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testDox Test that inserting with strict SQL mode is also supported.
|
||||
*/
|
||||
public function test_order_create_with_strict_mode_and_null_values() {
|
||||
global $wpdb;
|
||||
$this->toggle_cot_feature_and_usage( true );
|
||||
$sql_mode = $wpdb->get_var( 'SELECT @@sql_mode' );
|
||||
// Set SQL mode to strict to disallow 0 dates.
|
||||
$wpdb->query( "SET sql_mode = 'TRADITIONAL'" );
|
||||
|
||||
$order = new WC_Order();
|
||||
$this->switch_data_store( $order, $this->sut );
|
||||
$order->save();
|
||||
|
||||
$this->assertTrue( $order->get_id() > 0 );
|
||||
|
||||
// Let's also repeat with sync off.
|
||||
$this->enable_cot_sync();
|
||||
$order = new WC_Order();
|
||||
$this->switch_data_store( $order, $this->sut );
|
||||
$order->save();
|
||||
|
||||
$this->assertTrue( $order->get_id() > 0 );
|
||||
$order = wc_get_order( $order->get_id() );
|
||||
$post = get_post( $order->get_id() );
|
||||
$this->assertEquals( $order->get_date_modified()->format( 'Y-m-d H:i:s' ), $post->post_date );
|
||||
|
||||
// phpcs:ignore -- Hardcoded value.
|
||||
$wpdb->query( "SET sql_mode = '$sql_mode' " );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testDox Test that multiple calls to read don't try to sync again.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue