PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0 4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 All 257 releases
give / src / Donations / Migrations / AddIndexesToDonationMetaTable.php

AddIndexesToDonationMetaTable.php in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at src/Donations/Migrations/AddIndexesToDonationMetaTable.php

91 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Give\Donations\Migrations;
4
5 use Give\Framework\Database\DB;
6 use Give\Framework\Database\Exceptions\DatabaseQueryException;
7 use Give\Framework\Migrations\Contracts\Migration;
8 use Give\Framework\Migrations\Exceptions\DatabaseMigrationException;
9
10 /**
11 * The donation meta table only indexes donation_id and meta_key on their own. Every model query
12 * joins the table once per meta key, and every filter by value (test mode, campaign, email) has
13 * to scan the whole key. Two composite indexes cover both patterns, and the single-column indexes
14 * they start with become redundant, so they are dropped to keep the table from growing by more
15 * than about a third. This mirrors the WooCommerce HPOS order meta table, which indexes
16 * (meta_key, meta_value) and (order_id, meta_key, meta_value) only.
17 *
18 * @since 4.18.0
19 */
20 class AddIndexesToDonationMetaTable extends Migration
21 {
22 /**
23 * @inheritdoc
24 */
25 public static function id(): string
26 {
27 return 'add_indexes_to_donation_meta_table';
28 }
29
30 /**
31 * @inheritdoc
32 */
33 public static function title(): string
34 {
35 return 'Add composite indexes to the donation meta table';
36 }
37
38 /**
39 * @inheritdoc
40 */
41 public static function timestamp(): string
42 {
43 return strtotime('2026-09-18 00:00:00');
44 }
45
46 /**
47 * @inheritDoc
48 * @throws DatabaseMigrationException
49 */
50 public function run()
51 {
52 global $wpdb;
53
54 $table = $wpdb->prefix . 'give_donationmeta';
55 $wanted = ['donation_meta_key', 'meta_key_value'];
56
57 try {
58 $existing = array_flip(DB::get_col("SHOW INDEX FROM {$table}", 2));
59
60 // Prefix lengths match WooCommerce HPOS wc_orders_meta. Under utf8mb4 they keep each key part under
61 // the 767-byte InnoDB COMPACT limit and the whole key under the 1000-byte MyISAM limit, so the
62 // ALTER succeeds on tables created by any host GiveWP has ever run on.
63 $clauses = array_diff_key([
64 'donation_meta_key' => 'ADD INDEX donation_meta_key (donation_id, meta_key(100))',
65 'meta_key_value' => 'ADD INDEX meta_key_value (meta_key(100), meta_value(82))',
66 ], $existing);
67
68 $clauses += array_intersect_key([
69 'donation_id' => 'DROP INDEX donation_id',
70 'meta_key' => 'DROP INDEX meta_key',
71 ], $existing);
72
73 if (!$clauses) {
74 return;
75 }
76
77 DB::query("ALTER TABLE {$table} " . implode(', ', $clauses));
78 } catch (DatabaseQueryException $exception) {
79 // Another request may have built the indexes while this one waited on the table lock.
80 // Only the finished layout counts, so a failed DROP alone still fails the migration.
81 $indexes = DB::get_col("SHOW INDEX FROM {$table}", 2);
82
83 if (!array_diff($wanted, $indexes) && !array_intersect(['donation_id', 'meta_key'], $indexes)) {
84 return;
85 }
86
87 throw new DatabaseMigrationException("An error occurred while adding indexes to the {$table} table", 0, $exception);
88 }
89 }
90 }
91