rawsql-ts 0.28.0 → 0.29.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 (36) hide show
  1. package/dist/esm/index.min.js +1 -1
  2. package/dist/esm/index.min.js.map +4 -4
  3. package/dist/esm/transformers/ConditionDeduplicationOptimizer.d.ts +22 -0
  4. package/dist/esm/transformers/ConditionDeduplicationOptimizer.js +198 -0
  5. package/dist/esm/transformers/ConditionDeduplicationOptimizer.js.map +1 -0
  6. package/dist/esm/transformers/ConditionOptimization.d.ts +31 -1
  7. package/dist/esm/transformers/ConditionOptimization.js +321 -4
  8. package/dist/esm/transformers/ConditionOptimization.js.map +1 -1
  9. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.d.ts +13 -0
  10. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js +246 -27
  11. package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
  12. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.d.ts +12 -0
  13. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js +211 -18
  14. package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js.map +1 -1
  15. package/dist/esm/transformers/TopLevelAndConditionDeduper.d.ts +10 -0
  16. package/dist/esm/transformers/TopLevelAndConditionDeduper.js +66 -0
  17. package/dist/esm/transformers/TopLevelAndConditionDeduper.js.map +1 -0
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +4 -4
  20. package/dist/src/transformers/ConditionDeduplicationOptimizer.d.ts +22 -0
  21. package/dist/src/transformers/ConditionOptimization.d.ts +31 -1
  22. package/dist/src/transformers/ParameterConditionPlacementOptimizer.d.ts +13 -0
  23. package/dist/src/transformers/StaticPredicatePlacementOptimizer.d.ts +12 -0
  24. package/dist/src/transformers/TopLevelAndConditionDeduper.d.ts +10 -0
  25. package/dist/transformers/ConditionDeduplicationOptimizer.js +202 -0
  26. package/dist/transformers/ConditionDeduplicationOptimizer.js.map +1 -0
  27. package/dist/transformers/ConditionOptimization.js +324 -4
  28. package/dist/transformers/ConditionOptimization.js.map +1 -1
  29. package/dist/transformers/ParameterConditionPlacementOptimizer.js +245 -26
  30. package/dist/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
  31. package/dist/transformers/StaticPredicatePlacementOptimizer.js +210 -17
  32. package/dist/transformers/StaticPredicatePlacementOptimizer.js.map +1 -1
  33. package/dist/transformers/TopLevelAndConditionDeduper.js +72 -0
  34. package/dist/transformers/TopLevelAndConditionDeduper.js.map +1 -0
  35. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  36. package/package.json +1 -1
@@ -8,9 +8,18 @@ const SelectQueryParser_1 = require("../parsers/SelectQueryParser");
8
8
  const ValueParser_1 = require("../parsers/ValueParser");
9
9
  const SqlComponentFormatter_1 = require("./SqlComponentFormatter");
10
10
  const SelectOutputCollector_1 = require("./SelectOutputCollector");
11
+ const TopLevelAndConditionDeduper_1 = require("./TopLevelAndConditionDeduper");
11
12
  const SUPPORTED_OPERATORS = new Set(["=", "<>", "!=", "<", "<=", ">", ">=", "like", "ilike", "in"]);
12
13
  const VOLATILE_OR_UNSUPPORTED_FUNCTION_REASON = "Condition contains a function call; volatile and expression predicates are not moved in the safe-only implementation.";
13
14
  const normalizeIdentifier = (value) => value.trim().toLowerCase();
