|
| 1 | +# converged-database-lab |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +Runnable proofs for the converged-database article series — every technical claim in the articles executes here, nightly, against a free container. |
| 6 | + |
| 7 | +**One truth. Many shapes. Every claim runs.** |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## About the name: 26ai vs 23.26.x |
| 12 | + |
| 13 | +Oracle AI Database 26ai is the product name — a long-term-support release announced October 2025. Container tags use a year.quarter version string convention, so `gvenzl/oracle-free:23.26.x` tags are the 26ai release line. Prose in this repo always says 26ai; the version string appears only where a tag or connection string requires it. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Quickstart |
| 18 | + |
| 19 | +```bash |
| 20 | +docker compose up -d --build oracle # ~2 GB image; first boot seeds the domain (~2 min) |
| 21 | +pip install -r validator/requirements.txt |
| 22 | +python validator/run.py # runs every module, prints ASSERT results |
| 23 | +``` |
| 24 | + |
| 25 | +If the container goes `unhealthy`, check `docker logs lab-oracle` — the most common cause is an ORDS install failure on first boot; `docker compose down -v && docker compose up -d --build oracle` usually resolves it. |
| 26 | + |
| 27 | +**Connection cheatsheet** |
| 28 | + |
| 29 | +| Interface | Connection string | |
| 30 | +|-----------|-------------------| |
| 31 | +| SQL | `LAB_USER/LabUser2026@localhost:1521/FREEPDB1` | |
| 32 | +| MongoDB API | `mongodb://LAB_USER:LabUser2026@localhost:27017/lab_user?authMechanism=PLAIN&authSource=$external&tls=false&loadBalanced=true&retryWrites=false` | |
| 33 | +| ORDS | `http://localhost:8181` | |
| 34 | + |
| 35 | +These are demo credentials. Override via `.env` — see `.env.example`. |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## The shared domain |
| 40 | + |
| 41 | +All modules run against one deterministically seeded domain. Seeds use an LCG (seed 42) so `docker compose down -v && docker compose up -d --build oracle` produces byte-for-byte identical data every rebuild. |
| 42 | + |
| 43 | +**Tables** |
| 44 | + |
| 45 | +| Object | Rows | Data model exercised | |
| 46 | +|--------|------|----------------------| |
| 47 | +| `customers` | 200 | Relational — primary entity, FK target | |
| 48 | +| `products` | 50 | Relational + JSON (`attributes` column: color, warrantyMonths) | |
| 49 | +| `stores` | 6 | Relational + Spatial (`SDO_GEOMETRY`, WGS-84 coordinates) | |
| 50 | +| `orders` | 1,000 | Relational — transactional fact table | |
| 51 | +| `order_items` | ~2,500 (avg 2.5/order) | Relational — composite PK, line items | |
| 52 | +| `devices` | 40 | Relational — device fingerprints | |
| 53 | +| `customer_devices` | 200 | Relational — M:M link; graph edge source | |
| 54 | +| `referrals` | 64 | Relational — self-referential; graph edge source (60 chain + 4-hop cycle 10→11→12→13→10) | |
| 55 | +| `support_tickets` | 300 | Relational + Vector (`VECTOR(8, FLOAT32)` — 8-dim demo embeddings, see note) | |
| 56 | + |
| 57 | +**JSON collection table** |
| 58 | + |
| 59 | +| Object | Data model exercised | |
| 60 | +|--------|----------------------| |
| 61 | +| `events` | JSON-native collection (Oracle `JSON COLLECTION TABLE`) | |
| 62 | + |
| 63 | +**JSON Relational Duality Views** |
| 64 | + |
| 65 | +| View | Projection | |
| 66 | +|------|------------| |
| 67 | +| `customer_profile_dv` | Customer + nested orders + line items; writeable via MongoDB API | |
| 68 | +| `order_dv` | Order-centric shape over the same rows — second projection of one stored truth | |
| 69 | + |
| 70 | +**Property graph** |
| 71 | + |
| 72 | +| Object | Vertices / Edges | |
| 73 | +|--------|-----------------| |
| 74 | +| `customer_graph` | 240 vertices (200 customers + 40 devices); 264 edges (200 `customer_devices` + 64 `referrals`) | |
| 75 | + |
| 76 | +**Indexes** |
| 77 | + |
| 78 | +| Index | Type | Purpose | |
| 79 | +|-------|------|---------| |
| 80 | +| `idx_orders_customer` | B-tree | Customer order range scans | |
| 81 | +| `idx_items_product` | B-tree | Product-level aggregations | |
| 82 | +| `idx_tickets_customer` | B-tree | Per-customer ticket lookups | |
| 83 | +| `ticket_text_idx` | Oracle Text (SEARCH INDEX) | Full-text keyword search on ticket bodies | |
| 84 | +| `ticket_vec_idx` | Vector IVF (NEIGHBOR PARTITIONS, COSINE) | Approximate nearest-neighbor on embeddings | |
| 85 | + |
| 86 | +**Note on embeddings:** The 8-dim vectors are deterministic demo values generated by the LCG seed. All engine behaviors demonstrated (distance functions, vector indexes, transactions, cross-model joins) are dimension-independent. Module 03 documents the optional real-model flow using `DBMS_VECTOR.LOAD_ONNX_MODEL` with all-MiniLM-L12-v2. |
| 87 | + |
| 88 | +**Oracle AI Database 26ai Free limits:** 2 CPU / 2 GB SGA+PGA / 12 GB data. The compose file caps the container at 2 CPUs and 4 GB (headroom for ORDS and OS overhead). |
| 89 | + |
| 90 | +--- |
| 91 | + |
| 92 | +## Modules |
| 93 | + |
| 94 | +| # | Slug | Status | Proofs | Assertions | Links | |
| 95 | +|---|------|--------|--------|------------|-------| |
| 96 | +| 01 | `what-is-a-converged-database` | Live | 4 | 14 | [README](modules/01-what-is-a-converged-database/README.md) · article link lands at publish | |
| 97 | +| 02 | `converged-vs-multi-model` | Arrives with its article | — | — | — | |
| 98 | +| 03 | `vector-db-vs-converged` | Arrives with its article | — | — | — | |
| 99 | +| 04 | `ai-agents-enterprise-data` | Arrives with its article | — | — | — | |
| 100 | +| 05 | `json-graph-vector-relational-one-db` | Arrives with its article | — | — | — | |
| 101 | +| 06 | `polyglot-vs-converged` | Arrives with its article | — | — | — | |
| 102 | +| 07 | `reading-stonebraker-and-pavlo` | Arrives with its article | — | — | — | |
| 103 | + |
| 104 | +--- |
| 105 | + |
| 106 | +## Validation contract |
| 107 | + |
| 108 | +Scripts live in `modules/NN-slug/scripts/` and run in lexical order — modules first, then scripts within each module. |
| 109 | + |
| 110 | +- **`*.sql`** — executed statement-by-statement via python-oracledb (thin mode) as `LAB_USER` against `localhost:1521/FREEPDB1`. PL/SQL blocks end with a line containing only `/`; plain SQL ends with `;`. The harness rolls back after each script so demos leave the domain unchanged. |
| 111 | +- **`*.js`** — executed with `mongosh` inside the `lab-oracle` container against the MongoDB API (port 27017). JS scripts auto-commit through the MongoDB API, so they must clean up explicitly — delete what they insert, restore what they update. |
| 112 | + |
| 113 | +**Assertion convention:** SQL scripts assert by SELECTing a string of the form `ASSERT:<name>:PASS|FAIL` as the first column. JS scripts `print()` the same string. The validator harvests these lines and reports per-script. |
| 114 | + |
| 115 | +**Results:** written to `validator/results.json` (gitignored). |
| 116 | + |
| 117 | +**CI:** runs on push to `main`/`article/**`, on pull requests, and on a nightly cron (`17 6 * * *`). The job uploads `results.json` as a build artifact. |
| 118 | + |
| 119 | +See [validator/README.md](validator/README.md) for the full authoring contract. |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +## MongoDB comparison profile |
| 124 | + |
| 125 | +```bash |
| 126 | +docker compose --profile mongodb up -d |
| 127 | +``` |
| 128 | + |
| 129 | +Boots `mongo:8.2` as a single-node replica set (required for transactions) on host port 27027. Used for head-to-head demos in modules 03 and 06. |
| 130 | + |
| 131 | +**Beta note:** `$vectorSearch`, `$search`, and `$changeStream` are beta in the Oracle 26ai MongoDB API per Oracle documentation. Modules that use these stages label them explicitly. |
| 132 | + |
| 133 | +--- |
| 134 | + |
| 135 | +## Related work |
| 136 | + |
| 137 | +- [github.com/rhoulihan/unified-model-theory](https://github.com/rhoulihan/unified-model-theory) — the UMT framework this lab demonstrates |
| 138 | +- Article links added as they publish |
| 139 | + |
| 140 | +--- |
| 141 | + |
| 142 | +## License |
| 143 | + |
| 144 | +Universal Permissive License v1.0 — see [LICENSE](LICENSE). |
0 commit comments