@crvouga/mockingbird-service-postgres 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Changelog — @crvouga/mockingbird-service-postgres
2
2
 
3
- ## 3.9.0 (2026-10-21)
3
+ ## 3.10.0 (2026-10-21)
4
+
5
+ ### Features
6
+
7
+ - add LifeFile and fix JSONB CASE typing ([6c5396b](https://github.com/crvouga/mockingbird/commit/6c5396bb2bbf0ab3f728471f0bdbee985d3a6c6e))
8
+
9
+ ## 3.9.0 (2026-10-20)
4
10
 
5
11
  ### Features
6
12
 
package/COMPATIBILITY.md CHANGED
@@ -78,7 +78,7 @@ The oracle exposes **2787 builtin functions** and **74 operators** in `pg_catalo
78
78
  | Date/time: date, time, timestamp[tz], interval + arithmetic | VERIFIED | Timezone conversions for named zones; some interval corners partial |
79
79
  | Casts (implicit/assignment/explicit) | VERIFIED | Generated cast matrices from oracle |
80
80
  | Arrays + unnest + subscripts/slices | VERIFIED | |
81
- | JSON / JSONB operators + functions | VERIFIED | |
81
+ | JSON / JSONB operators + functions | VERIFIED | JSONB CASE branches preserve the JSONB type for selected untyped NULL/literal results, including empty LATERAL sources and nested views. Type hints cover column references, casts, JSON extraction operators and nested CASE without executing unselected result expressions; arbitrary function-result branch inference remains partial (`tests/contract/regressions/jsonb-case-types.test.ts`) |
82
82
  | Window functions (frames, EXCLUDE) | VERIFIED | |
83
83
  | GROUPING SETS / ROLLUP / CUBE, DISTINCT ON, LATERAL, set ops | VERIFIED | |
84
84
  | Recursive + data-modifying CTEs | VERIFIED | |
package/dist/admin.js CHANGED
@@ -15743,6 +15743,45 @@ function validateCaseSubExpr(ctx, scope, e) {
15743
15743
  return;
15744
15744
  }
15745
15745
  }
15746
+ function caseBranchType(ctx, scope, e) {
15747
+ switch (e.type) {
15748
+ case "null_lit":
15749
+ case "string_lit":
15750
+ return UNKNOWN;
15751
+ case "number_lit":
15752
+ return numberLitValue(e.raw).t;
15753
+ case "bool_lit":
15754
+ return "bool";
15755
+ case "colref":
15756
+ return scope.lookupColumn(e.parts)?.t ?? null;
15757
+ case "cast":
15758
+ return resolveTypeName(ctx.state, e.target).column.id;
15759
+ case "collate":
15760
+ return caseBranchType(ctx, scope, e.expr);
15761
+ case "binop": {
15762
+ const left = caseBranchType(ctx, scope, e.left);
15763
+ if (left !== "json" && left !== "jsonb") return null;
15764
+ if (e.op === "->" || e.op === "#>") return left;
15765
+ if (e.op === "->>" || e.op === "#>>") return "text";
15766
+ return null;
15767
+ }
15768
+ case "case": {
15769
+ let type = UNKNOWN;
15770
+ const branches = [...e.whens.map((w) => w.then), ...e.elseExpr ? [e.elseExpr] : []];
15771
+ for (const branch of branches) {
15772
+ const next = caseBranchType(ctx, scope, branch);
15773
+ if (next === null) return null;
15774
+ if (next === UNKNOWN) continue;
15775
+ const unified = unifyTypes(type, next);
15776
+ if (unified === null) return null;
15777
+ type = unified;
15778
+ }
15779
+ return type;
15780
+ }
15781
+ default:
15782
+ return null;
15783
+ }
15784
+ }
15746
15785
  function evalCase(ctx, scope, e) {
15747
15786
  validateSearchedCaseTree(ctx, scope, e);
15748
15787
  let chosen = null;
@@ -15766,8 +15805,10 @@ function evalCase(ctx, scope, e) {
15766
15805
  }
15767
15806
  }
15768
15807
  const resultExpr = chosen ?? e.elseExpr;
15769
- if (resultExpr === null) return tv(UNKNOWN, null);
15770
- return evalExpr(ctx, scope, resultExpr);
15808
+ const result = resultExpr === null ? tv(UNKNOWN, null) : evalExpr(ctx, scope, resultExpr);
15809
+ if (result.t !== UNKNOWN) return result;
15810
+ const type = caseBranchType(ctx, scope, e);
15811
+ return type !== null && type !== UNKNOWN ? castTo(ctx, result, type, {}) : result;
15771
15812
  }
15772
15813
  function evalIn(ctx, scope, e) {
15773
15814
  const left = evalExpr(ctx, scope, e.left);