Limit index length to 191 characters by default.

Additionally, connect verify db tooling to order tables when they are enabled.
This commit is contained in:
Vedanshu Jain 2023-07-14 15:40:47 +05:30
parent f8dfc30708
commit c2590f2520
4 changed files with 54 additions and 9 deletions

View File

@ -8,6 +8,10 @@
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\Notes\Notes;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Register as Download_Directories;
use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Synchronize as Download_Directories_Sync;
@ -460,9 +464,21 @@ class WC_Install {
self::create_tables();
}
$schema = self::get_schema();
$feature_controller = wc_get_container()->get( FeaturesController::class );
if (
$feature_controller->feature_is_enabled( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION )
|| $feature_controller->feature_is_enabled( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION )
) {
$schema .= wc_get_container()
->get( OrdersTableDataStore::class )
->get_database_schema();
}
$missing_tables = wc_get_container()
->get( DatabaseUtil::class )
->get_missing_tables( self::get_schema() );
->get_missing_tables( $schema );
if ( 0 < count( $missing_tables ) ) {
if ( $modify_notice ) {
@ -1122,12 +1138,20 @@ class WC_Install {
$collate = $wpdb->get_charset_collate();
}
/*
* Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
/**
* Filters the maximum index length in the database.
*
* Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
* As of WP 4.2, however, they moved to utf8mb4, which uses 4 bytes per character. This means that an index which
* used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
*
* Additionally, MyISAM engine also limits the index size to 1000 bytes. We add this filter so that interested folks on InnoDB engine can increase the size till allowed 3600 bytes.
*
* @param int $max_index_length Maximum index length. Default 191.
*
* @since 8.0.0
*/
$max_index_length = 191;
$max_index_length = apply_filters( 'woocommerce_database_max_index_length', 191 );
$product_attributes_lookup_table_creation_sql = wc_get_container()->get( DataRegenerator::class )->get_table_creation_sql();

View File

@ -366,6 +366,7 @@ class CustomOrdersTableController {
if ( ! $this->data_synchronizer->check_orders_table_exists() ) {
$this->data_synchronizer->create_database_tables();
}
// Enabling/disabling the sync implies starting/stopping it too, if needed.

View File

@ -2584,6 +2584,23 @@ FROM $order_meta_table
$operational_data_table_name = $this->get_operational_data_table_name();
$meta_table = $this->get_meta_table_name();
/**
* Filters the maximum index length in the database.
*
* Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
* As of WP 4.2, however, they moved to utf8mb4, which uses 4 bytes per character. This means that an index which
* used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
*
* Additionally, MyISAM engine also limits the index size to 1000 bytes. We add this filter so that interested folks on InnoDB engine can increase the size till allowed 3600 bytes.
*
* @param int $max_index_length Maximum index length. Default 191.
*
* @since 8.0.0
*/
$max_index_length = apply_filters( 'woocommerce_database_max_index_length', 191 );
$composite_meta_value_index_length = max( $max_index_length - 8 - 100 - 1, 20 ); // 8 for order_id, 100 for meta_key, 10 minimum for meta_value.
$composite_customer_id_email_length = max( $max_index_length - 20, 20 ); // 8 for customer_id, 20 minimum for email.
$sql = "
CREATE TABLE $orders_table_name (
id bigint(20) unsigned,
@ -2606,8 +2623,8 @@ CREATE TABLE $orders_table_name (
PRIMARY KEY (id),
KEY status (status),
KEY date_created (date_created_gmt),
KEY customer_id_billing_email (customer_id, billing_email),
KEY billing_email (billing_email),
KEY customer_id_billing_email (customer_id, billing_email({$composite_customer_id_email_length})),
KEY billing_email (billing_email($max_index_length)),
KEY type_status (type, status),
KEY parent_order_id (parent_order_id),
KEY date_updated (date_updated_gmt)
@ -2629,7 +2646,7 @@ CREATE TABLE $addresses_table_name (
phone varchar(100) null,
KEY order_id (order_id),
UNIQUE KEY address_type_order_id (address_type, order_id),
KEY email (email),
KEY email (email($max_index_length)),
KEY phone (phone)
) $collate;
CREATE TABLE $operational_data_table_name (
@ -2659,8 +2676,8 @@ CREATE TABLE $meta_table (
order_id bigint(20) unsigned null,
meta_key varchar(255),
meta_value text null,
KEY meta_key_value (meta_key, meta_value(100)),
KEY order_id_meta_key_meta_value (order_id, meta_key, meta_value(100))
KEY meta_key_value (meta_key(100), meta_value($composite_meta_value_index_length)),
KEY order_id_meta_key_meta_value (order_id, meta_key(100), meta_value($composite_meta_value_index_length))
) $collate;
";

View File

@ -424,7 +424,10 @@ class FeaturesController {
case 'new_navigation':
return Init::TOGGLE_OPTION_NAME;
case 'custom_order_tables':
case CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION:
return CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION;
case DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION:
return DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION;
default:
return "woocommerce_feature_{$feature_id}_enabled";
}