You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/FUNCTIONAL_NULL_SAFETY.md
+34-2Lines changed: 34 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -215,9 +215,39 @@ This suite validates parser translation, `OPTIONALLY FROM`, `IS SOME` / `IS NONE
215
215
216
216
---
217
217
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
+
218
248
## Verify It Yourself
219
249
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.
221
251
222
252
### Prerequisites
223
253
@@ -254,11 +284,13 @@ dotnet test tests/SharpCoreDB.Functional.Tests --filter "FullyQualifiedName~Null
254
284
| 10 |`WriteOperation_FinCapturesErrorsAsValues`|`Fin<T>` captures insert failure as value, not exception |
255
285
| 11 |`Pipeline_OptionSeqProvidesSafeComposition`|`Option` pipeline filters null/empty emails without exceptions |
256
286
| 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 |
0 commit comments