@nshiab/simple-data-analysis-core 2.1.7 → 2.1.9

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 (59) hide show
  1. package/esm/class/SimpleTable.d.ts +191 -108
  2. package/esm/class/SimpleTable.d.ts.map +1 -1
  3. package/esm/class/SimpleTable.js +188 -105
  4. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts +1 -1
  5. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -1
  6. package/esm/helpers/buildGraphTemporalCostStateSql.js +23 -9
  7. package/esm/helpers/graphRouteResultSchema.d.ts +1 -1
  8. package/esm/helpers/graphRouteResultSchema.d.ts.map +1 -1
  9. package/esm/helpers/graphRouteResultSchema.js +3 -3
  10. package/esm/helpers/graphRouteResultSelect.d.ts +1 -1
  11. package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -1
  12. package/esm/helpers/graphRouteResultSelect.js +2 -2
  13. package/esm/helpers/prepareGraphMetricOptions.d.ts +2 -2
  14. package/esm/helpers/prepareGraphMetricOptions.d.ts.map +1 -1
  15. package/esm/helpers/prepareGraphMetricOptions.js +5 -4
  16. package/esm/helpers/prepareGraphRouteSql.d.ts +2 -2
  17. package/esm/helpers/prepareGraphRouteSql.d.ts.map +1 -1
  18. package/esm/helpers/prepareGraphRouteSql.js +4 -4
  19. package/esm/helpers/validateGraphRouteResultSchema.d.ts +1 -1
  20. package/esm/helpers/validateGraphRouteResultSchema.d.ts.map +1 -1
  21. package/esm/helpers/validateGraphRouteResultSchema.js +3 -1
  22. package/esm/methods/distances.d.ts +1 -1
  23. package/esm/methods/distances.d.ts.map +1 -1
  24. package/esm/methods/distances.js +235 -73
  25. package/esm/methods/shortestPath.d.ts +1 -1
  26. package/esm/methods/shortestPath.d.ts.map +1 -1
  27. package/esm/methods/shortestPath.js +44 -28
  28. package/esm/methods/similarityMahalanobis.js +3 -3
  29. package/llm.md +214 -119
  30. package/llms.txt +1 -1
  31. package/package.json +1 -1
  32. package/script/class/SimpleTable.d.ts +191 -108
  33. package/script/class/SimpleTable.d.ts.map +1 -1
  34. package/script/class/SimpleTable.js +188 -105
  35. package/script/helpers/buildGraphTemporalCostStateSql.d.ts +1 -1
  36. package/script/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -1
  37. package/script/helpers/buildGraphTemporalCostStateSql.js +23 -9
  38. package/script/helpers/graphRouteResultSchema.d.ts +1 -1
  39. package/script/helpers/graphRouteResultSchema.d.ts.map +1 -1
  40. package/script/helpers/graphRouteResultSchema.js +3 -3
  41. package/script/helpers/graphRouteResultSelect.d.ts +1 -1
  42. package/script/helpers/graphRouteResultSelect.d.ts.map +1 -1
  43. package/script/helpers/graphRouteResultSelect.js +2 -2
  44. package/script/helpers/prepareGraphMetricOptions.d.ts +2 -2
  45. package/script/helpers/prepareGraphMetricOptions.d.ts.map +1 -1
  46. package/script/helpers/prepareGraphMetricOptions.js +5 -4
  47. package/script/helpers/prepareGraphRouteSql.d.ts +2 -2
  48. package/script/helpers/prepareGraphRouteSql.d.ts.map +1 -1
  49. package/script/helpers/prepareGraphRouteSql.js +4 -4
  50. package/script/helpers/validateGraphRouteResultSchema.d.ts +1 -1
  51. package/script/helpers/validateGraphRouteResultSchema.d.ts.map +1 -1
  52. package/script/helpers/validateGraphRouteResultSchema.js +3 -1
  53. package/script/methods/distances.d.ts +1 -1
  54. package/script/methods/distances.d.ts.map +1 -1
  55. package/script/methods/distances.js +235 -73
  56. package/script/methods/shortestPath.d.ts +1 -1
  57. package/script/methods/shortestPath.d.ts.map +1 -1
  58. package/script/methods/shortestPath.js +44 -28
  59. package/script/methods/similarityMahalanobis.js +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"prepareGraphMetricOptions.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphMetricOptions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,QAAQ,GAAG,aAAa,GAAG,aAAa,CAAC;CACpD,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAChB,0BAA0B,CAwD5B"}
