effect-qb 0.13.0 → 0.14.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.
Files changed (54) hide show
  1. package/README.md +6 -1431
  2. package/dist/mysql.js +1678 -355
  3. package/dist/postgres/metadata.js +2724 -0
  4. package/dist/postgres.js +7197 -5433
  5. package/package.json +8 -10
  6. package/src/internal/column-state.ts +84 -10
  7. package/src/internal/column.ts +556 -34
  8. package/src/internal/datatypes/define.ts +0 -30
  9. package/src/internal/executor.ts +45 -11
  10. package/src/internal/expression-ast.ts +4 -0
  11. package/src/internal/expression.ts +1 -1
  12. package/src/internal/implication-runtime.ts +171 -0
  13. package/src/internal/mysql-query.ts +7173 -0
  14. package/src/internal/mysql-renderer.ts +2 -2
  15. package/src/internal/plan.ts +14 -4
  16. package/src/internal/{query-factory.ts → postgres-query.ts} +619 -167
  17. package/src/internal/postgres-renderer.ts +2 -2
  18. package/src/internal/postgres-schema-model.ts +144 -0
  19. package/src/internal/predicate-analysis.ts +10 -0
  20. package/src/internal/predicate-context.ts +112 -36
  21. package/src/internal/predicate-formula.ts +31 -19
  22. package/src/internal/predicate-normalize.ts +177 -106
  23. package/src/internal/predicate-runtime.ts +676 -0
  24. package/src/internal/query.ts +455 -39
  25. package/src/internal/renderer.ts +2 -2
  26. package/src/internal/runtime-schema.ts +74 -20
  27. package/src/internal/schema-ddl.ts +55 -0
  28. package/src/internal/schema-derivation.ts +93 -21
  29. package/src/internal/schema-expression.ts +44 -0
  30. package/src/internal/sql-expression-renderer.ts +95 -31
  31. package/src/internal/table-options.ts +87 -7
  32. package/src/internal/table.ts +104 -41
  33. package/src/mysql/column.ts +1 -0
  34. package/src/mysql/datatypes/index.ts +17 -2
  35. package/src/mysql/function/core.ts +1 -0
  36. package/src/mysql/function/index.ts +1 -0
  37. package/src/mysql/private/query.ts +1 -13
  38. package/src/mysql/query.ts +5 -0
  39. package/src/postgres/cast.ts +31 -0
  40. package/src/postgres/column.ts +26 -0
  41. package/src/postgres/datatypes/index.ts +40 -5
  42. package/src/postgres/function/core.ts +12 -0
  43. package/src/postgres/function/index.ts +2 -1
  44. package/src/postgres/function/json.ts +499 -2
  45. package/src/postgres/metadata.ts +31 -0
  46. package/src/postgres/private/query.ts +1 -13
  47. package/src/postgres/query.ts +5 -2
  48. package/src/postgres/schema-expression.ts +16 -0
  49. package/src/postgres/schema-management.ts +204 -0
  50. package/src/postgres/schema.ts +35 -0
  51. package/src/postgres/table.ts +307 -41
  52. package/src/postgres/type.ts +4 -0
  53. package/src/postgres.ts +14 -0
  54. package/CHANGELOG.md +0 -134
@@ -9,8 +9,10 @@ import type { JsonNode } from "./json/ast.js"
9
9
  import type * as JsonPath from "./json/path.js"
10
10
  import type { QueryCapability } from "./query-requirements.js"
11
11
  import type { CaseBranchAssumeFalse, CaseBranchAssumeTrue, CaseBranchDecision } from "./case-analysis.js"
12
- import type { GuaranteedNonNullKeys, GuaranteedNullKeys, GuaranteedSourceNames } from "./predicate-analysis.js"
12
+ import type { ContradictsFormula, GuaranteedNonNullKeys, GuaranteedNullKeys, GuaranteedSourceNames } from "./predicate-analysis.js"
13
+ import type { ColumnKeyOfExpression } from "./predicate-key.js"
13
14
  import type { PredicateFormula, TrueFormula } from "./predicate-formula.js"
15
+ import { trueFormula } from "./predicate-runtime.js"
14
16
 