15
+ const isCaseSensitiveIdentifier = (value) => /[A-Z]/.test(value.trim());
16
+ const identifiersEqual = (left, right) => {
17
+ const trimmedLeft = left.trim();
18
+ const trimmedRight = right.trim();
19
+ return isCaseSensitiveIdentifier(trimmedLeft) || isCaseSensitiveIdentifier(trimmedRight)
20
+ ? trimmedLeft === trimmedRight
21
+ : trimmedLeft.toLowerCase() === trimmedRight.toLowerCase();
22
+ };
14
23
  const unwrapParens = (expression) => {
15
24
  let candidate = expression;
16
25
  while (candidate instanceof ValueComponent_1.ParenExpression) {
@@ -62,8 +71,8 @@ const columnReferenceText = (reference) => {
62
71
  return namespace ? `${namespace}.${reference.column.name}` : reference.column.name;
63
72
  };
64
73
  const sameColumnReference = (left, right) => {
65
- return normalizeIdentifier(left.column.name) === normalizeIdentifier(right.column.name)
66
- && normalizeIdentifier(left.getNamespace()) === normalizeIdentifier(right.getNamespace());
74
+ return identifiersEqual(left.column.name, right.column.name)
75
+ && identifiersEqual(left.getNamespace(), right.getNamespace());
67
76
  };
68
77
  const appendUnique = (items, value) => {
69
78
  if (!items.includes(value)) {
@@ -123,7 +132,11 @@ class ParameterConditionPlacementOptimizer {
123
132
  continue;
124
133
  }
125
134
  let appliedReason = "";
126
- if (target.kind === "simple") {
135
+ if (target.kind === "join_on") {
136
+ this.appendJoinOnCondition(target.join, candidate.expression, options);
137
+ appliedReason = target.reason;
138
+ }
139
+ else if (target.kind === "simple") {
127
140
  const targetColumns = this.resolveTargetColumns(query, target.query, candidate.references);
128
141
  if ("code" in targetColumns) {
129
142
  skipped.push(this.makeSkipped(term, targetColumns, options));
@@ -136,6 +149,7 @@ class ParameterConditionPlacementOptimizer {
136
149
  }
137
150
  const movedCondition = this.rebaseCondition(candidate.expression, targetColumns, options);
138
151
  target.query.appendWhere(movedCondition);
152
+ (0, TopLevelAndConditionDeduper_1.dedupeWhereTopLevelAndConditions)(target.query, options);
139
153
  appliedReason = placement.reason;
140
154
  }
141
155
  else {
@@ -156,6 +170,7 @@ class ParameterConditionPlacementOptimizer {
156
170
  for (const branch of target.branches) {
157
171
  const movedCondition = this.rebaseCondition(candidate.expression, branch.targetColumns, options);
158
172
  branch.query.appendWhere(movedCondition);
173
+ (0, TopLevelAndConditionDeduper_1.dedupeWhereTopLevelAndConditions)(branch.query, options);
159
174
  }
160
175
  appliedReason = placements.some(item => /group by/i.test(item.reason))
161
176
  ? "Condition is distributed to every UNION branch by output column position; grouped branches only receive GROUP BY-key predicates."
@@ -354,9 +369,15 @@ class ParameterConditionPlacementOptimizer {
354
369
  }
355
370
  return null;
356
371
  }
372
+ if (candidate instanceof ValueComponent_1.UnaryExpression) {
373
+ const operator = candidate.operator.value.trim().toLowerCase();
374
+ if (operator === "not") {
375
+ return visit(candidate.expression);
376
+ }
377
+ }
357
378
  return {
358
379
  code: "UNSUPPORTED_PARAMETER_CONDITION",
359
- reason: "Only simple binary, BETWEEN, and whole OR/AND parameter predicates are moved in the safe-only implementation."
380
+ reason: "Only simple binary, BETWEEN, and whole OR/AND/NOT parameter predicates are moved in the safe-only implementation."
360
381
  };
361
382
  };
362
383
  return visit(expression);
@@ -377,6 +398,7 @@ class ParameterConditionPlacementOptimizer {
377
398
  && right.values.every(value => unwrapParens(value) instanceof ValueComponent_1.ParameterExpression);
378
399
  }
379
400
  resolveTarget(root, candidate) {
401
+ var _a;
380
402
  const boundary = this.findRootQueryBoundary(root);
381
403
  if (boundary) {
382
404
  return boundary;
@@ -404,12 +426,25 @@ class ParameterConditionPlacementOptimizer {
404
426
  };
405
427
  }
406
428
  const binding = bindings[0];
429
+ if ((_a = binding.join) === null || _a === void 0 ? void 0 : _a.lateral) {
430
+ return {
431
+ code: "LATERAL_JOIN_BOUNDARY",
432
+ reason: "Condition crosses a LATERAL JOIN boundary; moving it may change semantics."
433
+ };
434
+ }
407
435
  const nullableSide = this.findNullableSideBoundary(root.fromClause, binding);
408
436
  if (nullableSide) {
409
437
  return nullableSide;
410
438
  }
411
439
  const upstream = this.resolveUpstreamQuery(root, binding, candidate.references);
412
440
  if ("code" in upstream) {
441
+ if (upstream.code === "NO_SAFE_UPSTREAM_QUERY") {
442
+ const joinOnTarget = this.resolveBaseTableJoinOnTarget(root, binding);
443
+ if (!("code" in joinOnTarget)) {
444
+ return joinOnTarget;
445
+ }
446
+ return joinOnTarget;
447
+ }
413
448
  return upstream;
414
449
  }
415
450
  return upstream;
@@ -491,10 +526,10 @@ class ParameterConditionPlacementOptimizer {
491
526
  };
492
527
  }
493
528
  const bindings = this.getSourceBindings(fromClause);
494
- const namespace = normalizeIdentifier(column.getNamespace());
529
+ const namespace = column.getNamespace();
495
530
  const columnName = column.column.name;
496
531
  if (namespace) {
497
- const matches = bindings.filter(binding => normalizeIdentifier(binding.alias) === namespace);
532
+ const matches = bindings.filter(binding => identifiersEqual(binding.alias, namespace));
498
533
  if (matches.length !== 1) {
499
534
  return {
500
535
  code: "AMBIGUOUS_COLUMN_SOURCE",
@@ -502,6 +537,9 @@ class ParameterConditionPlacementOptimizer {
502
537
  };
503
538
  }
504
539
  const matchCount = this.getOutputColumnMatchCount(contextRoot, matches[0], columnName);
540
+ if (matchCount === 0 && this.isBaseTableBinding(contextRoot, matches[0])) {
541
+ return matches[0];
542
+ }
505
543
  if (matchCount === 0) {
506
544
  return {
507
545
  code: "COLUMN_NOT_AVAILABLE_UPSTREAM",
@@ -630,7 +668,7 @@ class ParameterConditionPlacementOptimizer {
630
668
  resolveTargetColumns(root, query, references) {
631
669
  const resolved = [];
632
670
  for (const reference of references) {
633
- const matches = this.collectSelectOutputs(root, query).filter(item => normalizeIdentifier(item.name) === normalizeIdentifier(reference.column.name));
671
+ const matches = this.collectDirectOutputMatches(root, query, reference.column.name);
634
672
  if (matches.length !== 1) {
635
673
  return {
636
674
  code: "AMBIGUOUS_TARGET_COLUMN",
@@ -657,6 +695,57 @@ class ParameterConditionPlacementOptimizer {
657
695
  }
658
696
  return resolved;
659
697
  }
698
+ resolveBaseTableJoinOnTarget(root, binding) {
699
+ var _a, _b, _c;
700
+ if (!root.fromClause || !this.isBaseTableBinding(root, binding)) {
701
+ return {
702
+ code: "NO_SAFE_UPSTREAM_QUERY",
703
+ reason: "The referenced source is a base table, so there is no upstream query block to move into."
704
+ };
705
+ }
706
+ if (this.hasOuterJoin(root.fromClause)) {
707
+ return {
708
+ code: "OUTER_JOIN_BOUNDARY",
709
+ reason: "Condition crosses an OUTER JOIN boundary; moving it into JOIN ON may change semantics."
710
+ };
711
+ }
712
+ const join = binding.isPrimary
713
+ ? (_b = (_a = root.fromClause.joins) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null
714
+ : binding.join;
715
+ if (join === null || join === void 0 ? void 0 : join.lateral) {
716
+ return {
717
+ code: "LATERAL_JOIN_BOUNDARY",
718
+ reason: "Condition crosses a LATERAL JOIN boundary; moving it into JOIN ON may change semantics."
719
+ };
720
+ }
721
+ if (!join || !this.isInnerJoin(join)) {
722
+ return {
723
+ code: "NO_SAFE_JOIN_ON_TARGET",
724
+ reason: "Base-table conditions are moved only into INNER JOIN ON clauses in the safe-only implementation."
725
+ };
726
+ }
727
+ if (!(join.condition instanceof Clause_1.JoinOnClause)) {
728
+ return {
729
+ code: "NO_SAFE_JOIN_ON_TARGET",
730
+ reason: "Base-table conditions are moved only into existing JOIN ON clauses, not USING or conditionless joins."
731
+ };
732
+ }
733
+ return {
734
+ kind: "join_on",
735
+ join,
736
+ scopeId: `join_on:${(_c = join.source.getAliasName()) !== null && _c !== void 0 ? _c : "unknown"}`,
737
+ reason: binding.isPrimary
738
+ ? "Condition references the primary source of an INNER JOIN; it is moved into the first JOIN ON clause."
739
+ : "Condition references the joined source of an INNER JOIN; it is moved into that JOIN ON clause."
740
+ };
741
+ }
742
+ appendJoinOnCondition(join, expression, options) {
743
+ if (!(join.condition instanceof Clause_1.JoinOnClause)) {
744
+ return;
745
+ }
746
+ join.condition.condition = new ValueComponent_1.BinaryExpression(join.condition.condition, "and", cloneValueComponent(expression, options));
747
+ join.condition.condition = (0, TopLevelAndConditionDeduper_1.dedupeTopLevelAndConditions)(join.condition.condition, options);
748
+ }
660
749
  resolveTargetColumnByOutputIndex(root, query, outputIndex, sourceColumn) {
661
750
  const output = this.collectSelectOutputs(root, query)[outputIndex];
662
751
  if (!output) {
@@ -665,6 +754,15 @@ class ParameterConditionPlacementOptimizer {
665
754
  reason: `UNION branch does not expose column '${sourceColumn.column.name}' at output position ${outputIndex + 1}.`
666
755
  };
667
756
  }
757
+ else if (identifiersEqual(output.name, sourceColumn.column.name)) {
758
+ const matches = this.collectDirectOutputMatches(root, query, sourceColumn.column.name);
759
+ if (matches.length > 1) {
760
+ return {
761
+ code: "AMBIGUOUS_TARGET_COLUMN",
762
+ reason: `UNION branch exposes multiple '${sourceColumn.column.name}' columns.`
763
+ };
764
+ }
765
+ }
668
766
  if (!(output.value instanceof ValueComponent_1.ColumnReference)) {
669
767
  return {
670
768
  code: "EXPRESSION_OUTPUT_UNSUPPORTED",
@@ -707,7 +805,10 @@ class ParameterConditionPlacementOptimizer {
707
805
  return { query, targetColumns: [...targetColumns] };
708
806
  }
709
807
  const upstream = this.resolveUpstreamQuery(contextRoot, binding, targetColumns.map(item => item.targetColumn));
710
- if ("code" in upstream || upstream.kind === "union") {
808
+ if ("code" in upstream) {
809
+ return { query, targetColumns: [...targetColumns] };
810
+ }
811
+ if (upstream.kind !== "simple") {
711
812
  return { query, targetColumns: [...targetColumns] };
712
813
  }
713
814
  const upstreamColumns = this.resolveTargetColumns(contextRoot, upstream.query, targetColumns.map(item => item.targetColumn));
@@ -732,9 +833,9 @@ class ParameterConditionPlacementOptimizer {
732
833
  };
733
834
  }
734
835
  const bindings = this.getSourceBindings(query.fromClause);
735
- const namespace = normalizeIdentifier(column.getNamespace());
836
+ const namespace = column.getNamespace();
736
837
  if (namespace) {
737
- const matches = bindings.filter(binding => normalizeIdentifier(binding.alias) === namespace);
838
+ const matches = bindings.filter(binding => identifiersEqual(binding.alias, namespace));
738
839
  return matches.length === 1
739
840
  ? null
740
841
  : {
@@ -765,7 +866,7 @@ class ParameterConditionPlacementOptimizer {
765
866
  if (sameColumnReference(left, right)) {
766
867
  return true;
767
868
  }
768
- if (normalizeIdentifier(left.column.name) !== normalizeIdentifier(right.column.name)) {
869
+ if (!identifiersEqual(left.column.name, right.column.name)) {
769
870
  return false;
770
871
  }
771
872
  const leftSource = this.resolveColumnSourceAlias(query, left);
@@ -777,12 +878,12 @@ class ParameterConditionPlacementOptimizer {
777
878
  return null;
778
879
  }
779
880
  const bindings = this.getSourceBindings(query.fromClause);
780
- const namespace = normalizeIdentifier(column.getNamespace());
881
+ const namespace = column.getNamespace();
781
882
  if (namespace) {
782
- const matches = bindings.filter(binding => normalizeIdentifier(binding.alias) === namespace);
783
- return matches.length === 1 ? normalizeIdentifier(matches[0].alias) : null;
883
+ const matches = bindings.filter(binding => identifiersEqual(binding.alias, namespace));
884
+ return matches.length === 1 ? matches[0].alias : null;
784
885
  }
785
- return bindings.length === 1 ? normalizeIdentifier(bindings[0].alias) : null;
886
+ return bindings.length === 1 ? bindings[0].alias : null;
786
887
  }
787
888
  rebaseCondition(expression, targetColumns, options) {
788
889
  const cloned = cloneValueComponent(expression, options);
@@ -800,33 +901,45 @@ class ParameterConditionPlacementOptimizer {
800
901
  source: fromClause.source,
801
902
  alias: (_a = fromClause.source.getAliasName()) !== null && _a !== void 0 ? _a : "",
802
903
  join: null,
904
+ joinIndex: -1,
803
905
  isPrimary: true
804
906
  }];
805
- for (const join of (_b = fromClause.joins) !== null && _b !== void 0 ? _b : []) {
907
+ for (let index = 0; index < ((_b = fromClause.joins) !== null && _b !== void 0 ? _b : []).length; index += 1) {
908
+ const join = fromClause.joins[index];
806
909
  bindings.push({
807
910
  source: join.source,
808
911
  alias: (_c = join.source.getAliasName()) !== null && _c !== void 0 ? _c : "",
809
912
  join,
913
+ joinIndex: index,
810
914
  isPrimary: false
811
915
  });
812
916
  }
813
917
  return bindings;
814
918
  }
919
+ isBaseTableBinding(root, binding) {
920
+ const source = binding.source.datasource;
921
+ return source instanceof Clause_1.TableSource && !this.findCte(root, source.table.name);
922
+ }
923
+ isInnerJoin(join) {
924
+ const joinType = join.joinType.value.trim().toLowerCase();
925
+ return joinType === "join" || joinType === "inner join";
926
+ }
815
927
  findNullableSideBoundary(fromClause, binding) {
816
928
  var _a;
817
- if (!binding.join) {
818
- const rightOrFull = ((_a = fromClause.joins) !== null && _a !== void 0 ? _a : []).some(join => {
819
- const joinType = join.joinType.value.toLowerCase();
820
- return joinType.includes("right") || joinType.includes("full");
821
- });
822
- return rightOrFull
929
+ const joins = (_a = fromClause.joins) !== null && _a !== void 0 ? _a : [];
930
+ if (binding.isPrimary) {
931
+ return this.hasLaterJoinThatNullsPriorSources(joins, -1)
823
932
  ? {
824
933
  code: "OUTER_JOIN_NULLABLE_SIDE",
825
934
  reason: "Condition crosses OUTER JOIN nullable side; moving it may change semantics."
826
935
  }
827
936
  : null;
828
937
  }
829
- const joinType = binding.join.joinType.value.toLowerCase();
938
+ const join = binding.join;
939
+ if (!join) {
940
+ return null;
941
+ }
942
+ const joinType = join.joinType.value.toLowerCase();
830
943
  if (joinType.includes("left")) {
831
944
  return {
832
945
  code: "OUTER_JOIN_NULLABLE_SIDE",
@@ -839,8 +952,22 @@ class ParameterConditionPlacementOptimizer {
839
952
  reason: "Condition crosses FULL JOIN nullable side; moving it may change semantics."
840
953
  };
841
954
  }
955
+ if (this.hasLaterJoinThatNullsPriorSources(joins, binding.joinIndex)) {
956
+ return {
957
+ code: "OUTER_JOIN_NULLABLE_SIDE",
958
+ reason: "Condition crosses later RIGHT/FULL JOIN nullable side; moving it may change semantics."
959
+ };
960
+ }
842
961
  return null;
843
962
  }
963
+ hasLaterJoinThatNullsPriorSources(joins, sourceJoinIndex) {
964
+ return joins
965
+ .slice(sourceJoinIndex + 1)
966
+ .some(join => {
967
+ const joinType = join.joinType.value.toLowerCase();
968
+ return joinType.includes("right") || joinType.includes("full");
969
+ });
970
+ }
844
971
  hasOuterJoin(fromClause) {
845
972
  var _a;
846
973
  return ((_a = fromClause.joins) !== null && _a !== void 0 ? _a : []).some(join => {
@@ -864,12 +991,12 @@ class ParameterConditionPlacementOptimizer {
864
991
  if ("code" in branches) {
865
992
  return 0;
866
993
  }
867
- return this.collectSelectOutputs(root, branches[0]).filter(item => normalizeIdentifier(item.name) === normalizeIdentifier(columnName)).length;
994
+ return this.collectDirectOutputMatches(root, branches[0], columnName).length;
868
995
  }
869
996
  if (!(target instanceof SelectQuery_1.SimpleSelectQuery)) {
870
997
  return 0;
871
998
  }
872
- return this.collectSelectOutputs(root, target).filter(item => normalizeIdentifier(item.name) === normalizeIdentifier(columnName)).length;
999
+ return this.collectDirectOutputMatches(root, target, columnName, true).length;
873
1000
  }
874
1001
  collectUnionBranches(query) {
875
1002
  const branches = [];
@@ -900,7 +1027,7 @@ class ParameterConditionPlacementOptimizer {
900
1027
  resolveUnionOutputIndex(root, firstBranch, outputColumnName) {
901
1028
  const matches = [];
902
1029
  this.collectSelectOutputs(root, firstBranch).forEach((item, index) => {
903
- if (normalizeIdentifier(item.name) === normalizeIdentifier(outputColumnName)) {
1030
+ if (identifiersEqual(item.name, outputColumnName)) {
904
1031
  matches.push(index);
905
1032
  }
906
1033
  });
@@ -923,6 +1050,98 @@ class ParameterConditionPlacementOptimizer {
923
1050
  const collector = new SelectOutputCollector_1.SelectOutputCollector(null, commonTables.length > 0 ? commonTables : null);
924
1051
  return collector.collect(query);
925
1052
  }
1053
+ collectDirectOutputMatches(root, query, columnName, includeUnprovenPotential = false) {
1054
+ const collectedMatches = this.collectSelectOutputs(root, query).filter(item => identifiersEqual(item.name, columnName));
1055
+ if (collectedMatches.length > 0) {
1056
+ return this.hasExplicitOutputMatch(query, columnName)
1057
+ ? [...collectedMatches, ...this.inferWildcardOutputMatches(root, query, columnName, true)]
1058
+ : collectedMatches;
1059
+ }
1060
+ return this.inferWildcardOutputMatches(root, query, columnName, includeUnprovenPotential);
1061
+ }
1062
+ hasExplicitOutputMatch(query, columnName) {
1063
+ return query.selectClause.items.some(item => {
1064
+ if (item.identifier) {
1065
+ return identifiersEqual(item.identifier.name, columnName);
1066
+ }
1067
+ return item.value instanceof ValueComponent_1.ColumnReference
1068
+ && item.value.column.name !== "*"
1069
+ && identifiersEqual(item.value.column.name, columnName);
1070
+ });
1071
+ }
1072
+ inferWildcardOutputMatches(root, query, columnName, includeUnprovenPotential) {
1073
+ const matches = [];
1074
+ query.selectClause.items.forEach((item, outputIndex) => {
1075
+ if (item.identifier || !(item.value instanceof ValueComponent_1.ColumnReference) || item.value.column.name !== "*") {
1076
+ return;
1077
+ }
1078
+ const targetColumn = this.inferWildcardTargetColumn(root, query, item.value, columnName, includeUnprovenPotential);
1079
+ if (!targetColumn) {
1080
+ return;
1081
+ }
1082
+ if (targetColumn === "ambiguous") {
1083
+ matches.push(this.createInferredOutputColumn(columnName, new ValueComponent_1.ColumnReference(null, columnName), outputIndex), this.createInferredOutputColumn(columnName, new ValueComponent_1.ColumnReference(null, columnName), outputIndex));
1084
+ return;
1085
+ }
1086
+ matches.push(this.createInferredOutputColumn(columnName, targetColumn, outputIndex));
1087
+ });
1088
+ return matches;
1089
+ }
1090
+ inferWildcardTargetColumn(root, query, wildcard, columnName, includeUnprovenPotential) {
1091
+ if (!query.fromClause) {
1092
+ return null;
1093
+ }
1094
+ const bindings = this.getSourceBindings(query.fromClause);
1095
+ if (wildcard.namespaces === null) {
1096
+ if (bindings.length !== 1) {
1097
+ return "ambiguous";
1098
+ }
1099
+ return this.resolveWildcardColumnFromBinding(root, query, bindings[0], columnName, includeUnprovenPotential);
1100
+ }
1101
+ const namespace = wildcard.getNamespace();
1102
+ const matches = bindings.filter(binding => identifiersEqual(binding.alias, namespace));
1103
+ if (matches.length === 0) {
1104
+ return null;
1105
+ }
1106
+ return matches.length === 1
1107
+ ? this.resolveWildcardColumnFromBinding(root, query, matches[0], columnName, includeUnprovenPotential)
1108
+ : "ambiguous";
1109
+ }
1110
+ resolveWildcardColumnFromBinding(root, query, binding, columnName, includeUnprovenPotential) {
1111
+ const matches = this.collectSourceOutputMatches(root, query, binding.source, columnName);
1112
+ if (matches.length > 1) {
1113
+ return "ambiguous";
1114
+ }
1115
+ if (matches.length === 1) {
1116
+ const value = matches[0].value;
1117
+ return value instanceof ValueComponent_1.ColumnReference ? value : null;
1118
+ }
1119
+ return includeUnprovenPotential && binding.source.datasource instanceof Clause_1.TableSource
1120
+ ? this.createColumnForBinding(binding, columnName)
1121
+ : null;
1122
+ }
1123
+ collectSourceOutputMatches(root, query, source, columnName) {
1124
+ var _a, _b, _c, _d;
1125
+ const commonTables = [
1126
+ ...((_b = (_a = query.withClause) === null || _a === void 0 ? void 0 : _a.tables) !== null && _b !== void 0 ? _b : []),
1127
+ ...((_d = (_c = root.withClause) === null || _c === void 0 ? void 0 : _c.tables) !== null && _d !== void 0 ? _d : [])
1128
+ ];
1129
+ const collector = new SelectOutputCollector_1.SelectOutputCollector(null, commonTables.length > 0 ? commonTables : null);
1130
+ return collector.collect(source).filter(item => identifiersEqual(item.name, columnName));
1131
+ }
1132
+ createColumnForBinding(binding, columnName) {
1133
+ return new ValueComponent_1.ColumnReference(binding.alias ? [binding.alias] : null, columnName);
1134
+ }
1135
+ createInferredOutputColumn(name, value, outputIndex) {
1136
+ return {
1137
+ name,
1138
+ value,
1139
+ outputIndex,
1140
+ sourceAlias: value.getNamespace() || null,
1141
+ sourceName: null,
1142
+ sourceColumnName: name
1143
+ };
1144
+ }
926
1145
  resolveSourceQueryForColumns(root, source) {
927
1146
  var _a;
928
1147
  if (source.datasource instanceof Clause_1.SubQuerySource) {