Skip to content

fix(core): support PostgreSQL with deterministic ordering#2518

Open
alecgarcia wants to merge 1 commit into
lunarphp:1.xfrom
alecgarcia:fix/postgres-deterministic-ordering
Open

fix(core): support PostgreSQL with deterministic ordering#2518
alecgarcia wants to merge 1 commit into
lunarphp:1.xfrom
alecgarcia:fix/postgres-deterministic-ordering

Conversation

@alecgarcia

Copy link
Copy Markdown

What & why

Several core relationships had no explicit ORDER BY, so row order depended on the database engine. MySQL/InnoDB returns clustered primary-key order by coincidence, but PostgreSQL — which is officially supported — returns heap order, which changes after an UPDATE. Running on PostgreSQL surfaces this as user-visible instability.

Changes

  • Cart::lines() and Order::lines() now order by id. Lunar relies on a stable line sequence: GenerateFingerprint reduces $cart->lines in iteration order, so an unstable order can change a cart's fingerprint after an unrelated update, not just shift the displayed order. Ordering Order::lines() also stabilizes the derived physicalLines/digitalLines/shippingLines/productLines.
  • ProductVariant::values() now orders by position, with the pivot id as a deterministic tie-break across options. getOption() joins these values into the variant option label, which is snapshotted onto order lines in CreateOrderLines, so the persisted value must be deterministic across engines.

This follows the relationship-level ordering convention already used by Order::transactions(), ProductOption::values(), and AttributeGroup::attributes().

Tests

New coverage in CartTest, OrderTest, and ProductVariantTest. Each ordering test fails on the current code and passes with the fix. The full tests/core suite passes (561 passed, 1 skipped); Pint is clean.

Note: the test database is SQLite, which returns rows in insertion order, so a behavioural heap-reorder cannot be reproduced there directly. The cart/order tests therefore assert the ordering contract on the relationship itself; the variant test asserts position ordering against a deliberately out-of-order attachment, which fails without the fix on any engine.

Fixes #2517

Several relationships had no explicit ORDER BY, so row order depended on
the database engine. MySQL/InnoDB returns rows in clustered primary-key
order by coincidence, but PostgreSQL — which is officially supported —
returns heap order, which changes after an UPDATE. This surfaced as
user-visible instability once running on PostgreSQL.

- Cart::lines() and Order::lines() now order by id. Lunar relies on a
  stable line sequence: GenerateFingerprint reduces $cart->lines in
  iteration order, so an unstable order can change a cart's fingerprint
  after an unrelated update, not just shift the displayed order.
- ProductVariant::values() now orders by position, with the pivot id as a
  deterministic tie-break across options. getOption() joins these values
  into the variant option label, which is snapshotted onto order lines, so
  the persisted value must be deterministic across engines.

This follows the relationship-level ordering convention already used by
Order::transactions(), ProductOption::values(), and
AttributeGroup::attributes().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Several core relationships lack deterministic ordering — row order shifts on PostgreSQL

1 participant