1
+ {"version":3,"file":"prepareGraphMetricOptions.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphMetricOptions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC9C,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAChB,0BAA0B,CA2D5B"}
@@ -17,8 +17,9 @@ function prepareGraphMetricOptions(options, method, optimize) {
17
17
  if (!optimize) {
18
18
  throw new TypeError(`${method} options.minimize is not supported because this method returns all routes.`);
19
19
  }
20
- if (options.minimize !== "weight" && options.minimize !== "elapsedTime") {
21
- throw new TypeError(`${method} options.minimize must be "weight" or "elapsedTime".`);
20
+ if (options.minimize !== "steps" && options.minimize !== "weight" &&
21
+ options.minimize !== "elapsedTime") {
22
+ throw new TypeError(`${method} options.minimize must be "steps", "weight", or "elapsedTime".`);
22
23
  }
23
24
  if (options.minimize === "weight" && options.weight === undefined) {
24
25
  throw new TypeError(`${method} options.minimize: "weight" requires options.weight.`);
@@ -29,7 +30,7 @@ function prepareGraphMetricOptions(options, method, optimize) {
29
30
  }
30
31
  if (optimize && elapsedTime && options.weight !== undefined &&
31
32
  options.minimize === undefined) {
32
- throw new TypeError(`${method} when weight and elapsedTime are both enabled, specify options.minimize: "weight" or "elapsedTime".`);
33
+ throw new TypeError(`${method} when weight and elapsedTime are both enabled, specify options.minimize: "steps", "weight", or "elapsedTime".`);
33
34
  }
34
35
  return {
35
36
  elapsedTime,
@@ -38,6 +39,6 @@ function prepareGraphMetricOptions(options, method, optimize) {
38
39
  ? "weight"
39
40
  : elapsedTime
40
41
  ? "elapsedTime"
41
- : "connections"),
42
+ : "steps"),
42
43
  };
43
44
  }
@@ -8,13 +8,13 @@ export type PreparedGraphRouteEndpoints = {
8
8
  /** Prepares and validates the two scalar endpoints shared by route methods. */
9
9
  export declare function prepareGraphRouteEndpoints(start: GraphId, end: GraphId, method: string): PreparedGraphRouteEndpoints;
10
10
  /** Validates the columns shared by edge-route methods from queued schema data. */
11
- export declare function validateGraphRouteInputs(schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string): {
11
+ export declare function validateGraphRouteInputs(schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string, includeTotal?: boolean): {
12
12
  distanceType: string;
13
13
  edgeIdType: string;
14
14
  nodeIdType: string;
15
15
  };
16
16
  /** Prepares the typed SQL expressions shared by edge-route enumeration. */
17
- export declare function prepareGraphRouteSql(input: string, schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string): {
17
+ export declare function prepareGraphRouteSql(input: string, schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string, includeTotal?: boolean): {
18
18
  distanceType: string;
19
19
  edgeIdColumn: import("./getGraphEdgeIdColumn.js").GraphEdgeIdColumn;
20
20
  edgeKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"prepareGraphRouteSql.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphRouteSql.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAA2B,EACzB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,mBAAmB,CAAC;IACzB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACb,2BAA2B,CA+B7B;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM;;;;EAmBf;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM;;;;;;;;;;;;;EAkDf"}
1
+ {"version":3,"file":"prepareGraphRouteSql.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphRouteSql.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAA2B,EACzB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,mBAAmB,CAAC;IACzB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACb,2BAA2B,CA+B7B;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,EACd,YAAY,UAAO;;;;EAmBpB;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,EACd,YAAY,UAAO;;;;;;;;;;;;;EAkDpB"}
@@ -75,13 +75,13 @@ function prepareGraphRouteEndpoints(start, end, method) {
75
75
  };
76
76
  }
77
77
  /** Validates the columns shared by edge-route methods from queued schema data. */
78
- function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, weight, method) {
78
+ function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, weight, method, includeTotal = true) {
79
79
  const nodes = (0, prepareGraphTraversal_js_1.validateGraphStarts)(schema, source, target, endpoints.values, method);
80
80
  const edges = (0, getGraphEdgeIdColumn_js_1.default)(schema, edgeId, method);
81
81
  const weightColumn = weight === undefined
82
82
  ? undefined
83
83
  : (0, getGraphWeightColumn_js_1.default)(schema, weight, method);
84
- (0, validateGraphRouteResultSchema_js_1.default)(schema, method);
84
+ (0, validateGraphRouteResultSchema_js_1.default)(schema, method, [], includeTotal);
85
85
  return {
86
86
  distanceType: weightColumn?.distanceType ?? "BIGINT",
87
87
  edgeIdType: edges.idType,
@@ -89,8 +89,8 @@ function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, wei
89
89
  };
90
90
  }
91
91
  /** Prepares the typed SQL expressions shared by edge-route enumeration. */
92
- function prepareGraphRouteSql(input, schema, source, target, edgeId, endpoints, weight, method) {
93
- (0, validateGraphRouteResultSchema_js_1.default)(schema, method);
92
+ function prepareGraphRouteSql(input, schema, source, target, edgeId, endpoints, weight, method, includeTotal = true) {
93
+ (0, validateGraphRouteResultSchema_js_1.default)(schema, method, [], includeTotal);
94
94
  const traversal = (0, prepareGraphTraversal_js_1.default)(input, schema, source, target, endpoints.values, method);
95
95
  const edgeIdColumn = (0, getGraphEdgeIdColumn_js_1.default)(schema, edgeId, method);
96
96
  const weightColumn = weight === undefined
@@ -1,4 +1,4 @@
1
1
  import type { TableSchema } from "./pendingOps.js";
2
2
  /** Validates that route result columns do not replace original input columns. */
3
- export default function validateGraphRouteResultSchema(schema: TableSchema, method: string, additionalResultColumns?: readonly string[]): void;
3
+ export default function validateGraphRouteResultSchema(schema: TableSchema, method: string, additionalResultColumns?: readonly string[], includeTotal?: boolean): void;
4
4
  //# sourceMappingURL=validateGraphRouteResultSchema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateGraphRouteResultSchema.d.ts","sourceRoot":"","sources":["../../src/helpers/validateGraphRouteResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CACpD,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,uBAAuB,GAAE,SAAS,MAAM,EAAO,GAC9C,IAAI,CAkBN"}
1
+ {"version":3,"file":"validateGraphRouteResultSchema.d.ts","sourceRoot":"","sources":["../../src/helpers/validateGraphRouteResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CACpD,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,uBAAuB,GAAE,SAAS,MAAM,EAAO,EAC/C,YAAY,UAAO,GAClB,IAAI,CAmBN"}
@@ -8,8 +8,10 @@ const foldIdentifier_js_1 = __importDefault(require("./foldIdentifier.js"));
8
8
  const quoteIdentifier_js_1 = __importDefault(require("./quoteIdentifier.js"));
9
9
  const resultColumns = ["pathId", "step", "weight", "total"];
10
10
  /** Validates that route result columns do not replace original input columns. */
11
- function validateGraphRouteResultSchema(schema, method, additionalResultColumns = []) {
11
+ function validateGraphRouteResultSchema(schema, method, additionalResultColumns = [], includeTotal = true) {
12
12
  for (const resultColumn of [...resultColumns, ...additionalResultColumns]) {
13
+ if (resultColumn === "total" && !includeTotal)
14
+ continue;
13
15
  const folded = (0, foldIdentifier_js_1.default)(resultColumn);
14
16
  const inputColumn = Object.keys(schema).find((column) => (0, foldIdentifier_js_1.default)(column) === folded);
15
17
  if (inputColumn !== undefined) {
@@ -7,7 +7,7 @@ type DistancesOptions = GraphTemporalOptions & {
7
7
  outputTable?: string | boolean;
8
8
  weight?: string;
9
9
  elapsedTime?: boolean;
10
- minimize?: "weight" | "elapsedTime";
10
+ minimize?: "steps" | "weight" | "elapsedTime";
11
11
  };
12
12
  export default function distances(simpleTable: SimpleTable, sourceColumn: string, targetColumn: string, startNodes: GraphId | GraphId[], options?: DistancesOptions): SimpleTable;
13
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"distances.d.ts","sourceRoot":"","sources":["../../src/methods/distances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAOvD,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAA2B,EACzB,KAAK,OAAO,EAEb,MAAM,kCAAkC,CAAC;AAC1C,OAA8B,EAC5B,KAAK,cAAc,EAEpB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,gBAAgB,GAAG,oBAAoB,GAAG;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;CACrC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,GAAG,OAAO,EAAE,EAC/B,OAAO,GAAE,gBAAqB,GAC7B,WAAW,CA4Gb"}
1
+ {"version":3,"file":"distances.d.ts","sourceRoot":"","sources":["../../src/methods/distances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAOvD,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAA2B,EACzB,KAAK,OAAO,EAEb,MAAM,kCAAkC,CAAC;AAC1C,OAA8B,EAC5B,KAAK,cAAc,EAEpB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,gBAAgB,GAAG,oBAAoB,GAAG;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,GAAG,OAAO,EAAE,EAC/B,OAAO,GAAE,gBAAqB,GAC7B,WAAW,CA+Gb"}
@@ -98,7 +98,10 @@ function distances(simpleTable, sourceColumn, targetColumn, startNodes, options
98
98
  return {
99
99
  start: validated.idType,
100
100
  node: validated.idType,
101
- total: validated.distanceType,
101
+ steps: "BIGINT",
102
+ ...(options.weight === undefined
103
+ ? {}
104
+ : { total: validated.distanceType }),
102
105
  ...(metrics.elapsedTime ? { elapsedTimeMs: "DOUBLE" } : {}),
103
106
  };
104
107
  },
@@ -123,12 +126,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
123
126
  const edgeWeight = weightColumn === undefined
124
127
  ? `CAST(1 AS ${distanceType})`
125
128
  : `CAST(${(0, quoteIdentifier_js_1.default)("edges")}.${(0, quoteIdentifier_js_1.default)(weightColumn.column)} AS ${distanceType})`;
126
- if (temporalOptions !== undefined) {
127
- const temporal = (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "distances()");
128
- if (metrics.elapsedTime) {
129
- return elapsedDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics.minimize);
130
- }
131
- return temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight);
129
+ const temporal = temporalOptions === undefined
130
+ ? undefined
131
+ : (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "distances()");
132
+ if (weight !== undefined || metrics.elapsedTime) {
133
+ return summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, weight !== undefined, weightColumn?.type === "FLOAT" || weightColumn?.type === "DOUBLE");
134
+ }
135
+ if (temporal !== undefined) {
136
+ return temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, "steps", false);
132
137
  }
133
138
  const relations = prepared.relationNames([
134
139
  "graph_start_values",
@@ -152,6 +157,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
152
157
  const edgeCost = `${(0, quoteIdentifier_js_1.default)("edges")}.${(0, quoteIdentifier_js_1.default)("__weight")}`;
153
158
  const bestDistance = `${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("distance")}`;
154
159
  const candidateDistance = `CAST(${reachedDistance} + ${edgeCost} AS ${distanceType})`;
160
+ const candidateSteps = `${(0, quoteIdentifier_js_1.default)("reached")}.${(0, quoteIdentifier_js_1.default)("steps")} + 1`;
161
+ const bestSteps = `${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("steps")}`;
162
+ const order = (distance, steps) => metrics.minimize === "steps"
163
+ ? `ROW(${steps}, ${distance})`
164
+ : `ROW(${distance}, ${steps})`;
165
+ const candidateOrder = order(candidateDistance, candidateSteps);
166
+ const selectedDistance = `arg_min(${candidateDistance}, ${candidateOrder})`;
167
+ const selectedSteps = `arg_min(${candidateSteps}, ${candidateOrder})`;
155
168
  return `WITH RECURSIVE ${startValuesRelation}(${(0, quoteIdentifier_js_1.default)("start")}) AS (
156
169
  VALUES ${prepared.startValues}
157
170
  ), ${startsRelation} AS (
@@ -165,19 +178,20 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
165
178
  ), ${distancesRelation}(
166
179
  ${(0, quoteIdentifier_js_1.default)("start")}, ${(0, quoteIdentifier_js_1.default)("node")},
167
180
  ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("__node_key")},
168
- ${(0, quoteIdentifier_js_1.default)("distance")}
181
+ ${(0, quoteIdentifier_js_1.default)("distance")}, ${(0, quoteIdentifier_js_1.default)("steps")}
169
182
  ) USING KEY(
170
183
  ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}
171
184
  ) AS (
172
185
  SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},
173
- MIN(${edgeCost}) AS ${(0, quoteIdentifier_js_1.default)("distance")}
186
+ MIN(${edgeCost}) AS ${(0, quoteIdentifier_js_1.default)("distance")}, CAST(1 AS BIGINT)
174
187
  FROM ${startsRelation} AS ${(0, quoteIdentifier_js_1.default)("starts")}
175
188
  INNER JOIN ${edgesRelation} AS ${(0, quoteIdentifier_js_1.default)("edges")}
176
189
  ON ${startKey} = ${edgeFromKey}
177
190
  GROUP BY ${start}, ${edgeTo}, ${startKey}, ${edgeToKey}
178
191
  UNION
179
192
  SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
180
- MIN(${candidateDistance}) AS ${(0, quoteIdentifier_js_1.default)("distance")}
193
+ ${selectedDistance} AS ${(0, quoteIdentifier_js_1.default)("distance")},
194
+ ${selectedSteps} AS ${(0, quoteIdentifier_js_1.default)("steps")}
181
195
  FROM ${distancesRelation} AS ${(0, quoteIdentifier_js_1.default)("reached")}
182
196
  INNER JOIN ${edgesRelation} AS ${(0, quoteIdentifier_js_1.default)("edges")}
183
197
  ON ${reachedNodeKey} = ${edgeFromKey}
@@ -185,111 +199,259 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
185
199
  ON ${reachedStartKey} = ${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("__start_key")}
186
200
  AND ${edgeToKey} = ${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("__node_key")}
187
201
  GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
188
- ${bestDistance}
189
- HAVING ${bestDistance} IS NULL OR MIN(${candidateDistance}) < ${bestDistance}
202
+ ${bestDistance}, ${bestSteps}
203
+ HAVING ${bestDistance} IS NULL OR
204
+ ${order(selectedDistance, selectedSteps)} < ${order(bestDistance, bestSteps)}
190
205
  )
191
206
  SELECT ${(0, quoteIdentifier_js_1.default)("start")}, ${(0, quoteIdentifier_js_1.default)("node")},
192
- ${(0, quoteIdentifier_js_1.default)("distance")} AS ${(0, quoteIdentifier_js_1.default)("total")}
207
+ ${(0, quoteIdentifier_js_1.default)("steps")}${weight === undefined
208
+ ? ""
209
+ : `, ${(0, quoteIdentifier_js_1.default)("distance")} AS ${(0, quoteIdentifier_js_1.default)("total")}`}
193
210
  FROM ${distancesRelation}
194
- ORDER BY ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("distance")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}`;
211
+ ORDER BY ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)(metrics.minimize === "steps" ? "steps" : "distance")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}`;
195
212
  }
196
- function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight) {
213
+ function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, minimize, includeTotal) {
197
214
  const q = quoteIdentifier_js_1.default;
198
215
  const startsSelect = `SELECT ${q("start")},
199
216
  ${prepared.key(q("start"))} AS ${q("__key")}
200
217
  FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})`;
201
- const costStates = (0, buildGraphTemporalCostStateSql_js_1.default)(prepared, startsSelect, direction, temporal, distanceType, edgeWeight);
218
+ const costStates = (0, buildGraphTemporalCostStateSql_js_1.default)(prepared, startsSelect, direction, temporal, distanceType, edgeWeight, [], minimize);
219
+ const order = minimize === "steps"
220
+ ? `${q("steps")}, ${q("distance")}`
221
+ : `${q("distance")}, ${q("steps")}`;
202
222
  return `${costStates.withClause}
203
- SELECT ${q("start")}, ${q("node")},
204
- MIN(${q("distance")}) AS ${q("total")}
223
+ SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}
205
224
  FROM ${costStates.costRelation}
206
- GROUP BY ${q("start")}, ${q("node")}, ${q("__start_key")},
207
- ${q("__node_key")}
208
- ORDER BY ${q("__start_key")}, ${q("total")}, ${q("__node_key")}`;
225
+ QUALIFY row_number() OVER (
226
+ PARTITION BY ${q("__start_key")}, ${q("__node_key")}
227
+ ORDER BY ${order}
228
+ ) = 1
229
+ ORDER BY ${q("__start_key")}, ${q(minimize === "steps" ? "steps" : "distance")}, ${q("__node_key")}`;
209
230
  }
210
- function elapsedDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, minimize) {
231
+ // Distinct visited sets, metrics, and temporal boundaries are enough to extend
232
+ // summaries. No edge IDs or full connection sequences are needed. Keeping the
233
+ // visited set is necessary: equal summaries can have different legal extensions.
234
+ function summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, includeTotal, floatingWeight) {
211
235
  const q = quoteIdentifier_js_1.default;
212
236
  const relations = prepared.relationNames([
213
237
  "graph_starts",
214
238
  "graph_temporal_settings",
215
239
  "graph_event_rows",
216
240
  "graph_edges",
217
- "graph_elapsed_states",
218
- "graph_elapsed_results",
241
+ "graph_summaries",
242
+ "graph_metric_results",
243
+ "graph_tied_summaries",
244
+ "graph_best_metrics",
245
+ "graph_metric_bounds",
219
246
  ]);
220
247
  const starts = relations.graph_starts;
221
248
  const settings = relations.graph_temporal_settings;
222
249
  const events = relations.graph_event_rows;
223
250
  const edges = relations.graph_edges;
224
- const states = relations.graph_elapsed_states;
225
- const results = relations.graph_elapsed_results;
251
+ const summaries = relations.graph_summaries;
252
+ const results = relations.graph_metric_results;
253
+ const tied = relations.graph_tied_summaries;
226
254
  const ref = (alias, column) => `${q(alias)}.${q(column)}`;
227
- const anchor = temporal.journeyAnchor("edges", direction);
228
- const reachedAnchor = ref("reached", "__anchor");
229
- const candidateDistance = `CAST(${ref("reached", "distance")} + ${ref("edges", "__weight")} AS ${distanceType})`;
230
- const order = minimize === "elapsedTime"
231
- ? `${q("__elapsed")}, ${q("distance")}`
232
- : `${q("distance")}, ${q("__elapsed")}`;
233
- // A physical event and the first departure (last arrival for incoming
234
- // traversal) fix elapsed time. Keep the cheapest cost for each such state;
235
- // merging different anchors would lose later-departing, faster journeys.
236
- // The state space is finite, and strict improvements terminate zero cycles.
237
- return `WITH RECURSIVE ${settings} AS MATERIALIZED (
238
- SELECT CAST(? AS HUGEINT) AS ${q("__gap")}
255
+ const searchDirection = direction;
256
+ const firstAnchor = temporal?.journeyAnchor("edges", searchDirection);
257
+ const sum = `CAST(${ref("reached", "distance")} + ${ref("edges", "__weight")} AS ${distanceType})`;
258
+ // Reported costs must not reject routes before the primary objective has
259
+ // selected its results. NULL marks overflow and propagates through sums;
260
+ // non-negative weights cannot bring an overflowing total back into range.
261
+ const nextDistance = metrics.minimize === "weight" ? sum : `TRY(${sum})`;
262
+ const temporalColumns = temporal === undefined
263
+ ? ""
264
+ : `, ${q("__event_start")}, ${q("__event_end")}`;
265
+ const eventValues = temporal === undefined
266
+ ? ""
267
+ : `, ${ref("edges", "__event_start")}, ${ref("edges", "__event_end")}`;
268
+ const metric = metrics.minimize === "steps"
269
+ ? q("steps")
270
+ : metrics.minimize === "weight"
271
+ ? q("distance")
272
+ : q("__elapsed");
273
+ // Use native time precision for selection. Collapse equal reported values
274
+ // after conversion to milliseconds, since these are summary rows.
275
+ const reportedElapsed = metrics.elapsedTime
276
+ ? `, ${temporal.elapsedMilliseconds(q("__elapsed"))} AS ${q("elapsedTimeMs")}`
277
+ : "";
278
+ const order = metrics.minimize === "steps"
279
+ ? [
280
+ q("steps"),
281
+ q("__node_key"),
282
+ ...(includeTotal ? [q("total")] : []),
283
+ ...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
284
+ ]
285
+ : metrics.minimize === "weight"
286
+ ? [
287
+ q("total"),
288
+ q("__node_key"),
289
+ q("steps"),
290
+ ...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
291
+ ]
292
+ : [
293
+ q("elapsedTimeMs"),
294
+ q("__node_key"),
295
+ q("steps"),
296
+ ...(includeTotal ? [q("total")] : []),
297
+ ];
298
+ const bounds = summaryBoundsSql(relations.graph_best_metrics, relations.graph_metric_bounds, starts, edges, settings, temporal, searchDirection, metrics.minimize, distanceType, floatingWeight);
299
+ return `WITH RECURSIVE ${settings} AS (
300
+ ${temporal === undefined
301
+ ? `SELECT 0 AS ${q("__gap")}`
302
+ : `SELECT CAST(? AS HUGEINT) AS ${q("__gap")}`}
239
303
  ), ${events} AS MATERIALIZED (
240
304
  ${prepared.edges(direction, [
241
305
  `${edgeWeight} AS ${q("__weight")}`,
242
- ...temporal.eventSelections("edges"),
306
+ ...(temporal?.eventSelections("edges") ?? []),
243
307
  ])}
244
308
  ), ${edges} AS MATERIALIZED (
245
- SELECT * FROM ${events} AS ${q("events")}
246
- WHERE ${temporal.eventValidity("events")}
247
- ), ${starts} AS MATERIALIZED (
309
+ SELECT DISTINCT ${q("__from")}, ${q("__to")}, ${q("__from_key")},
310
+ ${q("__to_key")}, ${q("__weight")}${temporalColumns}
311
+ FROM ${events} AS ${q("events")}
312
+ ${temporal === undefined ? "" : `WHERE ${temporal.eventValidity("events")}`}
313
+ ), ${starts} AS (
248
314
  SELECT ${q("start")}, ${prepared.key(q("start"))} AS ${q("__key")}
249
315
  FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})
250
- ), ${states}(
316
+ ), ${bounds.ctes}, ${summaries}(
251
317
  ${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
252
- ${q("__event_id")}, ${q("__event_start")}, ${q("__event_end")},
253
- ${q("__anchor")}, ${q("distance")}
254
- ) USING KEY(${q("__start_key")}, ${q("__event_id")}, ${q("__anchor")}) AS (
318
+ ${q("__visited")}, ${q("steps")}, ${q("distance")}${temporalColumns}${metrics.elapsedTime ? `, ${q("__anchor")}` : ""}
319
+ ) AS (
255
320
  SELECT ${ref("starts", "start")}, ${ref("edges", "__to")},
256
321
  ${ref("starts", "__key")}, ${ref("edges", "__to_key")},
257
- ${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
258
- ${ref("edges", "__event_end")}, ${anchor}, ${ref("edges", "__weight")}
322
+ list_sort(list_distinct([${ref("starts", "__key")}, ${ref("edges", "__to_key")}])),
323
+ CAST(1 AS BIGINT), ${ref("edges", "__weight")}${eventValues}${metrics.elapsedTime ? `, ${firstAnchor}` : ""}
259
324
  FROM ${starts} AS ${q("starts")}
260
325
  INNER JOIN ${edges} AS ${q("edges")}
261
326
  ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
327
+ ${bounds.join(ref("starts", "__key"))}
328
+ WHERE ${bounds.test("CAST(1 AS BIGINT)", ref("edges", "__weight"), firstAnchor)}
262
329
  UNION
263
330
  SELECT ${ref("reached", "start")}, ${ref("edges", "__to")},
264
331
  ${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
265
- ${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
266
- ${ref("edges", "__event_end")}, ${reachedAnchor},
267
- MIN(${candidateDistance}) AS ${q("distance")}
268
- FROM ${states} AS ${q("reached")}
332
+ list_sort(list_distinct(list_append(${ref("reached", "__visited")}, ${ref("edges", "__to_key")}))),
333
+ ${ref("reached", "steps")} + 1, ${nextDistance}${eventValues}${metrics.elapsedTime ? `, ${ref("reached", "__anchor")}` : ""}
334
+ FROM ${summaries} AS ${q("reached")}
269
335
  INNER JOIN ${edges} AS ${q("edges")}
270
336
  ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
271
337
  CROSS JOIN ${settings} AS ${q("settings")}
272
- LEFT JOIN recurring.${states} AS ${q("best")}
273
- ON ${ref("reached", "__start_key")} = ${ref("best", "__start_key")}
274
- AND ${ref("edges", "__event_id")} = ${ref("best", "__event_id")}
275
- AND ${reachedAnchor} = ${ref("best", "__anchor")}
276
- WHERE ${temporal.transition("reached", "edges", direction, ref("settings", "__gap"))}
277
- GROUP BY ${ref("reached", "start")}, ${ref("edges", "__to")},
278
- ${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
279
- ${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
280
- ${ref("edges", "__event_end")}, ${reachedAnchor}, ${ref("best", "distance")}
281
- HAVING ${ref("best", "distance")} IS NULL OR
282
- MIN(${candidateDistance}) < ${ref("best", "distance")}
338
+ ${bounds.join(ref("reached", "__start_key"))}
339
+ WHERE ${bounds.test(`${ref("reached", "steps")} + 1`, nextDistance, ref("reached", "__anchor"))}
340
+ AND ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
341
+ AND (NOT list_contains(${ref("reached", "__visited")}, ${ref("edges", "__to_key")})
342
+ OR ${ref("edges", "__to_key")} = ${ref("reached", "__start_key")})
343
+ ${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", searchDirection, ref("settings", "__gap"))}`}
283
344
  ), ${results} AS (
284
- SELECT *, ${temporal.journeyElapsed("states", ref("states", "__anchor"), direction)} AS ${q("__elapsed")}
285
- FROM ${states} AS ${q("states")}
345
+ SELECT *${metrics.elapsedTime
346
+ ? `, ${temporal.journeyElapsed("summaries", ref("summaries", "__anchor"), searchDirection)} AS ${q("__elapsed")}`
347
+ : ""}
348
+ FROM ${summaries} AS ${q("summaries")}
349
+ ), ${tied} AS MATERIALIZED (
350
+ SELECT DISTINCT ${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
351
+ ${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}${reportedElapsed}
352
+ FROM ${results}
353
+ QUALIFY ${metric} = MIN(${metric}) OVER (
354
+ PARTITION BY ${q("__start_key")}, ${q("__node_key")}
355
+ )
286
356
  )
287
- SELECT ${q("start")}, ${q("node")}, ${q("distance")} AS ${q("total")},
288
- ${temporal.elapsedMilliseconds(q("__elapsed"))} AS ${q("elapsedTimeMs")}
289
- FROM ${results}
290
- QUALIFY row_number() OVER (
291
- PARTITION BY ${q("__start_key")}, ${q("__node_key")}
292
- ORDER BY ${order}, ${q("__event_id")}, ${q("__anchor")}
293
- ) = 1
294
- ORDER BY ${q("__start_key")}, ${order}, ${q("__node_key")}`;
357
+ SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal
358
+ ? `, CASE WHEN ${q("total")} IS NULL
359
+ THEN error('distances() total exceeds the supported ${distanceType} range for an optimal route.')
360
+ ELSE ${q("total")} END AS ${q("total")}`
361
+ : ""}${metrics.elapsedTime ? `, ${q("elapsedTimeMs")}` : ""}
362
+ FROM ${tied}
363
+ ORDER BY ${q("__start_key")}, ${order.join(", ")}`;
364
+ }
365
+ // Compute primary optima without enumerating visited sets. Exact additive
366
+ // objectives have optimal prefixes (at the same event boundary in temporal
367
+ // traversal). Floating addition can erase prefix differences, and elapsed
368
+ // optima can depend on a later departure, so those use a per-start upper bound.
369
+ function summaryBoundsSql(best, limits, starts, edges, settings, temporal, direction, minimize, distanceType, floatingWeight) {
370
+ const q = quoteIdentifier_js_1.default;
371
+ const ref = (alias, column) => `${q(alias)}.${q(column)}`;
372
+ const elapsed = minimize === "elapsedTime";
373
+ const globalBound = elapsed || (minimize === "weight" && floatingWeight);
374
+ const boundaries = temporal === undefined
375
+ ? []
376
+ : ["__event_start", "__event_end"];
377
+ const keys = [
378
+ "__start_key",
379
+ "__node_key",
380
+ ...boundaries,
381
+ ...(elapsed ? ["__anchor"] : []),
382
+ ];
383
+ const firstAnchor = elapsed
384
+ ? temporal.journeyAnchor("edges", direction)
385
+ : undefined;
386
+ const firstKeys = [
387
+ ref("starts", "__key"),
388
+ ref("edges", "__to_key"),
389
+ ...boundaries.map((key) => ref("edges", key)),
390
+ ...(elapsed ? [firstAnchor] : []),
391
+ ];
392
+ const nextKeys = [
393
+ ref("reached", "__start_key"),
394
+ ref("edges", "__to_key"),
395
+ ...boundaries.map((key) => ref("edges", key)),
396
+ ...(elapsed ? [ref("reached", "__anchor")] : []),
397
+ ];
398
+ const firstMetric = minimize === "steps"
399
+ ? "CAST(1 AS BIGINT)"
400
+ : elapsed
401
+ ? temporal.journeyElapsed("edges", firstAnchor, direction)
402
+ : ref("edges", "__weight");
403
+ const nextMetric = minimize === "steps"
404
+ ? `${ref("reached", "__metric")} + 1`
405
+ : elapsed
406
+ ? temporal.journeyElapsed("edges", ref("reached", "__anchor"), direction)
407
+ : `CAST(${ref("reached", "__metric")} + ${ref("edges", "__weight")} AS ${distanceType})`;
408
+ const minimum = `MIN(${nextMetric})`;
409
+ const bestMetric = ref("best", "__metric");
410
+ const ctes = `${best}(${keys.map(q).join(", ")}, ${q("__metric")})
411
+ USING KEY(${keys.map(q).join(", ")}) AS (
412
+ SELECT ${firstKeys.join(", ")}, MIN(${firstMetric})
413
+ FROM ${starts} AS ${q("starts")}
414
+ INNER JOIN ${edges} AS ${q("edges")}
415
+ ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
416
+ GROUP BY ${firstKeys.join(", ")}
417
+ UNION
418
+ SELECT ${nextKeys.join(", ")}, ${minimum}
419
+ FROM ${best} AS ${q("reached")}
420
+ INNER JOIN ${edges} AS ${q("edges")}
421
+ ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
422
+ CROSS JOIN ${settings} AS ${q("settings")}
423
+ LEFT JOIN recurring.${best} AS ${q("best")}
424
+ ON ${keys.map((key, i) => `${ref("best", key)} = ${nextKeys[i]}`).join(" AND ")}
425
+ WHERE ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
426
+ ${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", direction, ref("settings", "__gap"))}`}
427
+ GROUP BY ${nextKeys.join(", ")}, ${bestMetric}
428
+ HAVING ${bestMetric} IS NULL OR ${minimum} < ${bestMetric}
429
+ )${globalBound
430
+ ? `, ${limits} AS (
431
+ SELECT ${q("__start_key")}, MAX(${q("__minimum")}) AS ${q("__metric")}
432
+ FROM (
433
+ SELECT ${q("__start_key")}, ${q("__node_key")}, MIN(${q("__metric")}) AS ${q("__minimum")}
434
+ FROM ${best}
435
+ GROUP BY ${q("__start_key")}, ${q("__node_key")}
436
+ ) AS ${q("minima")}
437
+ GROUP BY ${q("__start_key")}
438
+ )`
439
+ : ""}`;
440
+ return {
441
+ ctes,
442
+ join: (startKey) => `INNER JOIN ${globalBound ? limits : best} AS ${q("bounds")}
443
+ ON ${ref("bounds", "__start_key")} = ${startKey}
444
+ ${globalBound
445
+ ? ""
446
+ : `AND ${ref("bounds", "__node_key")} = ${ref("edges", "__to_key")}
447
+ ${boundaries.map((key) => `AND ${ref("bounds", key)} = ${ref("edges", key)}`).join(" ")}`}`,
448
+ test: (steps, distance, anchor) => {
449
+ const metric = minimize === "steps"
450
+ ? steps
451
+ : elapsed
452
+ ? temporal.journeyElapsed("edges", anchor, direction)
453
+ : distance;
454
+ return `${metric} ${globalBound ? "<=" : "="} ${ref("bounds", "__metric")}`;
455
+ },
456
+ };
295
457
  }
@@ -7,7 +7,7 @@ type ShortestPathOptions = GraphTemporalOptions & {
7
7
  outputTable?: string | boolean;
8
8
  weight?: string;
9
9
  elapsedTime?: boolean;
10
- minimize?: "weight" | "elapsedTime";
10
+ minimize?: "steps" | "weight" | "elapsedTime";
11
11
  };
12
12
  export default function shortestPath(simpleTable: SimpleTable, sourceColumn: string, targetColumn: string, edgeId: string, start: GraphId, end: GraphId, options?: ShortestPathOptions): SimpleTable;
13
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"shortestPath.d.ts","sourceRoot":"","sources":["../../src/methods/shortestPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAMvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAShE,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAK1E,KAAK,mBAAmB,GAAG,oBAAoB,GAAG;IAChD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;CACrC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,WAAW,CAsHb"}
1
+ {"version":3,"file":"shortestPath.d.ts","sourceRoot":"","sources":["../../src/methods/shortestPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAMvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAShE,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAK1E,KAAK,mBAAmB,GAAG,oBAAoB,GAAG;IAChD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,WAAW,CAyHb"}