Skip to content

Commit 39aa8d8

Browse files
author
MPCoreDeveloper
committed
test(docs): prove NULL semantics limits and exception vs Option cost
1 parent c07b8a6 commit 39aa8d8

2 files changed

Lines changed: 543 additions & 2 deletions

File tree

docs/FUNCTIONAL_NULL_SAFETY.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,39 @@ This suite validates parser translation, `OPTIONALLY FROM`, `IS SOME` / `IS NONE
215215

216216
---
217217

218+
## Why "Databases return NULL, so why not just use NULL?"
219+
220+
This objection is valid at SQL level: databases should return `NULL` / empty sets for missing data.
221+
222+
The practical issue is the **application boundary**:
223+
224+
- SQL returns `NULL` (or empty string in some providers)
225+
- application code often assumes value presence
226+
- the failure then appears as app-level exceptions (`NullReferenceException`, index errors, mapping failures)
227+
228+
So the goal is **not** "replace SQL NULL with exceptions".
229+
The goal is: make absence explicit in types (`Option<T>`) so missing data stays a value, not a crash path.
230+
231+
### Static analysis limit (core point)
232+
233+
You can only remove null branches when non-nullability is provable for every row at compile time.
234+
For real queries that is often impossible due to runtime data shape (missing references, partial projections, semantic nulls like `""` or `"NULL"`).
235+
236+
### Cost proof
237+
238+
In .NET, branch checks are cheap; thrown exceptions are expensive.
239+
The added proof test compares:
240+
241+
1. exception-driven missing-data handling
242+
2. `Option<T>`-driven missing-data handling
243+
244+
and verifies the `Option` path is faster for the same workload.
245+
246+
---
247+
218248
## Verify It Yourself
219249

220-
All claims above are backed by **12 passing tests** you can run right now.
250+
All claims above are backed by **14 passing tests** you can run right now.
221251

222252
### Prerequisites
223253

@@ -254,11 +284,13 @@ dotnet test tests/SharpCoreDB.Functional.Tests --filter "FullyQualifiedName~Null
254284
| 10 | `WriteOperation_FinCapturesErrorsAsValues` | `Fin<T>` captures insert failure as value, not exception |
255285
| 11 | `Pipeline_OptionSeqProvidesSafeComposition` | `Option` pipeline filters null/empty emails without exceptions |
256286
| 12 | `RealWorkload_BatchLookupWithMissingReferences` | 100 batch lookups with ~50% missing FKs — all handled via `Option.Match`, zero exceptions |
287+
| 13 | `SemanticNulls_CannotBeProvenStaticallyForRuntimeRows` | Runtime row semantics (`null`, `""`, `"NULL"`) cannot be fully proven at compile time |
288+
| 14 | `ExceptionDrivenMissingData_IsSlowerThanOptionFlow` | Exception-based control flow is slower than `Option`-based value flow for missing-data handling |
257289

258290
### Expected Output
259291

260292
```
261-
Passed! - Failed: 0, Passed: 12, Skipped: 0, Total: 12
293+
Passed! - Failed: 0, Passed: 14, Skipped: 0, Total: 14
262294
```
263295

264296
---

0 commit comments

Comments
 (0)