|
| 1 | +# Module 02 — Converged vs Multi-Model |
| 2 | + |
| 3 | +Three runnable proofs for leaf article 2's core claims ("multi-model is a |
| 4 | +storage claim; converged is a guarantees claim"). Every script executes |
| 5 | +against the live lab container and emits machine-checkable assertions |
| 6 | +(`ASSERT:<name>:PASS|FAIL`). No screenshots, no trust-me — run them yourself. |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## Proof 1: `scripts/01-survey-challenge.sql` |
| 11 | + |
| 12 | +**Article claim: the academic literature's canonical multi-model query runs as |
| 13 | +one standard SQL statement.** Lu & Holubová's ACM Computing Surveys survey of |
| 14 | +multi-model databases (52(3) Art. 55, 2019) opens with a running example |
| 15 | +(their Fig. 1): relational customers (Mary, credit 5000; John, 3000; William, |
| 16 | +2000), a "knows" social graph, and orders as JSON documents — challenge query: |
| 17 | +*"Return all product_no which are ordered by a friend of a customer whose |
| 18 | +credit_limit>3000"*, published result `['2724f','3424g']`. The survey solves |
| 19 | +it in ArangoDB AQL and OrientDB SQL, each a proprietary language on its own |
| 20 | +engine. This script recreates the dataset as module-local tables plus a SQL |
| 21 | +property graph, then answers the query in **one statement**: `GRAPH_TABLE` |
| 22 | +(SQL/PGQ, ISO/IEC 9075-16) walks the knows-graph, `JSON_TABLE` (SQL/JSON, |
| 23 | +SQL:2016) unnests the order lines, a relational predicate filters on |
| 24 | +`credit_limit` — and an assertion checks the result set equals the survey's |
| 25 | +published answer **exactly**. `EXPLAIN PLAN` then shows graph, document, and |
| 26 | +relational access costed as ordinary row sources in a single plan tree. |
| 27 | + |
| 28 | +**Dataset note:** the survey publishes the customers, the query, and the |
| 29 | +result, but not the complete knows-edge topology or full order documents. The |
| 30 | +script constructs the minimal dataset consistent with the survey's published |
| 31 | +inputs and published result (Mary knows John and William; John's order |
| 32 | +contains product `2724f`, William's contains `3424g`); `Order_no`, |
| 33 | +`Product_Name`, and `Price` values are constructed placeholders in the |
| 34 | +survey's document shape. |
| 35 | + |
| 36 | +**DDL exception:** this script intentionally performs DDL, and DDL |
| 37 | +autocommits — the harness rollback cannot undo it. Cleanup is therefore |
| 38 | +explicit and asserted: every module-local object (`smm_` prefix) is dropped |
| 39 | +before the script ends, an idempotence guard at the top clears leftovers from |
| 40 | +interrupted runs, and the transactional `EXPLAIN PLAN` rows are deleted before |
| 41 | +the autocommitting drops so `plan_table` is left unchanged too. |
| 42 | + |
| 43 | +Expected assertions: |
| 44 | + |
| 45 | +``` |
| 46 | +ASSERT:survey-result-exact:PASS |
| 47 | +ASSERT:plan-captured:PASS |
| 48 | +ASSERT:plan-spans-graph:PASS |
| 49 | +ASSERT:plan-spans-relational:PASS |
| 50 | +ASSERT:plan-spans-document:PASS |
| 51 | +ASSERT:plan-evaluates-json:PASS |
| 52 | +ASSERT:one-plan-tree:PASS |
| 53 | +ASSERT:smm-tables-dropped:PASS |
| 54 | +ASSERT:smm-graph-dropped:PASS |
| 55 | +ASSERT:plan-table-clean:PASS |
| 56 | +``` |
| 57 | + |
| 58 | +## Proof 2: `scripts/02-one-enforcement-domain.js` |
| 59 | + |
| 60 | +**Article claim: one enforcement domain — the same constraint guards every |
| 61 | +API.** The shared domain declares `CHECK (qty > 0)` on `order_items`. The |
| 62 | +script pushes `qty: -1` through the MongoDB document API (an `updateOne` on |
| 63 | +the `order_dv` duality view) and gets a `MongoServerError` carrying |
| 64 | +`ORA-02290` (check-constraint violated); it then submits the same violation as |
| 65 | +a SQL `UPDATE` through the `$sql` aggregation stage on the same connection and |
| 66 | +gets the same `ORA-02290`. Document and rows verified unchanged after both |
| 67 | +attempts. The constraint lives in the engine, beneath every surface — there is |
| 68 | +no per-API validation layer to drift. |
| 69 | + |
| 70 | +**Error-text note:** the exact `MongoServerError` message format (ORA-42692 |
| 71 | +wrapping ORA-02290 on the document path; bare ORA-02290 via `$sql`) is |
| 72 | +observed behavior on Oracle AI Database 26ai Free as of June 2026, not a |
| 73 | +documented contract. Assertions match only the documented element — the |
| 74 | +ORA-02290 code. |
| 75 | + |
| 76 | +Expected assertions: |
| 77 | + |
| 78 | +``` |
| 79 | +ASSERT:doc-read:PASS |
| 80 | +ASSERT:mongo-api-rejected:PASS |
| 81 | +ASSERT:doc-unchanged:PASS |
| 82 | +ASSERT:sql-update-rejected:PASS |
| 83 | +ASSERT:final-state-unchanged:PASS |
| 84 | +``` |
| 85 | + |
| 86 | +## Proof 3: `scripts/03-read-after-write-search.sql` |
| 87 | + |
| 88 | +**Article claim: transactional read-after-write text search.** The script |
| 89 | +inserts a support ticket containing a unique marker token, COMMITs, and |
| 90 | +immediately finds it with `CONTAINS` — then deletes it, COMMITs, and |
| 91 | +immediately does not. Search visibility arrives with the commit, in the same |
| 92 | +engine, with no separate search process, change stream, or refresh interval. |
| 93 | +The lab's `ticket_text_idx` is created with `PARAMETERS ('SYNC (ON COMMIT)')` |
| 94 | +(`docker/init/05-text-vector.sql`), so the text index syncs inside the |
| 95 | +committing transaction. |
| 96 | + |
| 97 | +**Commit exception:** this script intentionally COMMITs (read-after-write can |
| 98 | +only be shown across a real commit boundary), so the harness rollback does not |
| 99 | +apply; explicit, asserted cleanup restores the domain. It is reseed-safe — |
| 100 | +`ticket_id` is identity-generated and the probe row is addressed only by its |
| 101 | +unique subject/marker, never a fixed id. |
| 102 | + |
| 103 | +Expected assertions: |
| 104 | + |
| 105 | +``` |
| 106 | +ASSERT:contains-finds-committed-write:PASS |
| 107 | +ASSERT:contains-after-cleanup:PASS |
| 108 | +ASSERT:probe-rows-gone:PASS |
| 109 | +``` |
| 110 | + |
| 111 | +## Cross-reference: the one-optimizer proof lives in module 01 |
| 112 | + |
| 113 | +The companion article also leans on **one cost-based plan spanning graph, |
| 114 | +document, vector, and relational** access. That evidence is module 01's |
| 115 | +[`05-one-plan.sql`](../01-what-is-a-converged-database/scripts/05-one-plan.sql) |
| 116 | +(`EXPLAIN PLAN` over the shared domain: `GRAPH_TABLE` + JSON predicate + |
| 117 | +`VECTOR_DISTANCE` + relational joins in one plan tree). Leaf article 2 quotes |
| 118 | +that proof; this module deliberately does not duplicate it — proof 1's plan |
| 119 | +assertions here cover the survey statement specifically. |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +## Run It Yourself |
| 124 | + |
| 125 | +```bash |
| 126 | +docker compose up -d --build oracle |
| 127 | +pip install -r validator/requirements.txt |
| 128 | +python validator/run.py |
| 129 | +``` |
| 130 | + |
| 131 | +The validator runs every script (modules 01 and 02) and exits 0 only if all |
| 132 | +assertions pass. |
| 133 | + |
| 134 | +**These proofs leave the seeded domain unchanged.** Two scripts in this module |
| 135 | +are documented exceptions to the rollback contract — proof 1 performs DDL |
| 136 | +(autocommits) and proof 3 COMMITs — so both clean up explicitly and assert the |
| 137 | +cleanup, which keeps the validator repeatable: run it any number of times with |
| 138 | +identical results. |
0 commit comments