15
17
  export type {
16
18
  MergeCapabilities,
@@ -416,7 +418,7 @@ export type ExtractDialect<Selection> = Selection extends Expression.Any
416
418
  * The query layer only needs the plan metadata and the static table name. It
417
419
  * deliberately avoids depending on the full table-definition surface.
418
420
  */
419
- export type TableLike<Name extends string = string, Dialect extends string = string> = Plan.Plan<any, any, Record<string, Plan.Source>, Dialect> & {
421
+ export type TableLike<Name extends string = string, Dialect extends string = string> = Plan.Plan<any, any, Record<string, Plan.AnySource>, Dialect> & {
420
422
  readonly [Table.TypeId]: {
421
423
  readonly name: Name
422
424
  readonly baseName: string
@@ -642,6 +644,240 @@ export type MutationTargetLike = Table.AnyTable
642
644
  export type MutationTargetTuple = readonly [MutationTargetLike, MutationTargetLike, ...MutationTargetLike[]]
643
645
  export type MutationTargetInput = MutationTargetLike | MutationTargetTuple
644
646
 
647
+ type JsonMutationDbKindError<
648
+ ColumnName extends string,
649
+ ExpectedKind extends string,
650
+ ReceivedKind extends string
651
+ > = {
652
+ readonly __effect_qb_error__: "effect-qb: incompatible postgres json mutation value"
653
+ readonly __effect_qb_column__: ColumnName
654
+ readonly __effect_qb_reason__: "postgres json/jsonb kinds do not match"
655
+ readonly __effect_qb_expected_json_kind__: ExpectedKind
656
+ readonly __effect_qb_received_json_kind__: ReceivedKind
657
+ readonly __effect_qb_hint__: "Use postgres.Function.json for json columns and postgres.Function.jsonb for jsonb columns"
658
+ }
659
+
660
+ type JsonMutationShapeError<
661
+ ColumnName extends string,
662
+ Expected,
663
+ Received
664
+ > = {
665
+ readonly __effect_qb_error__: "effect-qb: incompatible postgres json mutation value"
666
+ readonly __effect_qb_column__: ColumnName
667
+ readonly __effect_qb_reason__: "json value is not assignable to the target column schema"
668
+ readonly __effect_qb_json_issues__: JsonShapeIssues<Expected, Received>
669
+ readonly __effect_qb_hint__: "Inspect __effect_qb_json_issues__ or the __effect_qb_json_issue__... sentinel keys to find the failing nested paths"
670
+ } & JsonIssueSentinels<Expected, Received>
671
+
672
+ type MutationValueShapeError<
673
+ ColumnName extends string,
674
+ Expected,
675
+ Received
676
+ > = {
677
+ readonly __effect_qb_error__: "effect-qb: incompatible mutation value"
678
+ readonly __effect_qb_column__: ColumnName
679
+ readonly __effect_qb_reason__: "value is not assignable to the target column schema"
680
+ readonly __effect_qb_expected_type__: Expected
681
+ readonly __effect_qb_received_type__: Received
682
+ }
683
+
684
+ type MutationUnknownColumnError<ColumnName extends string> = {
685
+ readonly __effect_qb_error__: "effect-qb: unknown mutation column"
686
+ readonly __effect_qb_column__: ColumnName
687
+ readonly __effect_qb_hint__: "Use only columns that exist on the target table"
688
+ }
689
+
690
+ type MutationRequiredKeys<Shape> = Extract<{
691
+ [K in keyof Shape]-?: {} extends Pick<Shape, K> ? never : K
692
+ }[keyof Shape], string>
693
+
694
+ type MutationExtraKeys<TargetShape, SourceShape> = Exclude<Extract<keyof SourceShape, string>, Extract<keyof TargetShape, string>>
695
+
696
+ type MutationMissingKeys<TargetShape, SourceShape> = Exclude<MutationRequiredKeys<TargetShape>, Extract<keyof SourceShape, string>>
697
+
698
+ type JsonPathDisplay<Path extends string> = Path extends "" ? "(root)" : Path
699
+
700
+ type JsonObjectKeyPath<Path extends string, Key extends string> = Path extends ""
701
+ ? Key
702
+ : `${Path}.${Key}`
703
+
704
+ type JsonArrayPath<Path extends string> = Path extends ""
705
+ ? "[number]"
706
+ : `${Path}[number]`
707
+
708
+ type JsonIssueKeyPath<Path extends string> = Path extends ""
709
+ ? "root"
710
+ : Path
711
+
712
+ type JsonShapeIssue<
713
+ Path extends string,
714
+ Kind extends string,
715
+ Expected,
716
+ Received
717
+ > = {
718
+ readonly path: JsonPathDisplay<Path>
719
+ readonly issue: Kind
720
+ readonly expected: Expected
721
+ readonly received: Received
722
+ }
723
+
724
+ type JsonSharedKeys<Expected, Received> = Extract<Extract<keyof Expected, keyof Received>, string>
725
+
726
+ type JsonIssueSentinelKeys<Issues> = Issues extends {
727
+ readonly path: infer Path extends string
728
+ readonly issue: infer Kind extends string
729
+ }
730
+ ? `__effect_qb_json_issue__${JsonIssueKeyPath<Path>}__${Kind}`
731
+ : never
732
+
733
+ type JsonIssueSentinels<
734
+ Expected,
735
+ Received
736
+ > = {
737
+ readonly [K in JsonIssueSentinelKeys<JsonShapeIssues<Expected, Received>>]: true
738
+ }
739
+
740
+ type JsonObjectShapeIssues<
741
+ Expected extends object,
742
+ Received extends object,
743
+ Path extends string
744
+ > =
745
+ | {
746
+ readonly [K in MutationMissingKeys<Expected, Received>]:
747
+ JsonShapeIssue<JsonObjectKeyPath<Path, K>, "missing_required_property", Expected[K], undefined>
748
+ }[MutationMissingKeys<Expected, Received>]
749
+ | {
750
+ readonly [K in JsonSharedKeys<Expected, Received>]:
751
+ JsonShapeIssues<Expected[K], Received[K], JsonObjectKeyPath<Path, K>>
752
+ }[JsonSharedKeys<Expected, Received>]
753
+
754
+ type JsonShapeIssues<
755
+ Expected,
756
+ Received,
757
+ Path extends string = ""
758
+ > = [Received] extends [Expected]
759
+ ? never
760
+ : [Expected] extends [readonly (infer ExpectedElement)[]]
761
+ ? [Received] extends [readonly (infer ReceivedElement)[]]
762
+ ? JsonShapeIssues<ExpectedElement, ReceivedElement, JsonArrayPath<Path>>
763
+ : JsonShapeIssue<Path, "type_mismatch", Expected, Received>
764
+ : [Expected] extends [object]
765
+ ? [Expected] extends [Function]
766
+ ? JsonShapeIssue<Path, "type_mismatch", Expected, Received>
767
+ : [Received] extends [object]
768
+ ? [Received] extends [Function]
769
+ ? JsonShapeIssue<Path, "type_mismatch", Expected, Received>
770
+ : JsonObjectShapeIssues<Expected & object, Received & object, Path> extends infer Issues
771
+ ? [Issues] extends [never]
772
+ ? JsonShapeIssue<Path, "type_mismatch", Expected, Received>
773
+ : Issues
774
+ : never
775
+ : JsonShapeIssue<Path, "type_mismatch", Expected, Received>
776
+ : JsonShapeIssue<Path, "type_mismatch", Expected, Received>
777
+
778
+ type MutationAcceptedInput<Column> =
779
+ Column extends Expression.Expression<infer Runtime, any, any, any, any, any, any, any>
780
+ ? MutationValueInput<Runtime>
781
+ : never
782
+
783
+ type MutationValueCompatibilityIssue<
784
+ Column,
785
+ Value,
786
+ ColumnName extends string
787
+ > = Column extends Expression.Expression<any, infer ColumnDb extends Expression.DbType.Any, any, any, any, any, any, any>
788
+ ? ColumnDb extends Expression.DbType.Json<"postgres", infer ExpectedKind>
789
+ ? Value extends Expression.Expression<any, infer ValueDb extends Expression.DbType.Any, any, any, any, any, any, any>
790
+ ? ValueDb extends Expression.DbType.Json<"postgres", infer ReceivedKind>
791
+ ? [ExpectedKind] extends [ReceivedKind]
792
+ ? [ReceivedKind] extends [ExpectedKind]
793
+ ? Value extends Expression.Expression<infer ReceivedRuntime, any, any, any, any, any, any, any>
794
+ ? Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
795
+ ? [ReceivedRuntime] extends [ExpectedRuntime]
796
+ ? never
797
+ : JsonMutationShapeError<ColumnName, ExpectedRuntime, ReceivedRuntime>
798
+ : never
799
+ : never
800
+ : JsonMutationDbKindError<ColumnName, ExpectedKind, ReceivedKind>
801
+ : JsonMutationDbKindError<ColumnName, ExpectedKind, ReceivedKind>
802
+ : Value extends Expression.Expression<infer ReceivedRuntime, any, any, any, any, any, any, any>
803
+ ? Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
804
+ ? [ReceivedRuntime] extends [ExpectedRuntime]
805
+ ? never
806
+ : JsonMutationShapeError<ColumnName, ExpectedRuntime, ReceivedRuntime>
807
+ : never
808
+ : Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
809
+ ? [Value] extends [ExpectedRuntime]
810
+ ? never
811
+ : JsonMutationShapeError<ColumnName, ExpectedRuntime, Value>
812
+ : never
813
+ : Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
814
+ ? [Value] extends [ExpectedRuntime]
815
+ ? never
816
+ : JsonMutationShapeError<ColumnName, ExpectedRuntime, Value>
817
+ : never
818
+ : Value extends Expression.Expression<infer ReceivedRuntime, any, any, any, any, any, any, any>
819
+ ? Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
820
+ ? [ReceivedRuntime] extends [ExpectedRuntime]
821
+ ? never
822
+ : MutationValueShapeError<ColumnName, ExpectedRuntime, ReceivedRuntime>
823
+ : never
824
+ : Column extends Expression.Expression<infer ExpectedRuntime, any, any, any, any, any, any, any>
825
+ ? [Value] extends [ExpectedRuntime]
826
+ ? never
827
+ : MutationValueShapeError<ColumnName, ExpectedRuntime, Value>
828
+ : never
829
+ : unknown
830
+
831
+ type MutationExpectedValue<
832
+ Column,
833
+ Value,
834
+ ColumnName extends string
835
+ > = [MutationValueCompatibilityIssue<Column, Value, ColumnName>] extends [never]
836
+ ? MutationAcceptedInput<Column>
837
+ : MutationValueCompatibilityIssue<Column, Value, ColumnName>
838
+
839
+ type MutationShapeOf<
840
+ Statement extends "insert" | "update",
841
+ Target extends MutationTargetLike
842
+ > = Statement extends "insert" ? Table.InsertOf<Target> : Table.UpdateOf<Target>
843
+
844
+ type MutationColumnAt<
845
+ Target extends MutationTargetLike,
846
+ Key extends string
847
+ > = Target extends {
848
+ readonly [Table.TypeId]: {
849
+ readonly fields: Record<Key, infer Column>
850
+ }
851
+ }
852
+ ? Column
853
+ : never
854
+
855
+ type MutationValueShape<
856
+ Shape,
857
+ Target extends MutationTargetLike,
858
+ Values extends Record<string, unknown>
859
+ > = {
860
+ readonly [K in Extract<keyof Values, string>]:
861
+ K extends Extract<keyof Shape, string>
862
+ ? MutationExpectedValue<MutationColumnAt<Target, K>, Values[K], K>
863
+ : MutationUnknownColumnError<K>
864
+ }
865
+
866
+ type MutationKeyShape<Shape> = {
867
+ readonly [K in keyof Shape]: unknown
868
+ }
869
+
870
+ export type MutationValuesInput<
871
+ Statement extends "insert" | "update",
872
+ Target extends MutationTargetLike,
873
+ Values extends Record<string, unknown>,
874
+ Shape = MutationShapeOf<Statement, Target>
875
+ > = Simplify<
876
+ Values &
877
+ MutationKeyShape<Shape> &
878
+ MutationValueShape<Shape, Target, Values>
879
+ >
880
+
645
881
  /** Extracts a source name from either a table or a derived source. */
646
882
  export type SourceNameOf<Source extends SourceLike> =
647
883
  Source extends TableLike<infer Name, any> ? Name :
@@ -760,10 +996,10 @@ export type TableNameOf<T extends TableLike> = T[typeof Table.TypeId]["name"]
760
996
  /** Extracts the effective dialect from a table-like value. */
761
997
  export type TableDialectOf<T extends TableLike> = T[typeof Plan.TypeId]["dialect"]
762
998
  /** Names of sources already available to a plan. */
763
- type AvailableNames<Available extends Record<string, Plan.Source>> = Extract<keyof Available, string>
999
+ type AvailableNames<Available extends Record<string, Plan.AnySource>> = Extract<keyof Available, string>
764
1000
  /** Availability mode of a named source within the current plan scope. */
765
1001
  type SourceModeOf<
766
- Available extends Record<string, Plan.Source>,
1002
+ Available extends Record<string, Plan.AnySource>,
767
1003
  Name extends string
768
1004
  > = Name extends keyof Available ? Available[Name]["mode"] : never
769
1005
  type TrueAssumptions = TrueFormula
@@ -810,23 +1046,46 @@ export type MutationTargetOfPlan<PlanValue extends QueryPlan<any, any, any, any,
810
1046
  export type InsertSourceStateOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
811
1047
  PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any, any, infer InsertState> ? InsertState : "ready"
812
1048
 
1049
+ type PresenceWitnessKeysOfSelection<Selection> = Selection extends Expression.Any
1050
+ ? AstOf<Selection> extends ExpressionAst.ColumnNode<any, any>
1051
+ ? Expression.NullabilityOf<Selection> extends "never"
1052
+ ? ColumnKeyOfExpression<Selection>
1053
+ : never
1054
+ : never
1055
+ : Selection extends Record<string, any>
1056
+ ? {
1057
+ readonly [K in keyof Selection]: PresenceWitnessKeysOfSelection<Selection[K]>
1058
+ }[keyof Selection]
1059
+ : never
1060
+
1061
+ export type PresenceWitnessKeysOfSource<Source extends SourceLike> =
1062
+ Source extends TableLike<any, any>
1063
+ ? PresenceWitnessKeysOfSelection<Source[typeof Plan.TypeId]["selection"]>
1064
+ : Source extends { readonly columns: infer Columns }
1065
+ ? PresenceWitnessKeysOfSelection<Columns>
1066
+ : never
1067
+
813
1068
  /**
814
1069
  * Adds a single source entry to the set of available sources.
815
1070
  *
816
1071
  * This is used by `from(...)` and the join builders.
817
1072
  */
818
1073
  export type AddAvailable<
819
- Available extends Record<string, Plan.Source>,
1074
+ Available extends Record<string, Plan.AnySource>,
820
1075
  Name extends string,
821
- Mode extends Plan.SourceMode = "required"
822
- > = Available & Record<Name, Plan.Source<Name, Mode>>
1076
+ Mode extends Plan.SourceMode = "required",
1077
+ PresentFormula extends PredicateFormula = TrueFormula,
1078
+ PresenceWitness extends string = never
1079
+ > = Available & Record<Name, Plan.Source<Name, Mode, PresentFormula, PresenceWitness>>
823
1080
 
824
1081
  export type AddAvailableMany<
825
- Available extends Record<string, Plan.Source>,
1082
+ Available extends Record<string, Plan.AnySource>,
826
1083
  Names extends string,
827
- Mode extends Plan.SourceMode = "required"
1084
+ Mode extends Plan.SourceMode = "required",
1085
+ PresentFormula extends PredicateFormula = TrueFormula,
1086
+ PresenceWitness extends string = never
828
1087
  > = Available & {
829
- readonly [K in Names]: Plan.Source<K, Mode>
1088
+ readonly [K in Names]: Plan.Source<K, Mode, PresentFormula, PresenceWitness>
830
1089
  }
831
1090
 
832
1091
  /** Join mode projected into the plan's source-scope mode lattice. */
@@ -835,25 +1094,38 @@ export type JoinSourceMode<Kind extends QueryAst.JoinKind> = Kind extends "left"
835
1094
  : "required"
836
1095
 
837
1096
  type DemoteAllAvailable<
838
- Available extends Record<string, Plan.Source>
1097
+ Available extends Record<string, Plan.AnySource>
839
1098
  > = {
840
- readonly [K in keyof Available]: Available[K] extends Plan.Source<infer Name extends string, any>
841
- ? Plan.Source<Name, "optional">
1099
+ readonly [K in keyof Available]: Available[K] extends Plan.Source<
1100
+ infer Name extends string,
1101
+ any,
1102
+ infer PresentFormula extends PredicateFormula,
1103
+ infer PresenceWitness extends string
1104
+ >
1105
+ ? Plan.Source<Name, "optional", PresentFormula, PresenceWitness>
842
1106
  : never
843
1107
  }
844
1108
 
845
1109
  export type ExistingAvailableAfterJoin<
846
- Available extends Record<string, Plan.Source>,
1110
+ Available extends Record<string, Plan.AnySource>,
847
1111
  Kind extends QueryAst.JoinKind
848
1112
  > = Kind extends "right" | "full"
849
1113
  ? DemoteAllAvailable<Available>
850
1114
  : Available
851
1115
 
852
1116
  export type AvailableAfterJoin<
853
- Available extends Record<string, Plan.Source>,
1117
+ Available extends Record<string, Plan.AnySource>,
854
1118
  JoinedName extends string,
855
- Kind extends QueryAst.JoinKind
856
- > = AddAvailable<ExistingAvailableAfterJoin<Available, Kind>, JoinedName, JoinSourceMode<Kind>>
1119
+ Kind extends QueryAst.JoinKind,
1120
+ PresentFormula extends PredicateFormula = TrueFormula,
1121
+ PresenceWitness extends string = never
1122
+ > = AddAvailable<
1123
+ ExistingAvailableAfterJoin<Available, Kind>,
1124
+ JoinedName,
1125
+ JoinSourceMode<Kind>,
1126
+ PresentFormula,
1127
+ PresenceWitness
1128
+ >
857
1129
 
858
1130
  /**
859
1131
  * Computes the next `required` set after introducing an additional expression.
@@ -862,7 +1134,7 @@ export type AvailableAfterJoin<
862
1134
  */
863
1135
  export type AddExpressionRequired<
864
1136
  Required,
865
- Available extends Record<string, Plan.Source>,
1137
+ Available extends Record<string, Plan.AnySource>,
866
1138
  Value extends ExpressionInput
867
1139
  > = Exclude<Required | RequiredFromInput<Value>, AvailableNames<Available>>
868
1140
 
@@ -874,7 +1146,7 @@ export type AddExpressionRequired<
874
1146
  */
875
1147
  export type AddJoinRequired<
876
1148
  Required,
877
- Available extends Record<string, Plan.Source>,
1149
+ Available extends Record<string, Plan.AnySource>,
878
1150
  JoinedName extends string,
879
1151
  Predicate extends PredicateInput | never,
880
1152
  Kind extends QueryAst.JoinKind = "inner"
@@ -1009,7 +1281,7 @@ type MergeNullabilityStates<
1009
1281
 
1010
1282
  type FoldEffectiveNullability<
1011
1283
  Values extends readonly Expression.Any[],
1012
- Available extends Record<string, Plan.Source>,
1284
+ Available extends Record<string, Plan.AnySource>,
1013
1285
  Assumptions extends PredicateFormula
1014
1286
  > = Extract<{
1015
1287
  [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
@@ -1023,7 +1295,7 @@ type FoldEffectiveNullability<
1023
1295
 
1024
1296
  type CoalesceEffectiveNullability<
1025
1297
  Values extends readonly Expression.Any[],
1026
- Available extends Record<string, Plan.Source>,
1298
+ Available extends Record<string, Plan.AnySource>,
1027
1299
  Assumptions extends PredicateFormula
1028
1300
  > = Extract<{
1029
1301
  [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
@@ -1040,42 +1312,184 @@ type NullabilityOfOutput<Output> =
1040
1312
  ? Exclude<Output, null> extends never ? "always" : "maybe"
1041
1313
  : "never"
1042
1314
 
1043
- type RequiredTablesFromAssumptions<Assumptions extends PredicateFormula> =
1044
- GuaranteedSourceNames<Assumptions>
1315
+ type PreciseFactSet<Value extends string> = string extends Value ? never : Value
1316
+
1317
+ type KnownGuaranteedNullKeys<
1318
+ Assumptions extends PredicateFormula
1319
+ > = PreciseFactSet<GuaranteedNullKeys<Assumptions>>
1320
+
1321
+ type KnownGuaranteedNonNullKeys<
1322
+ Assumptions extends PredicateFormula
1323
+ > = PreciseFactSet<GuaranteedNonNullKeys<Assumptions>>
1324
+
1325
+ type KnownGuaranteedSourceNames<
1326
+ Assumptions extends PredicateFormula
1327
+ > = PreciseFactSet<GuaranteedSourceNames<Assumptions>>
1328
+
1329
+ type ExplicitlyRequiredSourceNames<
1330
+ Available extends Record<string, Plan.AnySource>
1331
+ > = Extract<{
1332
+ readonly [K in keyof Available]:
1333
+ Available[K] extends Plan.Source<any, infer Mode extends Plan.SourceMode>
1334
+ ? Mode extends "required" ? K : never
1335
+ : never
1336
+ }[keyof Available], string>
1337
+
1338
+ type PresentFormulaOfSource<Source extends Plan.AnySource> =
1339
+ Source extends Plan.Source<any, any, infer PresentFormula extends PredicateFormula, any>
1340
+ ? PresentFormula
1341
+ : TrueFormula
1342
+
1343
+ type PresenceWitnessesOfSource<Source extends Plan.AnySource> =
1344
+ Source extends Plan.Source<any, any, any, infer PresenceWitness extends string>
1345
+ ? PresenceWitness
1346
+ : never
1347
+
1348
+ type ImpliedSourceNamesFromRequired<
1349
+ Available extends Record<string, Plan.AnySource>,
1350
+ Required extends string
1351
+ > = Extract<{
1352
+ readonly [K in Extract<keyof Available, string>]:
1353
+ K extends Required
1354
+ ? PreciseFactSet<GuaranteedSourceNames<PresentFormulaOfSource<Available[K]>>>
1355
+ : never
1356
+ }[Extract<keyof Available, string>], string>
1357
+
1358
+ type ExpandRequiredSourceNames<
1359
+ Available extends Record<string, Plan.AnySource>,
1360
+ Required extends string
1361
+ > = ExpandRequiredSourceNamesStep<
1362
+ Available,
1363
+ Required,
1364
+ Required | ImpliedSourceNamesFromRequired<Available, Required>
1365
+ >
1366
+
1367
+ type ExpandRequiredSourceNamesStep<
1368
+ Available extends Record<string, Plan.AnySource>,
1369
+ Current extends string,
1370
+ Next extends string
1371
+ > = [Exclude<Next, Current>] extends [never]
1372
+ ? Current
1373
+ : ExpandRequiredSourceNames<Available, Next>
1374
+
1375
+ type DirectlyAbsentSourceNames<
1376
+ Available extends Record<string, Plan.AnySource>,
1377
+ Assumptions extends PredicateFormula
1378
+ > = Extract<{
1379
+ readonly [K in Extract<keyof Available, string>]:
1380
+ K extends string
1381
+ ? PresenceWitnessesOfSource<Available[K]> extends infer Witnesses extends string
1382
+ ? Extract<Witnesses, KnownGuaranteedNullKeys<Assumptions>> extends never
1383
+ ? ContradictsFormula<Assumptions, PresentFormulaOfSource<Available[K]>> extends true
1384
+ ? K
1385
+ : never
1386
+ : K
1387
+ : never
1388
+ : never
1389
+ }[Extract<keyof Available, string>], string>
1390
+
1391
+ type ImpliedAbsentSourceNames<
1392
+ Available extends Record<string, Plan.AnySource>,
1393
+ Absent extends string
1394
+ > = Extract<{
1395
+ readonly [K in Extract<keyof Available, string>]:
1396
+ Extract<PreciseFactSet<GuaranteedSourceNames<PresentFormulaOfSource<Available[K]>>>, Absent> extends never
1397
+ ? never
1398
+ : K
1399
+ }[Extract<keyof Available, string>], string>
1400
+
1401
+ type ExpandAbsentSourceNames<
1402
+ Available extends Record<string, Plan.AnySource>,
1403
+ Current extends string
1404
+ > = ExpandAbsentSourceNamesStep<
1405
+ Available,
1406
+ Current,
1407
+ Current | ImpliedAbsentSourceNames<Available, Current>
1408
+ >
1409
+
1410
+ type ExpandAbsentSourceNamesStep<
1411
+ Available extends Record<string, Plan.AnySource>,
1412
+ Current extends string,
1413
+ Next extends string
1414
+ > = [Exclude<Next, Current>] extends [never]
1415
+ ? Current
1416
+ : ExpandAbsentSourceNames<Available, Next>
1417
+
1418
+ type AbsentSourceNamesInScope<
1419
+ Available extends Record<string, Plan.AnySource>,
1420
+ Assumptions extends PredicateFormula
1421
+ > = ExpandAbsentSourceNames<Available, DirectlyAbsentSourceNames<Available, Assumptions>>
1422
+
1423
+ type RequiredSourceNamesInScope<
1424
+ Available extends Record<string, Plan.AnySource>,
1425
+ Assumptions extends PredicateFormula
1426
+ > = Exclude<
1427
+ ExpandRequiredSourceNames<
1428
+ Available,
1429
+ ExplicitlyRequiredSourceNames<Available> | KnownGuaranteedSourceNames<Assumptions>
1430
+ >,
1431
+ AbsentSourceNamesInScope<Available, Assumptions>
1432
+ >
1045
1433
 
1046
1434
  type EffectiveAvailable<
1047
- Available extends Record<string, Plan.Source>,
1435
+ Available extends Record<string, Plan.AnySource>,
1048
1436
  Assumptions extends PredicateFormula
1049
1437
  > = {
1050
- readonly [K in keyof Available]: Available[K] & {
1051
- readonly mode: K extends RequiredTablesFromAssumptions<Assumptions> ? "required" : Available[K]["mode"]
1052
- }
1438
+ readonly [K in keyof Available]:
1439
+ Available[K] extends Plan.Source<
1440
+ infer Name extends string,
1441
+ infer Mode extends Plan.SourceMode,
1442
+ infer PresentFormula extends PredicateFormula,
1443
+ infer PresenceWitness extends string
1444
+ >
1445
+ ? Plan.Source<
1446
+ Name,
1447
+ K extends RequiredSourceNamesInScope<Available, Assumptions> ? "required" : Mode,
1448
+ PresentFormula,
1449
+ PresenceWitness
1450
+ > & {
1451
+ readonly baseName?: Available[K]["baseName"]
1452
+ }
1453
+ : never
1053
1454
  }
1054
1455
 
1456
+ type HasAbsentSource<
1457
+ Dependencies extends Expression.SourceDependencies,
1458
+ Available extends Record<string, Plan.AnySource>,
1459
+ Assumptions extends PredicateFormula
1460
+ > = Extract<{
1461
+ [K in keyof Dependencies & string]:
1462
+ K extends AbsentSourceNamesInScope<Available, Assumptions> ? true : never
1463
+ }[keyof Dependencies & string], true> extends never ? false : true
1464
+
1055
1465
  type BaseEffectiveNullability<
1056
1466
  Value extends Expression.Any,
1057
- Available extends Record<string, Plan.Source>,
1467
+ Available extends Record<string, Plan.AnySource>,
1058
1468
  Assumptions extends PredicateFormula
1059
1469
  > = AstOf<Value> extends ExpressionAst.ColumnNode<infer TableName extends string, infer ColumnName extends string>
1060
- ? `${TableName}.${ColumnName}` extends GuaranteedNullKeys<Assumptions>
1470
+ ? TableName extends AbsentSourceNamesInScope<Available, Assumptions>
1471
+ ? "always"
1472
+ : `${TableName}.${ColumnName}` extends KnownGuaranteedNullKeys<Assumptions>
1061
1473
  ? "always"
1062
- : `${TableName}.${ColumnName}` extends GuaranteedNonNullKeys<Assumptions>
1474
+ : `${TableName}.${ColumnName}` extends KnownGuaranteedNonNullKeys<Assumptions>
1063
1475
  ? "never"
1064
1476
  : Expression.NullabilityOf<Value> extends "always" ? "always"
1065
1477
  : Expression.SourceNullabilityOf<Value> extends "resolved"
1066
1478
  ? Expression.NullabilityOf<Value>
1479
+ : HasAbsentSource<DependenciesOf<Value>, Available, Assumptions> extends true ? "always"
1067
1480
  : HasOptionalSource<DependenciesOf<Value>, Available> extends true ? "maybe"
1068
1481
  : Expression.NullabilityOf<Value>
1069
1482
  : Expression.NullabilityOf<Value> extends "always" ? "always"
1070
1483
  : Expression.SourceNullabilityOf<Value> extends "resolved"
1071
1484
  ? Expression.NullabilityOf<Value>
1485
+ : HasAbsentSource<DependenciesOf<Value>, Available, Assumptions> extends true ? "always"
1072
1486
  : HasOptionalSource<DependenciesOf<Value>, Available> extends true ? "maybe"
1073
1487
  : Expression.NullabilityOf<Value>
1074
1488
 
1075
1489
  type CaseOutputOf<
1076
1490
  Branches extends readonly ExpressionAst.CaseBranchNode[],
1077
1491
  Else extends Expression.Any,
1078
- Available extends Record<string, Plan.Source>,
1492
+ Available extends Record<string, Plan.AnySource>,
1079
1493
  Assumptions extends PredicateFormula
1080
1494
  > = Branches extends readonly [
1081
1495
  infer Head extends ExpressionAst.CaseBranchNode,
@@ -1094,7 +1508,7 @@ type CaseOutputOf<
1094
1508
  /** Effective nullability of an expression after source-scope nullability is applied. */
1095
1509
  export type EffectiveNullability<
1096
1510
  Value extends Expression.Any,
1097
- Available extends Record<string, Plan.Source>,
1511
+ Available extends Record<string, Plan.AnySource>,
1098
1512
  Assumptions extends PredicateFormula = TrueAssumptions
1099
1513
  > =
1100
1514
  AstOf<Value> extends infer Ast extends ExpressionAst.Any
@@ -1126,12 +1540,14 @@ export type EffectiveNullability<
1126
1540
  /** Result runtime type of an expression after effective nullability is resolved. */
1127
1541
  export type ExpressionOutput<
1128
1542
  Value extends Expression.Any,
1129
- Available extends Record<string, Plan.Source>,
1543
+ Available extends Record<string, Plan.AnySource>,
1130
1544
  Assumptions extends PredicateFormula = TrueAssumptions
1131
1545
  > = AstOf<Value> extends ExpressionAst.CaseNode<infer Branches extends readonly ExpressionAst.CaseBranchNode[], infer Else extends Expression.Any>
1132
1546
  ? CaseOutputOf<Branches, Else, Available, Assumptions>
1133
1547
  : EffectiveNullability<Value, Available, Assumptions> extends "never"
1134
- ? Expression.RuntimeOf<Value>
1548
+ ? Expression.NullabilityOf<Value> extends "never"
1549
+ ? Expression.RuntimeOf<Value>
1550
+ : NonNullable<Expression.RuntimeOf<Value>>
1135
1551
  : EffectiveNullability<Value, Available, Assumptions> extends "always"
1136
1552
  ? null
1137
1553
  : Expression.RuntimeOf<Value> | null
@@ -1139,7 +1555,7 @@ export type ExpressionOutput<
1139
1555
  /** Result runtime type of a nested selection after source-scope nullability is resolved. */
1140
1556
  export type OutputOfSelection<
1141
1557
  Selection,
1142
- Available extends Record<string, Plan.Source>,
1558
+ Available extends Record<string, Plan.AnySource>,
1143
1559
  Assumptions extends PredicateFormula = TrueAssumptions
1144
1560
  > = Selection extends Expression.Any
1145
1561
  ? ExpressionOutput<Selection, Available, Assumptions>
@@ -1352,7 +1768,7 @@ export type SetCompatibleRightPlan<
1352
1768
  /** True when any of an expression's dependencies are optional in the current scope. */
1353
1769
  type HasOptionalSource<
1354
1770
  Dependencies extends Expression.SourceDependencies,
1355
- Available extends Record<string, Plan.Source>
1771
+ Available extends Record<string, Plan.AnySource>
1356
1772
  > = Extract<{
1357
1773
  [K in keyof Dependencies & string]: SourceModeOf<Available, K> extends "optional" ? true : never
1358
1774
  }[keyof Dependencies & string], true> extends never ? false : true
@@ -1367,7 +1783,7 @@ type HasOptionalSource<
1367
1783
  export type QueryPlan<
1368
1784
  Selection,
1369
1785
  Required = never,
1370
- Available extends Record<string, Plan.Source> = {},
1786
+ Available extends Record<string, Plan.AnySource> = {},
1371
1787
  Dialect extends string = never,
1372
1788
  Grouped extends string = never,
1373
1789
  ScopedNames extends string = Extract<keyof Available, string>,
@@ -1510,7 +1926,7 @@ export const makeExpression = <
1510
1926
  export const makePlan = <
1511
1927
  Selection,
1512
1928
  Required,
1513
- Available extends Record<string, Plan.Source>,
1929
+ Available extends Record<string, Plan.AnySource>,
1514
1930
  Dialect extends string,
1515
1931
  Grouped extends string = never,
1516
1932
  ScopedNames extends string = Extract<keyof Available, string>,
@@ -1536,7 +1952,7 @@ export const makePlan = <
1536
1952
  required: undefined as unknown as Outstanding,
1537
1953
  availableNames: undefined as unknown as ScopedNames,
1538
1954
  grouped: undefined as unknown as Grouped,
1539
- assumptions: undefined as unknown as Assumptions,
1955
+ assumptions: ((_assumptions ?? trueFormula()) as Assumptions),
1540
1956
  capabilities: undefined as unknown as Capabilities,
1541
1957
  statement: (_statement ?? ("select" as Statement)) as Statement,
1542
1958
  target: (_target ?? (undefined as unknown as Target)) as Target,
@@ -41,12 +41,12 @@ export type RowOf<Value extends RenderedQuery<any, any>> = Value[typeof TypeId][
41
41
  */
42
42
  export interface Renderer<Dialect extends string = string> {
43
43
  readonly dialect: Dialect
44
- render<PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any>>(
44
+ render<PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
45
45
  plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
46
46
  ): RenderedQuery<any, Dialect>
47
47
  }
48
48
 
49
- type CustomRender<Dialect extends string> = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any>>(
49
+ type CustomRender<Dialect extends string> = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
50
50
  plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
51
51
  ) => {
52
52
  readonly sql: string