| @@ -510,11 +510,18 @@ | ||
| 510 | 510 | * meta onto a second record. Resolving such a uuid to an arbitrary first match would |
| 511 | 511 | * route a write/delete to the WRONG record, so we fetch up to two and **fail closed** |
| 512 | 512 | * (`WP_Error` 409 `woo_rxdb_sync_identity_ambiguous`) when more than one record carries |
| 513 | 513 | * the uuid — the caller aborts the mutation (and releases its reservation) rather than |
| 514 | - * corrupt a record. A unique match is returned by lowest id (deterministic) so retries | |
| 515 | - * are stable. | |
| 514 | + * corrupt a record. A unique match is the only id in the result set, so resolution is | |
| 515 | + * deterministic and retries are stable without the query imposing an order. | |
| 516 | 516 | * |
| 517 | + * DELIBERATELY UNORDERED — do not add an `ORDER BY` back (#1725). Because the outcome | |
| 518 | + * is decided by the COUNT (0 = none, 1 = that id, >1 = fail closed), which two ids a | |
| 519 | + * `LIMIT 2` returns is immaterial. `wp_postmeta`/`wp_usermeta`/`wp_termmeta` index | |
| 520 | + * `meta_key` but never `meta_value`, so `ORDER BY <id> ASC LIMIT 2` made the optimizer | |
| 521 | + * prefer an id-ordered walk that expects to stop early — and, with at most one match, | |
| 522 | + * never does. Measured at ~1.35 s per call on a real store; see Pos_Uuid::get_order_ids_by_uuid. | |
| 523 | + * | |
| 517 | 524 | * @return int|WP_Error 0 if none, the id if unique, or a 409 WP_Error if ambiguous. |
| 518 | 525 | */ |
| 519 | 526 | public function resolve_id_by_uuid( string $id_type, string $uuid, array $opts = array() ) { |
| 520 | 527 | $key = Api::UUID_META_KEY; |
| @@ -525,9 +532,9 @@ | ||
| 525 | 532 | $wpdb->prepare( |
| 526 | 533 | "SELECT DISTINCT u.ID FROM {$wpdb->users} u" |
| 527 | 534 | . " JOIN {$wpdb->usermeta} m ON m.user_id = u.ID" |
| 528 | 535 | . ' WHERE m.meta_key = %s AND m.meta_value = %s' |
| 529 | - . ' ORDER BY u.ID ASC LIMIT 2', | |
| 536 | + . ' LIMIT 2', | |
| 530 | 537 | $key, |
| 531 | 538 | $uuid |
| 532 | 539 | ) |
| 533 | 540 | ); |
| @@ -546,9 +553,9 @@ | ||
| 546 | 553 | if ( 'any' !== $post_type ) { |
| 547 | 554 | $sql .= ' AND p.post_type = %s'; |
| 548 | 555 | $args[] = $post_type; |
| 549 | 556 | } |
| 550 | - $sql .= ' ORDER BY p.ID ASC LIMIT 2'; | |
| 557 | + $sql .= ' LIMIT 2'; | |
| 551 | 558 | $found = $wpdb->get_col( $wpdb->prepare( $sql, ...$args ) ); |
| 552 | 559 | break; |
| 553 | 560 | case 'term': |
| 554 | 561 | $found = $wpdb->get_col( |
| @@ -554,9 +561,9 @@ | ||
| 554 | 561 | $found = $wpdb->get_col( |
| 555 | 562 | $wpdb->prepare( |
| 556 | 563 | "SELECT DISTINCT term_id FROM {$wpdb->termmeta}" |
| 557 | 564 | . ' WHERE meta_key = %s AND meta_value = %s' |
| 558 | - . ' ORDER BY term_id ASC LIMIT 2', | |
| 565 | + . ' LIMIT 2', | |
| 559 | 566 | $key, |
| 560 | 567 | $uuid |
| 561 | 568 | ) |
| 562 | 569 | ); |