@nshiab/simple-data-analysis-core 2.1.12 → 2.1.13

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 (2123) hide show
  1. package/README.md +56 -70
  2. package/dist/SimpleDB-d3LMXBzY.mjs +23823 -0
  3. package/dist/SimpleDB-d3LMXBzY.mjs.map +1 -0
  4. package/dist/SimpleTable-BdiLf6k7.d.mts +8760 -0
  5. package/dist/helpers/index.d.mts +324 -0
  6. package/dist/helpers/index.mjs +166 -0
  7. package/dist/helpers/index.mjs.map +1 -0
  8. package/dist/index.d.mts +67 -0
  9. package/dist/index.mjs +1 -0
  10. package/llm.md +11214 -7618
  11. package/llms.txt +18 -22
  12. package/package.json +50 -22
  13. package/src/class/SDAError.ts +74 -0
  14. package/src/class/Simple.ts +104 -0
  15. package/src/class/SimpleDB.ts +1131 -0
  16. package/src/class/SimpleTable.ts +9263 -0
  17. package/src/helpers/LogValue.ts +16 -0
  18. package/src/helpers/appendColumnBatches.ts +32 -0
  19. package/src/helpers/assertColumnsExist.ts +31 -0
  20. package/src/helpers/assertNewColumns.ts +33 -0
  21. package/src/helpers/assertSameDatabase.ts +26 -0
  22. package/src/helpers/asyncOperationContext.ts +64 -0
  23. package/src/helpers/buildApproximateMutualReachabilityMst.ts +307 -0
  24. package/src/helpers/buildChronologicalGraphComponentsSql.ts +193 -0
  25. package/src/helpers/buildExactMutualReachabilityMst.ts +122 -0
  26. package/src/helpers/buildFuzzyMatchSql.ts +30 -0
  27. package/src/helpers/buildGraphTemporalCostStateSql.ts +120 -0
  28. package/src/helpers/buildGraphTemporalReachabilitySql.ts +84 -0
  29. package/src/helpers/buildSparseMutualReachabilityMst.ts +53 -0
  30. package/src/helpers/buildUmapGraph.ts +85 -0
  31. package/src/helpers/buildVectorNeighbors.ts +248 -0
  32. package/src/helpers/buildWeakGraphComponentsSql.ts +38 -0
  33. package/src/helpers/cacheDatabase.ts +146 -0
  34. package/src/helpers/cacheDiagnostics.ts +42 -0
  35. package/src/helpers/cacheTableDependencies.ts +292 -0
  36. package/src/helpers/camelCase.ts +50 -0
  37. package/src/helpers/capitalize.ts +35 -0
  38. package/src/helpers/cleanCache.ts +33 -0
  39. package/src/helpers/cleanPath.ts +3 -0
  40. package/src/helpers/cleanSQL.ts +278 -0
  41. package/src/helpers/clusterHdbscan.ts +396 -0
  42. package/src/helpers/computeCovariance.ts +139 -0
  43. package/src/helpers/computeMahalanobisDistances.ts +114 -0
  44. package/src/helpers/createDirectory.ts +26 -0
  45. package/src/helpers/csvFormat.ts +74 -0
  46. package/src/helpers/dataToArrays.ts +63 -0
  47. package/src/helpers/ensureSpatial.ts +23 -0
  48. package/src/helpers/extractTypes.ts +17 -0
  49. package/src/helpers/extractZipEntryToFile.ts +268 -0
  50. package/src/helpers/factorCovariance.ts +233 -0
  51. package/src/helpers/fileCache.ts +199 -0
  52. package/src/helpers/findGeoColumn.ts +23 -0
  53. package/src/helpers/findGeoColumnFromSchema.ts +46 -0
  54. package/src/helpers/fitUmapCurve.ts +68 -0
  55. package/src/helpers/flushAllTables.ts +500 -0
  56. package/src/helpers/foldIdentifier.ts +4 -0
  57. package/src/helpers/formatDate.ts +76 -0
  58. package/src/helpers/formatMissingTables.ts +39 -0
  59. package/src/helpers/formatNumber.ts +166 -0
  60. package/src/helpers/geometryFromJSON.ts +4 -0
  61. package/src/helpers/getCombinations.ts +27 -0
  62. package/src/helpers/getCurrentDatabase.ts +9 -0
  63. package/src/helpers/getDbFileType.ts +10 -0
  64. package/src/helpers/getDbIndexes.ts +11 -0
  65. package/src/helpers/getExtension.ts +6 -0
  66. package/src/helpers/getGraphEdgeIdColumn.ts +45 -0
  67. package/src/helpers/getGraphEndpointColumns.ts +205 -0
  68. package/src/helpers/getGraphWeightColumn.ts +64 -0
  69. package/src/helpers/getIdenticalColumns.ts +3 -0
  70. package/src/helpers/getName.ts +13 -0
  71. package/src/helpers/getStatExpression.ts +90 -0
  72. package/src/helpers/graphRouteResultSchema.ts +26 -0
  73. package/src/helpers/graphRouteResultSelect.ts +39 -0
  74. package/src/helpers/hasGeometryColumn.ts +24 -0
  75. package/src/helpers/index.ts +23 -0
  76. package/src/helpers/indexDefinitions.ts +40 -0
  77. package/src/helpers/indexQueries.ts +53 -0
  78. package/src/helpers/initialUmapCoordinates.ts +6 -0
  79. package/src/helpers/inspectGraphConnectivity.ts +64 -0
  80. package/src/helpers/keepNumericalColumns.ts +14 -0
  81. package/src/helpers/loadOsmFile.ts +33 -0
  82. package/src/helpers/logData.ts +76 -0
  83. package/src/helpers/makeLogConverter.ts +69 -0
  84. package/src/helpers/mergeOptions.ts +78 -0
  85. package/src/helpers/normalizeCacheCode.ts +348 -0
  86. package/src/helpers/observeQuery.ts +64 -0
  87. package/src/helpers/optimizeUmapLayout.ts +103 -0
  88. package/src/helpers/osmCache.ts +280 -0
  89. package/src/helpers/osmFiles.ts +370 -0
  90. package/src/helpers/parseDuckDBType.ts +41 -0
  91. package/src/helpers/parseTypes.ts +57 -0
  92. package/src/helpers/parseValue.ts +34 -0
  93. package/src/helpers/pendingOps.ts +154 -0
  94. package/src/helpers/prepareDbExtensions.ts +48 -0
  95. package/src/helpers/prepareGeometry.ts +114 -0
  96. package/src/helpers/prepareGraphMetricOptions.ts +67 -0
  97. package/src/helpers/prepareGraphRouteSql.ts +123 -0
  98. package/src/helpers/prepareGraphStarts.ts +92 -0
  99. package/src/helpers/prepareGraphTemporalSql.ts +250 -0
  100. package/src/helpers/prepareGraphTraversal.ts +133 -0
  101. package/src/helpers/prepareJSON.ts +63 -0
  102. package/src/helpers/prepareNumericFeatures.ts +354 -0
  103. package/src/helpers/prepareUmapLayoutOptions.ts +38 -0
  104. package/src/helpers/prepareValueFilters.ts +22 -0
  105. package/src/helpers/prettyDuration.ts +164 -0
  106. package/src/helpers/printTable.ts +264 -0
  107. package/src/helpers/publishPreparedColumns.ts +172 -0
  108. package/src/helpers/queryDB.ts +116 -0
  109. package/src/helpers/queryDbFile.ts +22 -0
  110. package/src/helpers/queueAsyncBarrier.ts +63 -0
  111. package/src/helpers/queueGraphResult.ts +58 -0
  112. package/src/helpers/queueOp.ts +84 -0
  113. package/src/helpers/quoteIdentifier.ts +18 -0
  114. package/src/helpers/quoteQualifiedIdentifier.ts +23 -0
  115. package/src/helpers/readCacheSources.ts +72 -0
  116. package/src/helpers/readDbMetadata.ts +81 -0
  117. package/src/helpers/readMutationRows.ts +107 -0
  118. package/src/helpers/readScalarNumber.ts +6 -0
  119. package/src/helpers/referencedTables.ts +24 -0
  120. package/src/helpers/removeColumnsNow.ts +27 -0
  121. package/src/helpers/resolveOutputTable.ts +19 -0
  122. package/src/helpers/rewind.ts +316 -0
  123. package/src/helpers/runQuery.ts +179 -0
  124. package/src/helpers/scanSQL.ts +61 -0
  125. package/src/helpers/selectFuzzyReplacements.ts +140 -0
  126. package/src/helpers/serializeCacheInputs.ts +117 -0
  127. package/src/helpers/setDbProps.ts +31 -0
  128. package/src/helpers/splitGraphemes.ts +7 -0
  129. package/src/helpers/stabilizeCosineVectors.ts +44 -0
  130. package/src/helpers/statCanCache.ts +57 -0
  131. package/src/helpers/stringToArray.ts +24 -0
  132. package/src/helpers/stringifyDates.ts +19 -0
  133. package/src/helpers/stringifyDatesInvert.ts +19 -0
  134. package/src/helpers/stringifyUnknown.ts +56 -0
  135. package/src/helpers/tableGeneration.ts +43 -0
  136. package/src/helpers/tableRegistry.ts +89 -0
  137. package/src/helpers/toDuckDBValue.ts +21 -0
  138. package/src/helpers/umapRandom.ts +10 -0
  139. package/src/helpers/unifyColumns.ts +49 -0
  140. package/src/helpers/updateColumnsWithJS.ts +199 -0
  141. package/src/helpers/validateGraphRouteResultSchema.ts +30 -0
  142. package/src/helpers/validateGraphTemporalEvents.ts +63 -0
  143. package/src/helpers/validateNumericalAnalysis.ts +83 -0
  144. package/src/helpers/validateVectorRowIds.ts +29 -0
  145. package/src/helpers/vectorDistanceExpression.ts +14 -0
  146. package/src/helpers/wrapString.ts +102 -0
  147. package/src/helpers/writeDataAsArrays.ts +14 -0
  148. package/src/helpers/writeDbMetadata.ts +19 -0
  149. package/src/helpers/writeGeoData.ts +248 -0
  150. package/src/helpers/writeZip.ts +311 -0
  151. package/src/index.ts +29 -0
  152. package/src/methods/accumulate.ts +64 -0
  153. package/src/methods/addBoundingBox.ts +35 -0
  154. package/src/methods/addCharacterCount.ts +23 -0
  155. package/src/methods/addColumn.ts +54 -0
  156. package/src/methods/addGeoClosedStatus.ts +30 -0
  157. package/src/methods/addGeoNoise.ts +185 -0
  158. package/src/methods/addGeoType.ts +30 -0
  159. package/src/methods/addGeoValidity.ts +30 -0
  160. package/src/methods/addId.ts +55 -0
  161. package/src/methods/addNoise.ts +86 -0
  162. package/src/methods/addRowNumber.ts +40 -0
  163. package/src/methods/addSummaryRows.ts +209 -0
  164. package/src/methods/addVertexCount.ts +30 -0
  165. package/src/methods/addWordCount.ts +19 -0
  166. package/src/methods/aggregateGeo.ts +105 -0
  167. package/src/methods/area.ts +36 -0
  168. package/src/methods/bins.ts +150 -0
  169. package/src/methods/bm25.ts +158 -0
  170. package/src/methods/buffer.ts +32 -0
  171. package/src/methods/cache.ts +464 -0
  172. package/src/methods/capitalize.ts +23 -0
  173. package/src/methods/centroid.ts +31 -0
  174. package/src/methods/clone.ts +55 -0
  175. package/src/methods/cloneColumn.ts +20 -0
  176. package/src/methods/cloneColumnWithOffset.ts +58 -0
  177. package/src/methods/columnProportions.ts +44 -0
  178. package/src/methods/commonNeighbors.ts +157 -0
  179. package/src/methods/concatenate.ts +33 -0
  180. package/src/methods/connectedComponents.ts +195 -0
  181. package/src/methods/convert.ts +228 -0
  182. package/src/methods/correlations.ts +136 -0
  183. package/src/methods/coveredBy.ts +25 -0
  184. package/src/methods/createFtsIndex.ts +139 -0
  185. package/src/methods/createPoints.ts +33 -0
  186. package/src/methods/createVssIndex.ts +99 -0
  187. package/src/methods/crossJoin.ts +68 -0
  188. package/src/methods/degree.ts +170 -0
  189. package/src/methods/difference.ts +28 -0
  190. package/src/methods/distance.ts +79 -0
  191. package/src/methods/distances.ts +627 -0
  192. package/src/methods/extractDatePart.ts +65 -0
  193. package/src/methods/extractLatLon.ts +27 -0
  194. package/src/methods/fill.ts +100 -0
  195. package/src/methods/fillHoles.ts +22 -0
  196. package/src/methods/filter.ts +17 -0
  197. package/src/methods/findCycles.ts +480 -0
  198. package/src/methods/firstChars.ts +16 -0
  199. package/src/methods/fixGeo.ts +25 -0
  200. package/src/methods/flipCoordinates.ts +25 -0
  201. package/src/methods/fuzzyClean.ts +142 -0
  202. package/src/methods/fuzzyJoin.ts +267 -0
  203. package/src/methods/getBottom.ts +42 -0
  204. package/src/methods/getBoundingBox.ts +28 -0
  205. package/src/methods/getCharacterCount.ts +29 -0
  206. package/src/methods/getColumns.ts +25 -0
  207. package/src/methods/getData.ts +42 -0
  208. package/src/methods/getDescription.ts +30 -0
  209. package/src/methods/getFirstRow.ts +31 -0
  210. package/src/methods/getGeoData.ts +60 -0
  211. package/src/methods/getHash.ts +45 -0
  212. package/src/methods/getLastRow.ts +37 -0
  213. package/src/methods/getMax.ts +29 -0
  214. package/src/methods/getMean.ts +39 -0
  215. package/src/methods/getMedian.ts +38 -0
  216. package/src/methods/getMin.ts +28 -0
  217. package/src/methods/getQuantile.ts +39 -0
  218. package/src/methods/getRow.ts +16 -0
  219. package/src/methods/getRowCount.ts +29 -0
  220. package/src/methods/getSchema.ts +20 -0
  221. package/src/methods/getSkew.ts +38 -0
  222. package/src/methods/getStdDev.ts +38 -0
  223. package/src/methods/getSum.ts +29 -0
  224. package/src/methods/getTableNames.ts +24 -0
  225. package/src/methods/getTop.ts +31 -0
  226. package/src/methods/getTypes.ts +22 -0
  227. package/src/methods/getUniques.ts +29 -0
  228. package/src/methods/getValues.ts +27 -0
  229. package/src/methods/getVariance.ts +39 -0
  230. package/src/methods/hdbscan.ts +278 -0
  231. package/src/methods/indexValues.ts +436 -0
  232. package/src/methods/insertRows.ts +53 -0
  233. package/src/methods/insertTables.ts +155 -0
  234. package/src/methods/intersection.ts +28 -0
  235. package/src/methods/intersects.ts +25 -0
  236. package/src/methods/join.ts +160 -0
  237. package/src/methods/joinGeo.ts +252 -0
  238. package/src/methods/keepValues.ts +49 -0
  239. package/src/methods/lastChars.ts +16 -0
  240. package/src/methods/length.ts +36 -0
  241. package/src/methods/linearRegressions.ts +147 -0
  242. package/src/methods/linesToPolygons.ts +20 -0
  243. package/src/methods/loadArray.ts +310 -0
  244. package/src/methods/loadDB.ts +73 -0
  245. package/src/methods/loadData.ts +238 -0
  246. package/src/methods/loadGeoData.ts +112 -0
  247. package/src/methods/loadOpenStreetMap.ts +498 -0
  248. package/src/methods/loadSample.ts +58 -0
  249. package/src/methods/loadStatCanData.ts +183 -0
  250. package/src/methods/loadYahooFinanceData.ts +205 -0
  251. package/src/methods/log.ts +76 -0
  252. package/src/methods/logBottom.ts +15 -0
  253. package/src/methods/longer.ts +33 -0
  254. package/src/methods/lower.ts +18 -0
  255. package/src/methods/neighbors.ts +133 -0
  256. package/src/methods/nest.ts +31 -0
  257. package/src/methods/normalize.ts +65 -0
  258. package/src/methods/normalizeString.ts +36 -0
  259. package/src/methods/normalizeVector.ts +202 -0
  260. package/src/methods/outliersIQR.ts +55 -0
  261. package/src/methods/pad.ts +88 -0
  262. package/src/methods/paths.ts +405 -0
  263. package/src/methods/perimeter.ts +36 -0
  264. package/src/methods/quantiles.ts +36 -0
  265. package/src/methods/randomPoint.ts +136 -0
  266. package/src/methods/ranks.ts +39 -0
  267. package/src/methods/reachable.ts +230 -0
  268. package/src/methods/reducePrecision.ts +35 -0
  269. package/src/methods/removeColumns.ts +16 -0
  270. package/src/methods/removeDuplicates.ts +25 -0
  271. package/src/methods/removeMissing.ts +111 -0
  272. package/src/methods/removeRows.ts +16 -0
  273. package/src/methods/removeTable.ts +21 -0
  274. package/src/methods/removeTables.ts +47 -0
  275. package/src/methods/removeValues.ts +51 -0
  276. package/src/methods/renameColumns.ts +34 -0
  277. package/src/methods/renameTable.ts +22 -0
  278. package/src/methods/repeatRows.ts +29 -0
  279. package/src/methods/replace.ts +83 -0
  280. package/src/methods/replaceNulls.ts +41 -0
  281. package/src/methods/reproject.ts +31 -0
  282. package/src/methods/rolling.ts +76 -0
  283. package/src/methods/round.ts +35 -0
  284. package/src/methods/rowProportions.ts +52 -0
  285. package/src/methods/rowRanks.ts +171 -0
  286. package/src/methods/rowToText.ts +34 -0
  287. package/src/methods/rowToVector.ts +122 -0
  288. package/src/methods/sample.ts +27 -0
  289. package/src/methods/selectColumns.ts +23 -0
  290. package/src/methods/selectRows.ts +45 -0
  291. package/src/methods/selectTables.ts +55 -0
  292. package/src/methods/setTypes.ts +63 -0
  293. package/src/methods/shortestPath.ts +621 -0
  294. package/src/methods/similarityMahalanobis.ts +166 -0
  295. package/src/methods/simplify.ts +64 -0
  296. package/src/methods/skip.ts +13 -0
  297. package/src/methods/sort.ts +52 -0
  298. package/src/methods/splitExtract.ts +29 -0
  299. package/src/methods/splitSpread.ts +140 -0
  300. package/src/methods/stream.ts +79 -0
  301. package/src/methods/summarize.ts +196 -0
  302. package/src/methods/topologicalSort.ts +189 -0
  303. package/src/methods/trim.ts +50 -0
  304. package/src/methods/truncate.ts +16 -0
  305. package/src/methods/umap.ts +186 -0
  306. package/src/methods/union.ts +28 -0
  307. package/src/methods/unnest.ts +18 -0
  308. package/src/methods/unnestGeo.ts +21 -0
  309. package/src/methods/updateColumn.ts +20 -0
  310. package/src/methods/updateWithJS.ts +291 -0
  311. package/src/methods/upper.ts +18 -0
  312. package/src/methods/wider.ts +41 -0
  313. package/src/methods/writeDB.ts +127 -0
  314. package/src/methods/writeData.ts +109 -0
  315. package/src/methods/zScore.ts +44 -0
  316. package/esm/_dnt.polyfills.d.ts +0 -18
  317. package/esm/_dnt.polyfills.d.ts.map +0 -1
  318. package/esm/_dnt.polyfills.js +0 -15
  319. package/esm/class/SDAError.d.ts +0 -63
  320. package/esm/class/SDAError.d.ts.map +0 -1
  321. package/esm/class/SDAError.js +0 -83
  322. package/esm/class/Simple.d.ts +0 -90
  323. package/esm/class/Simple.d.ts.map +0 -1
  324. package/esm/class/Simple.js +0 -113
  325. package/esm/class/SimpleDB.d.ts +0 -726
  326. package/esm/class/SimpleDB.d.ts.map +0 -1
  327. package/esm/class/SimpleDB.js +0 -1133
  328. package/esm/class/SimpleTable.d.ts +0 -7801
  329. package/esm/class/SimpleTable.d.ts.map +0 -1
  330. package/esm/class/SimpleTable.js +0 -7949
  331. package/esm/helpers/LogValue.d.ts +0 -8
  332. package/esm/helpers/LogValue.d.ts.map +0 -1
  333. package/esm/helpers/LogValue.js +0 -23
  334. package/esm/helpers/appendColumnBatches.d.ts +0 -3
  335. package/esm/helpers/appendColumnBatches.d.ts.map +0 -1
  336. package/esm/helpers/appendColumnBatches.js +0 -21
  337. package/esm/helpers/assertColumnsExist.d.ts +0 -16
  338. package/esm/helpers/assertColumnsExist.d.ts.map +0 -1
  339. package/esm/helpers/assertColumnsExist.js +0 -21
  340. package/esm/helpers/assertNewColumns.d.ts +0 -17
  341. package/esm/helpers/assertNewColumns.d.ts.map +0 -1
  342. package/esm/helpers/assertNewColumns.js +0 -22
  343. package/esm/helpers/assertSameDatabase.d.ts +0 -11
  344. package/esm/helpers/assertSameDatabase.d.ts.map +0 -1
  345. package/esm/helpers/assertSameDatabase.js +0 -13
  346. package/esm/helpers/asyncOperationContext.d.ts +0 -19
  347. package/esm/helpers/asyncOperationContext.d.ts.map +0 -1
  348. package/esm/helpers/asyncOperationContext.js +0 -38
  349. package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts +0 -45
  350. package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts.map +0 -1
  351. package/esm/helpers/buildApproximateMutualReachabilityMst.js +0 -212
  352. package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts +0 -14
  353. package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts.map +0 -1
  354. package/esm/helpers/buildChronologicalGraphComponentsSql.js +0 -167
  355. package/esm/helpers/buildExactMutualReachabilityMst.d.ts +0 -28
  356. package/esm/helpers/buildExactMutualReachabilityMst.d.ts.map +0 -1
  357. package/esm/helpers/buildExactMutualReachabilityMst.js +0 -97
  358. package/esm/helpers/buildFuzzyMatchSql.d.ts +0 -9
  359. package/esm/helpers/buildFuzzyMatchSql.d.ts.map +0 -1
  360. package/esm/helpers/buildFuzzyMatchSql.js +0 -17
  361. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts +0 -12
  362. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts.map +0 -1
  363. package/esm/helpers/buildGraphTemporalCostStateSql.js +0 -100
  364. package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts +0 -13
  365. package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts.map +0 -1
  366. package/esm/helpers/buildGraphTemporalReachabilitySql.js +0 -70
  367. package/esm/helpers/buildSparseMutualReachabilityMst.d.ts +0 -10
  368. package/esm/helpers/buildSparseMutualReachabilityMst.d.ts.map +0 -1
  369. package/esm/helpers/buildSparseMutualReachabilityMst.js +0 -47
  370. package/esm/helpers/buildUmapGraph.d.ts +0 -21
  371. package/esm/helpers/buildUmapGraph.d.ts.map +0 -1
  372. package/esm/helpers/buildUmapGraph.js +0 -61
  373. package/esm/helpers/buildVectorNeighbors.d.ts +0 -45
  374. package/esm/helpers/buildVectorNeighbors.d.ts.map +0 -1
  375. package/esm/helpers/buildVectorNeighbors.js +0 -170
  376. package/esm/helpers/buildWeakGraphComponentsSql.d.ts +0 -3
  377. package/esm/helpers/buildWeakGraphComponentsSql.d.ts.map +0 -1
  378. package/esm/helpers/buildWeakGraphComponentsSql.js +0 -32
  379. package/esm/helpers/cacheDatabase.d.ts +0 -5
  380. package/esm/helpers/cacheDatabase.d.ts.map +0 -1
  381. package/esm/helpers/cacheDatabase.js +0 -111
  382. package/esm/helpers/cacheDiagnostics.d.ts +0 -4
  383. package/esm/helpers/cacheDiagnostics.d.ts.map +0 -1
  384. package/esm/helpers/cacheDiagnostics.js +0 -21
  385. package/esm/helpers/cacheTableDependencies.d.ts +0 -28
  386. package/esm/helpers/cacheTableDependencies.d.ts.map +0 -1
  387. package/esm/helpers/cacheTableDependencies.js +0 -227
  388. package/esm/helpers/camelCase.d.ts +0 -32
  389. package/esm/helpers/camelCase.d.ts.map +0 -1
  390. package/esm/helpers/camelCase.js +0 -47
  391. package/esm/helpers/capitalize.d.ts +0 -30
  392. package/esm/helpers/capitalize.d.ts.map +0 -1
  393. package/esm/helpers/capitalize.js +0 -35
  394. package/esm/helpers/cleanCache.d.ts +0 -3
  395. package/esm/helpers/cleanCache.d.ts.map +0 -1
  396. package/esm/helpers/cleanCache.js +0 -17
  397. package/esm/helpers/cleanPath.d.ts +0 -2
  398. package/esm/helpers/cleanPath.d.ts.map +0 -1
  399. package/esm/helpers/cleanPath.js +0 -3
  400. package/esm/helpers/cleanSQL.d.ts +0 -2
  401. package/esm/helpers/cleanSQL.d.ts.map +0 -1
  402. package/esm/helpers/cleanSQL.js +0 -269
  403. package/esm/helpers/clusterHdbscan.d.ts +0 -18
  404. package/esm/helpers/clusterHdbscan.d.ts.map +0 -1
  405. package/esm/helpers/clusterHdbscan.js +0 -342
  406. package/esm/helpers/computeCovariance.d.ts +0 -16
  407. package/esm/helpers/computeCovariance.d.ts.map +0 -1
  408. package/esm/helpers/computeCovariance.js +0 -99
  409. package/esm/helpers/computeMahalanobisDistances.d.ts +0 -14
  410. package/esm/helpers/computeMahalanobisDistances.d.ts.map +0 -1
  411. package/esm/helpers/computeMahalanobisDistances.js +0 -87
  412. package/esm/helpers/createDirectory.d.ts +0 -16
  413. package/esm/helpers/createDirectory.d.ts.map +0 -1
  414. package/esm/helpers/createDirectory.js +0 -24
  415. package/esm/helpers/csvFormat.d.ts +0 -3
  416. package/esm/helpers/csvFormat.d.ts.map +0 -1
  417. package/esm/helpers/csvFormat.js +0 -165
  418. package/esm/helpers/dataToArrays.d.ts +0 -53
  419. package/esm/helpers/dataToArrays.d.ts.map +0 -1
  420. package/esm/helpers/dataToArrays.js +0 -57
  421. package/esm/helpers/ensureSpatial.d.ts +0 -7
  422. package/esm/helpers/ensureSpatial.d.ts.map +0 -1
  423. package/esm/helpers/ensureSpatial.js +0 -17
  424. package/esm/helpers/extractTypes.d.ts +0 -6
  425. package/esm/helpers/extractTypes.d.ts.map +0 -1
  426. package/esm/helpers/extractTypes.js +0 -6
  427. package/esm/helpers/extractZipEntryToFile.d.ts +0 -3
  428. package/esm/helpers/extractZipEntryToFile.d.ts.map +0 -1
  429. package/esm/helpers/extractZipEntryToFile.js +0 -226
  430. package/esm/helpers/factorCovariance.d.ts +0 -17
  431. package/esm/helpers/factorCovariance.d.ts.map +0 -1
  432. package/esm/helpers/factorCovariance.js +0 -189
  433. package/esm/helpers/fileCache.d.ts +0 -15
  434. package/esm/helpers/fileCache.d.ts.map +0 -1
  435. package/esm/helpers/fileCache.js +0 -128
  436. package/esm/helpers/findGeoColumn.d.ts +0 -17
  437. package/esm/helpers/findGeoColumn.d.ts.map +0 -1
  438. package/esm/helpers/findGeoColumn.js +0 -18
  439. package/esm/helpers/findGeoColumnFromSchema.d.ts +0 -23
  440. package/esm/helpers/findGeoColumnFromSchema.d.ts.map +0 -1
  441. package/esm/helpers/findGeoColumnFromSchema.js +0 -31
  442. package/esm/helpers/fitUmapCurve.d.ts +0 -2
  443. package/esm/helpers/fitUmapCurve.d.ts.map +0 -1
  444. package/esm/helpers/fitUmapCurve.js +0 -66
  445. package/esm/helpers/flushAllTables.d.ts +0 -23
  446. package/esm/helpers/flushAllTables.d.ts.map +0 -1
  447. package/esm/helpers/flushAllTables.js +0 -406
  448. package/esm/helpers/foldIdentifier.d.ts +0 -3
  449. package/esm/helpers/foldIdentifier.d.ts.map +0 -1
  450. package/esm/helpers/foldIdentifier.js +0 -4
  451. package/esm/helpers/formatDate.d.ts +0 -40
  452. package/esm/helpers/formatDate.d.ts.map +0 -1
  453. package/esm/helpers/formatDate.js +0 -75
  454. package/esm/helpers/formatMissingTables.d.ts +0 -22
  455. package/esm/helpers/formatMissingTables.d.ts.map +0 -1
  456. package/esm/helpers/formatMissingTables.js +0 -32
  457. package/esm/helpers/formatNumber.d.ts +0 -55
  458. package/esm/helpers/formatNumber.d.ts.map +0 -1
  459. package/esm/helpers/formatNumber.js +0 -137
  460. package/esm/helpers/geometryFromJSON.d.ts +0 -3
  461. package/esm/helpers/geometryFromJSON.d.ts.map +0 -1
  462. package/esm/helpers/geometryFromJSON.js +0 -4
  463. package/esm/helpers/getCombinations.d.ts +0 -3
  464. package/esm/helpers/getCombinations.d.ts.map +0 -1
  465. package/esm/helpers/getCombinations.js +0 -24
  466. package/esm/helpers/getCurrentDatabase.d.ts +0 -3
  467. package/esm/helpers/getCurrentDatabase.d.ts.map +0 -1
  468. package/esm/helpers/getCurrentDatabase.js +0 -7
  469. package/esm/helpers/getDbFileType.d.ts +0 -2
  470. package/esm/helpers/getDbFileType.d.ts.map +0 -1
  471. package/esm/helpers/getDbFileType.js +0 -9
  472. package/esm/helpers/getDbIndexes.d.ts +0 -4
  473. package/esm/helpers/getDbIndexes.d.ts.map +0 -1
  474. package/esm/helpers/getDbIndexes.js +0 -4
  475. package/esm/helpers/getExtension.d.ts +0 -2
  476. package/esm/helpers/getExtension.d.ts.map +0 -1
  477. package/esm/helpers/getExtension.js +0 -9
  478. package/esm/helpers/getGraphEdgeIdColumn.d.ts +0 -9
  479. package/esm/helpers/getGraphEdgeIdColumn.d.ts.map +0 -1
  480. package/esm/helpers/getGraphEdgeIdColumn.js +0 -25
  481. package/esm/helpers/getGraphEndpointColumns.d.ts +0 -11
  482. package/esm/helpers/getGraphEndpointColumns.d.ts.map +0 -1
  483. package/esm/helpers/getGraphEndpointColumns.js +0 -160
  484. package/esm/helpers/getGraphWeightColumn.d.ts +0 -10
  485. package/esm/helpers/getGraphWeightColumn.d.ts.map +0 -1
  486. package/esm/helpers/getGraphWeightColumn.js +0 -40
  487. package/esm/helpers/getIdenticalColumns.d.ts +0 -2
  488. package/esm/helpers/getIdenticalColumns.d.ts.map +0 -1
  489. package/esm/helpers/getIdenticalColumns.js +0 -3
  490. package/esm/helpers/getStatExpression.d.ts +0 -10
  491. package/esm/helpers/getStatExpression.d.ts.map +0 -1
  492. package/esm/helpers/getStatExpression.js +0 -75
  493. package/esm/helpers/graphRouteResultSchema.d.ts +0 -4
  494. package/esm/helpers/graphRouteResultSchema.d.ts.map +0 -1
  495. package/esm/helpers/graphRouteResultSchema.js +0 -13
  496. package/esm/helpers/graphRouteResultSelect.d.ts +0 -4
  497. package/esm/helpers/graphRouteResultSelect.d.ts.map +0 -1
  498. package/esm/helpers/graphRouteResultSelect.js +0 -25
  499. package/esm/helpers/hasGeometryColumn.d.ts +0 -21
  500. package/esm/helpers/hasGeometryColumn.d.ts.map +0 -1
  501. package/esm/helpers/hasGeometryColumn.js +0 -22
  502. package/esm/helpers/index.d.ts +0 -24
  503. package/esm/helpers/index.d.ts.map +0 -1
  504. package/esm/helpers/index.js +0 -23
  505. package/esm/helpers/indexDefinitions.d.ts +0 -30
  506. package/esm/helpers/indexDefinitions.d.ts.map +0 -1
  507. package/esm/helpers/indexDefinitions.js +0 -7
  508. package/esm/helpers/indexQueries.d.ts +0 -3
  509. package/esm/helpers/indexQueries.d.ts.map +0 -1
  510. package/esm/helpers/indexQueries.js +0 -36
  511. package/esm/helpers/initialUmapCoordinates.d.ts +0 -2
  512. package/esm/helpers/initialUmapCoordinates.d.ts.map +0 -1
  513. package/esm/helpers/initialUmapCoordinates.js +0 -5
  514. package/esm/helpers/inspectGraphConnectivity.d.ts +0 -10
  515. package/esm/helpers/inspectGraphConnectivity.d.ts.map +0 -1
  516. package/esm/helpers/inspectGraphConnectivity.js +0 -55
  517. package/esm/helpers/keepNumericalColumns.d.ts +0 -4
  518. package/esm/helpers/keepNumericalColumns.d.ts.map +0 -1
  519. package/esm/helpers/keepNumericalColumns.js +0 -12
  520. package/esm/helpers/loadOsmFile.d.ts +0 -8
  521. package/esm/helpers/loadOsmFile.d.ts.map +0 -1
  522. package/esm/helpers/loadOsmFile.js +0 -20
  523. package/esm/helpers/logData.d.ts +0 -6
  524. package/esm/helpers/logData.d.ts.map +0 -1
  525. package/esm/helpers/logData.js +0 -54
  526. package/esm/helpers/makeLogConverter.d.ts +0 -5
  527. package/esm/helpers/makeLogConverter.d.ts.map +0 -1
  528. package/esm/helpers/makeLogConverter.js +0 -64
  529. package/esm/helpers/mergeOptions.d.ts +0 -71
  530. package/esm/helpers/mergeOptions.d.ts.map +0 -1
  531. package/esm/helpers/mergeOptions.js +0 -53
  532. package/esm/helpers/normalizeCacheCode.d.ts +0 -8
  533. package/esm/helpers/normalizeCacheCode.d.ts.map +0 -1
  534. package/esm/helpers/normalizeCacheCode.js +0 -331
  535. package/esm/helpers/observeQuery.d.ts +0 -9
  536. package/esm/helpers/observeQuery.d.ts.map +0 -1
  537. package/esm/helpers/observeQuery.js +0 -49
  538. package/esm/helpers/optimizeUmapLayout.d.ts +0 -7
  539. package/esm/helpers/optimizeUmapLayout.d.ts.map +0 -1
  540. package/esm/helpers/optimizeUmapLayout.js +0 -93
  541. package/esm/helpers/osmCache.d.ts +0 -13
  542. package/esm/helpers/osmCache.d.ts.map +0 -1
  543. package/esm/helpers/osmCache.js +0 -186
  544. package/esm/helpers/osmFiles.d.ts +0 -18
  545. package/esm/helpers/osmFiles.d.ts.map +0 -1
  546. package/esm/helpers/osmFiles.js +0 -263
  547. package/esm/helpers/parseDuckDBType.d.ts +0 -2
  548. package/esm/helpers/parseDuckDBType.d.ts.map +0 -1
  549. package/esm/helpers/parseDuckDBType.js +0 -38
  550. package/esm/helpers/parseTypes.d.ts +0 -2
  551. package/esm/helpers/parseTypes.d.ts.map +0 -1
  552. package/esm/helpers/parseTypes.js +0 -41
  553. package/esm/helpers/parseValue.d.ts +0 -20
  554. package/esm/helpers/parseValue.d.ts.map +0 -1
  555. package/esm/helpers/parseValue.js +0 -38
  556. package/esm/helpers/pendingOps.d.ts +0 -153
  557. package/esm/helpers/pendingOps.d.ts.map +0 -1
  558. package/esm/helpers/pendingOps.js +0 -1
  559. package/esm/helpers/prepareDbExtensions.d.ts +0 -4
  560. package/esm/helpers/prepareDbExtensions.d.ts.map +0 -1
  561. package/esm/helpers/prepareDbExtensions.js +0 -22
  562. package/esm/helpers/prepareGeometry.d.ts +0 -3
  563. package/esm/helpers/prepareGeometry.d.ts.map +0 -1
  564. package/esm/helpers/prepareGeometry.js +0 -99
  565. package/esm/helpers/prepareGraphMetricOptions.d.ts +0 -14
  566. package/esm/helpers/prepareGraphMetricOptions.d.ts.map +0 -1
  567. package/esm/helpers/prepareGraphMetricOptions.js +0 -41
  568. package/esm/helpers/prepareGraphRouteSql.d.ts +0 -31
  569. package/esm/helpers/prepareGraphRouteSql.d.ts.map +0 -1
  570. package/esm/helpers/prepareGraphRouteSql.js +0 -86
  571. package/esm/helpers/prepareGraphStarts.d.ts +0 -9
  572. package/esm/helpers/prepareGraphStarts.d.ts.map +0 -1
  573. package/esm/helpers/prepareGraphStarts.js +0 -68
  574. package/esm/helpers/prepareGraphTemporalSql.d.ts +0 -31
  575. package/esm/helpers/prepareGraphTemporalSql.d.ts.map +0 -1
  576. package/esm/helpers/prepareGraphTemporalSql.js +0 -161
  577. package/esm/helpers/prepareGraphTraversal.d.ts +0 -19
  578. package/esm/helpers/prepareGraphTraversal.d.ts.map +0 -1
  579. package/esm/helpers/prepareGraphTraversal.js +0 -79
  580. package/esm/helpers/prepareJSON.d.ts +0 -3
  581. package/esm/helpers/prepareJSON.d.ts.map +0 -1
  582. package/esm/helpers/prepareJSON.js +0 -50
  583. package/esm/helpers/prepareNumericFeatures.d.ts +0 -41
  584. package/esm/helpers/prepareNumericFeatures.d.ts.map +0 -1
  585. package/esm/helpers/prepareNumericFeatures.js +0 -210
  586. package/esm/helpers/prepareUmapLayoutOptions.d.ts +0 -14
  587. package/esm/helpers/prepareUmapLayoutOptions.d.ts.map +0 -1
  588. package/esm/helpers/prepareUmapLayoutOptions.js +0 -23
  589. package/esm/helpers/prepareValueFilters.d.ts +0 -11
  590. package/esm/helpers/prepareValueFilters.d.ts.map +0 -1
  591. package/esm/helpers/prepareValueFilters.js +0 -12
  592. package/esm/helpers/prettyDuration.d.ts +0 -61
  593. package/esm/helpers/prettyDuration.d.ts.map +0 -1
  594. package/esm/helpers/prettyDuration.js +0 -151
  595. package/esm/helpers/printTable.d.ts +0 -55
  596. package/esm/helpers/printTable.d.ts.map +0 -1
  597. package/esm/helpers/printTable.js +0 -224
  598. package/esm/helpers/publishPreparedColumns.d.ts +0 -37
  599. package/esm/helpers/publishPreparedColumns.d.ts.map +0 -1
  600. package/esm/helpers/publishPreparedColumns.js +0 -97
  601. package/esm/helpers/queryDB.d.ts +0 -65
  602. package/esm/helpers/queryDB.d.ts.map +0 -1
  603. package/esm/helpers/queryDB.js +0 -92
  604. package/esm/helpers/queryDbFile.d.ts +0 -8
  605. package/esm/helpers/queryDbFile.d.ts.map +0 -1
  606. package/esm/helpers/queryDbFile.js +0 -12
  607. package/esm/helpers/queueAsyncBarrier.d.ts +0 -56
  608. package/esm/helpers/queueAsyncBarrier.d.ts.map +0 -1
  609. package/esm/helpers/queueAsyncBarrier.js +0 -54
  610. package/esm/helpers/queueGraphResult.d.ts +0 -18
  611. package/esm/helpers/queueGraphResult.d.ts.map +0 -1
  612. package/esm/helpers/queueGraphResult.js +0 -39
  613. package/esm/helpers/queueOp.d.ts +0 -18
  614. package/esm/helpers/queueOp.d.ts.map +0 -1
  615. package/esm/helpers/queueOp.js +0 -72
  616. package/esm/helpers/quoteIdentifier.d.ts +0 -17
  617. package/esm/helpers/quoteIdentifier.d.ts.map +0 -1
  618. package/esm/helpers/quoteIdentifier.js +0 -18
  619. package/esm/helpers/quoteQualifiedIdentifier.d.ts +0 -20
  620. package/esm/helpers/quoteQualifiedIdentifier.d.ts.map +0 -1
  621. package/esm/helpers/quoteQualifiedIdentifier.js +0 -22
  622. package/esm/helpers/readDbMetadata.d.ts +0 -5
  623. package/esm/helpers/readDbMetadata.d.ts.map +0 -1
  624. package/esm/helpers/readDbMetadata.js +0 -55
  625. package/esm/helpers/readMutationRows.d.ts +0 -9
  626. package/esm/helpers/readMutationRows.d.ts.map +0 -1
  627. package/esm/helpers/readMutationRows.js +0 -94
  628. package/esm/helpers/readScalarNumber.d.ts +0 -3
  629. package/esm/helpers/readScalarNumber.d.ts.map +0 -1
  630. package/esm/helpers/readScalarNumber.js +0 -4
  631. package/esm/helpers/referencedTables.d.ts +0 -9
  632. package/esm/helpers/referencedTables.d.ts.map +0 -1
  633. package/esm/helpers/referencedTables.js +0 -22
  634. package/esm/helpers/removeColumnsNow.d.ts +0 -8
  635. package/esm/helpers/removeColumnsNow.d.ts.map +0 -1
  636. package/esm/helpers/removeColumnsNow.js +0 -15
  637. package/esm/helpers/resolveOutputTable.d.ts +0 -9
  638. package/esm/helpers/resolveOutputTable.d.ts.map +0 -1
  639. package/esm/helpers/resolveOutputTable.js +0 -14
  640. package/esm/helpers/rewind.d.ts +0 -3
  641. package/esm/helpers/rewind.d.ts.map +0 -1
  642. package/esm/helpers/rewind.js +0 -1293
  643. package/esm/helpers/runQuery.d.ts +0 -17
  644. package/esm/helpers/runQuery.d.ts.map +0 -1
  645. package/esm/helpers/runQuery.js +0 -141
  646. package/esm/helpers/scanSQL.d.ts +0 -7
  647. package/esm/helpers/scanSQL.d.ts.map +0 -1
  648. package/esm/helpers/scanSQL.js +0 -71
  649. package/esm/helpers/selectFuzzyReplacements.d.ts +0 -11
  650. package/esm/helpers/selectFuzzyReplacements.d.ts.map +0 -1
  651. package/esm/helpers/selectFuzzyReplacements.js +0 -124
  652. package/esm/helpers/serializeCacheInputs.d.ts +0 -8
  653. package/esm/helpers/serializeCacheInputs.d.ts.map +0 -1
  654. package/esm/helpers/serializeCacheInputs.js +0 -114
  655. package/esm/helpers/setDbProps.d.ts +0 -6
  656. package/esm/helpers/setDbProps.d.ts.map +0 -1
  657. package/esm/helpers/setDbProps.js +0 -23
  658. package/esm/helpers/splitGraphemes.d.ts +0 -2
  659. package/esm/helpers/splitGraphemes.d.ts.map +0 -1
  660. package/esm/helpers/splitGraphemes.js +0 -6
  661. package/esm/helpers/stabilizeCosineVectors.d.ts +0 -14
  662. package/esm/helpers/stabilizeCosineVectors.d.ts.map +0 -1
  663. package/esm/helpers/stabilizeCosineVectors.js +0 -34
  664. package/esm/helpers/statCanCache.d.ts +0 -6
  665. package/esm/helpers/statCanCache.d.ts.map +0 -1
  666. package/esm/helpers/statCanCache.js +0 -38
  667. package/esm/helpers/stringToArray.d.ts +0 -17
  668. package/esm/helpers/stringToArray.d.ts.map +0 -1
  669. package/esm/helpers/stringToArray.js +0 -26
  670. package/esm/helpers/stringifyDates.d.ts +0 -5
  671. package/esm/helpers/stringifyDates.d.ts.map +0 -1
  672. package/esm/helpers/stringifyDates.js +0 -14
  673. package/esm/helpers/stringifyDatesInvert.d.ts +0 -5
  674. package/esm/helpers/stringifyDatesInvert.d.ts.map +0 -1
  675. package/esm/helpers/stringifyDatesInvert.js +0 -14
  676. package/esm/helpers/tableGeneration.d.ts +0 -18
  677. package/esm/helpers/tableGeneration.d.ts.map +0 -1
  678. package/esm/helpers/tableGeneration.js +0 -29
  679. package/esm/helpers/tableRegistry.d.ts +0 -11
  680. package/esm/helpers/tableRegistry.d.ts.map +0 -1
  681. package/esm/helpers/tableRegistry.js +0 -54
  682. package/esm/helpers/toDuckDBValue.d.ts +0 -4
  683. package/esm/helpers/toDuckDBValue.d.ts.map +0 -1
  684. package/esm/helpers/toDuckDBValue.js +0 -15
  685. package/esm/helpers/umapRandom.d.ts +0 -2
  686. package/esm/helpers/umapRandom.d.ts.map +0 -1
  687. package/esm/helpers/umapRandom.js +0 -10
  688. package/esm/helpers/unifyColumns.d.ts +0 -12
  689. package/esm/helpers/unifyColumns.d.ts.map +0 -1
  690. package/esm/helpers/unifyColumns.js +0 -33
  691. package/esm/helpers/updateColumnsWithJS.d.ts +0 -58
  692. package/esm/helpers/updateColumnsWithJS.d.ts.map +0 -1
  693. package/esm/helpers/updateColumnsWithJS.js +0 -147
  694. package/esm/helpers/validateGraphRouteResultSchema.d.ts +0 -4
  695. package/esm/helpers/validateGraphRouteResultSchema.d.ts.map +0 -1
  696. package/esm/helpers/validateGraphRouteResultSchema.js +0 -15
  697. package/esm/helpers/validateGraphTemporalEvents.d.ts +0 -7
  698. package/esm/helpers/validateGraphTemporalEvents.d.ts.map +0 -1
  699. package/esm/helpers/validateGraphTemporalEvents.js +0 -47
  700. package/esm/helpers/validateNumericalAnalysis.d.ts +0 -29
  701. package/esm/helpers/validateNumericalAnalysis.d.ts.map +0 -1
  702. package/esm/helpers/validateNumericalAnalysis.js +0 -53
  703. package/esm/helpers/validateVectorRowIds.d.ts +0 -4
  704. package/esm/helpers/validateVectorRowIds.d.ts.map +0 -1
  705. package/esm/helpers/validateVectorRowIds.js +0 -16
  706. package/esm/helpers/vectorDistanceExpression.d.ts +0 -6
  707. package/esm/helpers/vectorDistanceExpression.d.ts.map +0 -1
  708. package/esm/helpers/vectorDistanceExpression.js +0 -11
  709. package/esm/helpers/wrapString.d.ts +0 -40
  710. package/esm/helpers/wrapString.d.ts.map +0 -1
  711. package/esm/helpers/wrapString.js +0 -97
  712. package/esm/helpers/writeDataAsArrays.d.ts +0 -3
  713. package/esm/helpers/writeDataAsArrays.d.ts.map +0 -1
  714. package/esm/helpers/writeDataAsArrays.js +0 -13
  715. package/esm/helpers/writeDbMetadata.d.ts +0 -4
  716. package/esm/helpers/writeDbMetadata.d.ts.map +0 -1
  717. package/esm/helpers/writeDbMetadata.js +0 -9
  718. package/esm/helpers/writeGeoData.d.ts +0 -9
  719. package/esm/helpers/writeGeoData.d.ts.map +0 -1
  720. package/esm/helpers/writeGeoData.js +0 -167
  721. package/esm/helpers/writeZip.d.ts +0 -15
  722. package/esm/helpers/writeZip.d.ts.map +0 -1
  723. package/esm/helpers/writeZip.js +0 -257
  724. package/esm/index.d.ts +0 -35
  725. package/esm/index.d.ts.map +0 -1
  726. package/esm/index.js +0 -34
  727. package/esm/methods/accumulate.d.ts +0 -5
  728. package/esm/methods/accumulate.d.ts.map +0 -1
  729. package/esm/methods/accumulate.js +0 -37
  730. package/esm/methods/addBoundingBox.d.ts +0 -6
  731. package/esm/methods/addBoundingBox.d.ts.map +0 -1
  732. package/esm/methods/addBoundingBox.js +0 -26
  733. package/esm/methods/addCharacterCount.d.ts +0 -3
  734. package/esm/methods/addCharacterCount.d.ts.map +0 -1
  735. package/esm/methods/addCharacterCount.js +0 -15
  736. package/esm/methods/addColumn.d.ts +0 -3
  737. package/esm/methods/addColumn.d.ts.map +0 -1
  738. package/esm/methods/addColumn.js +0 -24
  739. package/esm/methods/addGeoClosedStatus.d.ts +0 -5
  740. package/esm/methods/addGeoClosedStatus.d.ts.map +0 -1
  741. package/esm/methods/addGeoClosedStatus.js +0 -21
  742. package/esm/methods/addGeoNoise.d.ts +0 -7
  743. package/esm/methods/addGeoNoise.d.ts.map +0 -1
  744. package/esm/methods/addGeoNoise.js +0 -135
  745. package/esm/methods/addGeoType.d.ts +0 -5
  746. package/esm/methods/addGeoType.d.ts.map +0 -1
  747. package/esm/methods/addGeoType.js +0 -21
  748. package/esm/methods/addGeoValidity.d.ts +0 -5
  749. package/esm/methods/addGeoValidity.d.ts.map +0 -1
  750. package/esm/methods/addGeoValidity.js +0 -21
  751. package/esm/methods/addId.d.ts +0 -5
  752. package/esm/methods/addId.d.ts.map +0 -1
  753. package/esm/methods/addId.js +0 -38
  754. package/esm/methods/addNoise.d.ts +0 -5
  755. package/esm/methods/addNoise.d.ts.map +0 -1
  756. package/esm/methods/addNoise.js +0 -53
  757. package/esm/methods/addRowNumber.d.ts +0 -5
  758. package/esm/methods/addRowNumber.d.ts.map +0 -1
  759. package/esm/methods/addRowNumber.js +0 -26
  760. package/esm/methods/addSummaryRows.d.ts +0 -14
  761. package/esm/methods/addSummaryRows.d.ts.map +0 -1
  762. package/esm/methods/addSummaryRows.js +0 -122
  763. package/esm/methods/addVertexCount.d.ts +0 -5
  764. package/esm/methods/addVertexCount.d.ts.map +0 -1
  765. package/esm/methods/addVertexCount.js +0 -21
  766. package/esm/methods/addWordCount.d.ts +0 -3
  767. package/esm/methods/addWordCount.d.ts.map +0 -1
  768. package/esm/methods/addWordCount.js +0 -15
  769. package/esm/methods/aggregateGeo.d.ts +0 -7
  770. package/esm/methods/aggregateGeo.d.ts.map +0 -1
  771. package/esm/methods/aggregateGeo.js +0 -69
  772. package/esm/methods/area.d.ts +0 -7
  773. package/esm/methods/area.d.ts.map +0 -1
  774. package/esm/methods/area.js +0 -25
  775. package/esm/methods/bins.d.ts +0 -5
  776. package/esm/methods/bins.d.ts.map +0 -1
  777. package/esm/methods/bins.js +0 -103
  778. package/esm/methods/bm25.d.ts +0 -17
  779. package/esm/methods/bm25.d.ts.map +0 -1
  780. package/esm/methods/bm25.js +0 -62
  781. package/esm/methods/buffer.d.ts +0 -5
  782. package/esm/methods/buffer.d.ts.map +0 -1
  783. package/esm/methods/buffer.js +0 -24
  784. package/esm/methods/cache.d.ts +0 -7
  785. package/esm/methods/cache.d.ts.map +0 -1
  786. package/esm/methods/cache.js +0 -289
  787. package/esm/methods/capitalize.d.ts +0 -3
  788. package/esm/methods/capitalize.d.ts.map +0 -1
  789. package/esm/methods/capitalize.js +0 -15
  790. package/esm/methods/centroid.d.ts +0 -5
  791. package/esm/methods/centroid.d.ts.map +0 -1
  792. package/esm/methods/centroid.js +0 -24
  793. package/esm/methods/clone.d.ts +0 -9
  794. package/esm/methods/clone.d.ts.map +0 -1
  795. package/esm/methods/clone.js +0 -35
  796. package/esm/methods/cloneColumn.d.ts +0 -3
  797. package/esm/methods/cloneColumn.d.ts.map +0 -1
  798. package/esm/methods/cloneColumn.js +0 -18
  799. package/esm/methods/cloneColumnWithOffset.d.ts +0 -6
  800. package/esm/methods/cloneColumnWithOffset.d.ts.map +0 -1
  801. package/esm/methods/cloneColumnWithOffset.js +0 -35
  802. package/esm/methods/columnProportions.d.ts +0 -7
  803. package/esm/methods/columnProportions.d.ts.map +0 -1
  804. package/esm/methods/columnProportions.js +0 -28
  805. package/esm/methods/commonNeighbors.d.ts +0 -10
  806. package/esm/methods/commonNeighbors.d.ts.map +0 -1
  807. package/esm/methods/commonNeighbors.js +0 -101
  808. package/esm/methods/concatenate.d.ts +0 -5
  809. package/esm/methods/concatenate.d.ts.map +0 -1
  810. package/esm/methods/concatenate.js +0 -25
  811. package/esm/methods/connectedComponents.d.ts +0 -9
  812. package/esm/methods/connectedComponents.d.ts.map +0 -1
  813. package/esm/methods/connectedComponents.js +0 -147
  814. package/esm/methods/convert.d.ts +0 -13
  815. package/esm/methods/convert.d.ts.map +0 -1
  816. package/esm/methods/convert.js +0 -117
  817. package/esm/methods/correlations.d.ts +0 -9
  818. package/esm/methods/correlations.d.ts.map +0 -1
  819. package/esm/methods/correlations.js +0 -86
  820. package/esm/methods/coveredBy.d.ts +0 -3
  821. package/esm/methods/coveredBy.d.ts.map +0 -1
  822. package/esm/methods/coveredBy.js +0 -16
  823. package/esm/methods/createFtsIndex.d.ts +0 -24
  824. package/esm/methods/createFtsIndex.d.ts.map +0 -1
  825. package/esm/methods/createFtsIndex.js +0 -67
  826. package/esm/methods/createPoints.d.ts +0 -5
  827. package/esm/methods/createPoints.d.ts.map +0 -1
  828. package/esm/methods/createPoints.js +0 -23
  829. package/esm/methods/createVssIndex.d.ts +0 -9
  830. package/esm/methods/createVssIndex.d.ts.map +0 -1
  831. package/esm/methods/createVssIndex.js +0 -59
  832. package/esm/methods/crossJoin.d.ts +0 -5
  833. package/esm/methods/crossJoin.d.ts.map +0 -1
  834. package/esm/methods/crossJoin.js +0 -35
  835. package/esm/methods/degree.d.ts +0 -9
  836. package/esm/methods/degree.d.ts.map +0 -1
  837. package/esm/methods/degree.js +0 -135
  838. package/esm/methods/difference.d.ts +0 -3
  839. package/esm/methods/difference.d.ts.map +0 -1
  840. package/esm/methods/difference.js +0 -19
  841. package/esm/methods/distance.d.ts +0 -7
  842. package/esm/methods/distance.d.ts.map +0 -1
  843. package/esm/methods/distance.js +0 -48
  844. package/esm/methods/distances.d.ts +0 -14
  845. package/esm/methods/distances.d.ts.map +0 -1
  846. package/esm/methods/distances.js +0 -418
  847. package/esm/methods/extractDatePart.d.ts +0 -7
  848. package/esm/methods/extractDatePart.d.ts.map +0 -1
  849. package/esm/methods/extractDatePart.js +0 -38
  850. package/esm/methods/extractLatLon.d.ts +0 -3
  851. package/esm/methods/extractLatLon.d.ts.map +0 -1
  852. package/esm/methods/extractLatLon.js +0 -16
  853. package/esm/methods/fill.d.ts +0 -7
  854. package/esm/methods/fill.d.ts.map +0 -1
  855. package/esm/methods/fill.js +0 -57
  856. package/esm/methods/fillHoles.d.ts +0 -3
  857. package/esm/methods/fillHoles.d.ts.map +0 -1
  858. package/esm/methods/fillHoles.js +0 -19
  859. package/esm/methods/filter.d.ts +0 -3
  860. package/esm/methods/filter.d.ts.map +0 -1
  861. package/esm/methods/filter.js +0 -14
  862. package/esm/methods/findCycles.d.ts +0 -13
  863. package/esm/methods/findCycles.d.ts.map +0 -1
  864. package/esm/methods/findCycles.js +0 -337
  865. package/esm/methods/firstChars.d.ts +0 -3
  866. package/esm/methods/firstChars.d.ts.map +0 -1
  867. package/esm/methods/firstChars.js +0 -11
  868. package/esm/methods/fixGeo.d.ts +0 -3
  869. package/esm/methods/fixGeo.d.ts.map +0 -1
  870. package/esm/methods/fixGeo.js +0 -22
  871. package/esm/methods/flipCoordinates.d.ts +0 -3
  872. package/esm/methods/flipCoordinates.d.ts.map +0 -1
  873. package/esm/methods/flipCoordinates.js +0 -22
  874. package/esm/methods/fuzzyClean.d.ts +0 -7
  875. package/esm/methods/fuzzyClean.d.ts.map +0 -1
  876. package/esm/methods/fuzzyClean.js +0 -94
  877. package/esm/methods/fuzzyJoin.d.ts +0 -8
  878. package/esm/methods/fuzzyJoin.d.ts.map +0 -1
  879. package/esm/methods/fuzzyJoin.js +0 -147
  880. package/esm/methods/getBottom.d.ts +0 -8
  881. package/esm/methods/getBottom.d.ts.map +0 -1
  882. package/esm/methods/getBottom.js +0 -23
  883. package/esm/methods/getBoundingBox.d.ts +0 -3
  884. package/esm/methods/getBoundingBox.d.ts.map +0 -1
  885. package/esm/methods/getBoundingBox.js +0 -19
  886. package/esm/methods/getCharacterCount.d.ts +0 -3
  887. package/esm/methods/getCharacterCount.d.ts.map +0 -1
  888. package/esm/methods/getCharacterCount.js +0 -17
  889. package/esm/methods/getColumns.d.ts +0 -3
  890. package/esm/methods/getColumns.d.ts.map +0 -1
  891. package/esm/methods/getColumns.js +0 -16
  892. package/esm/methods/getData.d.ts +0 -9
  893. package/esm/methods/getData.d.ts.map +0 -1
  894. package/esm/methods/getData.js +0 -23
  895. package/esm/methods/getDescription.d.ts +0 -9
  896. package/esm/methods/getDescription.d.ts.map +0 -1
  897. package/esm/methods/getDescription.js +0 -25
  898. package/esm/methods/getFirstRow.d.ts +0 -7
  899. package/esm/methods/getFirstRow.d.ts.map +0 -1
  900. package/esm/methods/getFirstRow.js +0 -16
  901. package/esm/methods/getGeoData.d.ts +0 -17
  902. package/esm/methods/getGeoData.d.ts.map +0 -1
  903. package/esm/methods/getGeoData.js +0 -34
  904. package/esm/methods/getHash.d.ts +0 -3
  905. package/esm/methods/getHash.d.ts.map +0 -1
  906. package/esm/methods/getHash.js +0 -39
  907. package/esm/methods/getLastRow.d.ts +0 -7
  908. package/esm/methods/getLastRow.d.ts.map +0 -1
  909. package/esm/methods/getLastRow.js +0 -23
  910. package/esm/methods/getMax.d.ts +0 -3
  911. package/esm/methods/getMax.d.ts.map +0 -1
  912. package/esm/methods/getMax.js +0 -18
  913. package/esm/methods/getMean.d.ts +0 -5
  914. package/esm/methods/getMean.d.ts.map +0 -1
  915. package/esm/methods/getMean.js +0 -20
  916. package/esm/methods/getMedian.d.ts +0 -5
  917. package/esm/methods/getMedian.d.ts.map +0 -1
  918. package/esm/methods/getMedian.js +0 -20
  919. package/esm/methods/getMin.d.ts +0 -3
  920. package/esm/methods/getMin.d.ts.map +0 -1
  921. package/esm/methods/getMin.js +0 -18
  922. package/esm/methods/getQuantile.d.ts +0 -5
  923. package/esm/methods/getQuantile.d.ts.map +0 -1
  924. package/esm/methods/getQuantile.js +0 -20
  925. package/esm/methods/getRow.d.ts +0 -7
  926. package/esm/methods/getRow.d.ts.map +0 -1
  927. package/esm/methods/getRow.js +0 -10
  928. package/esm/methods/getRowCount.d.ts +0 -5
  929. package/esm/methods/getRowCount.d.ts.map +0 -1
  930. package/esm/methods/getRowCount.js +0 -16
  931. package/esm/methods/getSchema.d.ts +0 -5
  932. package/esm/methods/getSchema.d.ts.map +0 -1
  933. package/esm/methods/getSchema.js +0 -12
  934. package/esm/methods/getSkew.d.ts +0 -5
  935. package/esm/methods/getSkew.d.ts.map +0 -1
  936. package/esm/methods/getSkew.js +0 -20
  937. package/esm/methods/getStdDev.d.ts +0 -5
  938. package/esm/methods/getStdDev.d.ts.map +0 -1
  939. package/esm/methods/getStdDev.js +0 -20
  940. package/esm/methods/getSum.d.ts +0 -3
  941. package/esm/methods/getSum.d.ts.map +0 -1
  942. package/esm/methods/getSum.js +0 -18
  943. package/esm/methods/getTableNames.d.ts +0 -3
  944. package/esm/methods/getTableNames.d.ts.map +0 -1
  945. package/esm/methods/getTableNames.js +0 -15
  946. package/esm/methods/getTop.d.ts +0 -7
  947. package/esm/methods/getTop.d.ts.map +0 -1
  948. package/esm/methods/getTop.js +0 -15
  949. package/esm/methods/getTypes.d.ts +0 -5
  950. package/esm/methods/getTypes.d.ts.map +0 -1
  951. package/esm/methods/getTypes.js +0 -14
  952. package/esm/methods/getUniques.d.ts +0 -3
  953. package/esm/methods/getUniques.d.ts.map +0 -1
  954. package/esm/methods/getUniques.js +0 -18
  955. package/esm/methods/getValues.d.ts +0 -3
  956. package/esm/methods/getValues.d.ts.map +0 -1
  957. package/esm/methods/getValues.js +0 -17
  958. package/esm/methods/getVariance.d.ts +0 -5
  959. package/esm/methods/getVariance.d.ts.map +0 -1
  960. package/esm/methods/getVariance.js +0 -20
  961. package/esm/methods/hdbscan.d.ts +0 -5
  962. package/esm/methods/hdbscan.d.ts.map +0 -1
  963. package/esm/methods/hdbscan.js +0 -208
  964. package/esm/methods/indexValues.d.ts +0 -27
  965. package/esm/methods/indexValues.d.ts.map +0 -1
  966. package/esm/methods/indexValues.js +0 -281
  967. package/esm/methods/insertRows.d.ts +0 -5
  968. package/esm/methods/insertRows.d.ts.map +0 -1
  969. package/esm/methods/insertRows.js +0 -41
  970. package/esm/methods/insertTables.d.ts +0 -5
  971. package/esm/methods/insertTables.d.ts.map +0 -1
  972. package/esm/methods/insertTables.js +0 -99
  973. package/esm/methods/intersection.d.ts +0 -3
  974. package/esm/methods/intersection.d.ts.map +0 -1
  975. package/esm/methods/intersection.js +0 -19
  976. package/esm/methods/intersects.d.ts +0 -3
  977. package/esm/methods/intersects.d.ts.map +0 -1
  978. package/esm/methods/intersects.js +0 -16
  979. package/esm/methods/join.d.ts +0 -7
  980. package/esm/methods/join.d.ts.map +0 -1
  981. package/esm/methods/join.js +0 -98
  982. package/esm/methods/joinGeo.d.ts +0 -12
  983. package/esm/methods/joinGeo.d.ts.map +0 -1
  984. package/esm/methods/joinGeo.js +0 -137
  985. package/esm/methods/keepValues.d.ts +0 -5
  986. package/esm/methods/keepValues.d.ts.map +0 -1
  987. package/esm/methods/keepValues.js +0 -35
  988. package/esm/methods/lastChars.d.ts +0 -3
  989. package/esm/methods/lastChars.d.ts.map +0 -1
  990. package/esm/methods/lastChars.js +0 -11
  991. package/esm/methods/length.d.ts +0 -7
  992. package/esm/methods/length.d.ts.map +0 -1
  993. package/esm/methods/length.js +0 -25
  994. package/esm/methods/linearRegressions.d.ts +0 -9
  995. package/esm/methods/linearRegressions.d.ts.map +0 -1
  996. package/esm/methods/linearRegressions.js +0 -97
  997. package/esm/methods/linesToPolygons.d.ts +0 -3
  998. package/esm/methods/linesToPolygons.d.ts.map +0 -1
  999. package/esm/methods/linesToPolygons.js +0 -17
  1000. package/esm/methods/loadArray.d.ts +0 -19
  1001. package/esm/methods/loadArray.d.ts.map +0 -1
  1002. package/esm/methods/loadArray.js +0 -245
  1003. package/esm/methods/loadDB.d.ts +0 -3
  1004. package/esm/methods/loadDB.d.ts.map +0 -1
  1005. package/esm/methods/loadDB.js +0 -60
  1006. package/esm/methods/loadData.d.ts +0 -52
  1007. package/esm/methods/loadData.d.ts.map +0 -1
  1008. package/esm/methods/loadData.js +0 -151
  1009. package/esm/methods/loadGeoData.d.ts +0 -9
  1010. package/esm/methods/loadGeoData.d.ts.map +0 -1
  1011. package/esm/methods/loadGeoData.js +0 -69
  1012. package/esm/methods/loadOpenStreetMap.d.ts +0 -24
  1013. package/esm/methods/loadOpenStreetMap.d.ts.map +0 -1
  1014. package/esm/methods/loadOpenStreetMap.js +0 -368
  1015. package/esm/methods/loadSample.d.ts +0 -9
  1016. package/esm/methods/loadSample.d.ts.map +0 -1
  1017. package/esm/methods/loadSample.js +0 -45
  1018. package/esm/methods/loadStatCanData.d.ts +0 -10
  1019. package/esm/methods/loadStatCanData.d.ts.map +0 -1
  1020. package/esm/methods/loadStatCanData.js +0 -130
  1021. package/esm/methods/loadYahooFinanceData.d.ts +0 -10
  1022. package/esm/methods/loadYahooFinanceData.d.ts.map +0 -1
  1023. package/esm/methods/loadYahooFinanceData.js +0 -133
  1024. package/esm/methods/log.d.ts +0 -7
  1025. package/esm/methods/log.d.ts.map +0 -1
  1026. package/esm/methods/log.js +0 -60
  1027. package/esm/methods/logBottom.d.ts +0 -5
  1028. package/esm/methods/logBottom.d.ts.map +0 -1
  1029. package/esm/methods/logBottom.js +0 -9
  1030. package/esm/methods/longer.d.ts +0 -3
  1031. package/esm/methods/longer.d.ts.map +0 -1
  1032. package/esm/methods/longer.js +0 -23
  1033. package/esm/methods/lower.d.ts +0 -3
  1034. package/esm/methods/lower.d.ts.map +0 -1
  1035. package/esm/methods/lower.js +0 -14
  1036. package/esm/methods/neighbors.d.ts +0 -9
  1037. package/esm/methods/neighbors.d.ts.map +0 -1
  1038. package/esm/methods/neighbors.js +0 -81
  1039. package/esm/methods/nest.d.ts +0 -3
  1040. package/esm/methods/nest.d.ts.map +0 -1
  1041. package/esm/methods/nest.js +0 -23
  1042. package/esm/methods/normalize.d.ts +0 -7
  1043. package/esm/methods/normalize.d.ts.map +0 -1
  1044. package/esm/methods/normalize.js +0 -41
  1045. package/esm/methods/normalizeString.d.ts +0 -5
  1046. package/esm/methods/normalizeString.d.ts.map +0 -1
  1047. package/esm/methods/normalizeString.js +0 -23
  1048. package/esm/methods/normalizeVector.d.ts +0 -5
  1049. package/esm/methods/normalizeVector.d.ts.map +0 -1
  1050. package/esm/methods/normalizeVector.js +0 -132
  1051. package/esm/methods/outliersIQR.d.ts +0 -5
  1052. package/esm/methods/outliersIQR.d.ts.map +0 -1
  1053. package/esm/methods/outliersIQR.js +0 -37
  1054. package/esm/methods/pad.d.ts +0 -6
  1055. package/esm/methods/pad.d.ts.map +0 -1
  1056. package/esm/methods/pad.js +0 -55
  1057. package/esm/methods/paths.d.ts +0 -13
  1058. package/esm/methods/paths.d.ts.map +0 -1
  1059. package/esm/methods/paths.js +0 -294
  1060. package/esm/methods/perimeter.d.ts +0 -7
  1061. package/esm/methods/perimeter.d.ts.map +0 -1
  1062. package/esm/methods/perimeter.js +0 -25
  1063. package/esm/methods/quantiles.d.ts +0 -5
  1064. package/esm/methods/quantiles.d.ts.map +0 -1
  1065. package/esm/methods/quantiles.js +0 -22
  1066. package/esm/methods/randomPoint.d.ts +0 -6
  1067. package/esm/methods/randomPoint.d.ts.map +0 -1
  1068. package/esm/methods/randomPoint.js +0 -105
  1069. package/esm/methods/ranks.d.ts +0 -7
  1070. package/esm/methods/ranks.d.ts.map +0 -1
  1071. package/esm/methods/ranks.js +0 -22
  1072. package/esm/methods/reachable.d.ts +0 -11
  1073. package/esm/methods/reachable.d.ts.map +0 -1
  1074. package/esm/methods/reachable.js +0 -131
  1075. package/esm/methods/reducePrecision.d.ts +0 -5
  1076. package/esm/methods/reducePrecision.d.ts.map +0 -1
  1077. package/esm/methods/reducePrecision.js +0 -24
  1078. package/esm/methods/removeColumns.d.ts +0 -3
  1079. package/esm/methods/removeColumns.d.ts.map +0 -1
  1080. package/esm/methods/removeColumns.js +0 -13
  1081. package/esm/methods/removeDuplicates.d.ts +0 -5
  1082. package/esm/methods/removeDuplicates.d.ts.map +0 -1
  1083. package/esm/methods/removeDuplicates.js +0 -17
  1084. package/esm/methods/removeMissing.d.ts +0 -7
  1085. package/esm/methods/removeMissing.d.ts.map +0 -1
  1086. package/esm/methods/removeMissing.js +0 -80
  1087. package/esm/methods/removeRows.d.ts +0 -3
  1088. package/esm/methods/removeRows.d.ts.map +0 -1
  1089. package/esm/methods/removeRows.js +0 -14
  1090. package/esm/methods/removeTable.d.ts +0 -3
  1091. package/esm/methods/removeTable.d.ts.map +0 -1
  1092. package/esm/methods/removeTable.js +0 -14
  1093. package/esm/methods/removeTables.d.ts +0 -4
  1094. package/esm/methods/removeTables.d.ts.map +0 -1
  1095. package/esm/methods/removeTables.js +0 -28
  1096. package/esm/methods/removeValues.d.ts +0 -5
  1097. package/esm/methods/removeValues.d.ts.map +0 -1
  1098. package/esm/methods/removeValues.js +0 -35
  1099. package/esm/methods/renameColumns.d.ts +0 -7
  1100. package/esm/methods/renameColumns.d.ts.map +0 -1
  1101. package/esm/methods/renameColumns.js +0 -27
  1102. package/esm/methods/renameTable.d.ts +0 -3
  1103. package/esm/methods/renameTable.d.ts.map +0 -1
  1104. package/esm/methods/renameTable.js +0 -16
  1105. package/esm/methods/repeatRows.d.ts +0 -5
  1106. package/esm/methods/repeatRows.d.ts.map +0 -1
  1107. package/esm/methods/repeatRows.js +0 -19
  1108. package/esm/methods/replace.d.ts +0 -8
  1109. package/esm/methods/replace.d.ts.map +0 -1
  1110. package/esm/methods/replace.js +0 -69
  1111. package/esm/methods/replaceNulls.d.ts +0 -3
  1112. package/esm/methods/replaceNulls.d.ts.map +0 -1
  1113. package/esm/methods/replaceNulls.js +0 -36
  1114. package/esm/methods/reproject.d.ts +0 -5
  1115. package/esm/methods/reproject.d.ts.map +0 -1
  1116. package/esm/methods/reproject.js +0 -21
  1117. package/esm/methods/rolling.d.ts +0 -6
  1118. package/esm/methods/rolling.d.ts.map +0 -1
  1119. package/esm/methods/rolling.js +0 -42
  1120. package/esm/methods/round.d.ts +0 -6
  1121. package/esm/methods/round.d.ts.map +0 -1
  1122. package/esm/methods/round.js +0 -22
  1123. package/esm/methods/rowProportions.d.ts +0 -7
  1124. package/esm/methods/rowProportions.d.ts.map +0 -1
  1125. package/esm/methods/rowProportions.js +0 -34
  1126. package/esm/methods/rowRanks.d.ts +0 -9
  1127. package/esm/methods/rowRanks.d.ts.map +0 -1
  1128. package/esm/methods/rowRanks.js +0 -113
  1129. package/esm/methods/rowToText.d.ts +0 -3
  1130. package/esm/methods/rowToText.d.ts.map +0 -1
  1131. package/esm/methods/rowToText.js +0 -27
  1132. package/esm/methods/rowToVector.d.ts +0 -5
  1133. package/esm/methods/rowToVector.d.ts.map +0 -1
  1134. package/esm/methods/rowToVector.js +0 -77
  1135. package/esm/methods/sample.d.ts +0 -5
  1136. package/esm/methods/sample.d.ts.map +0 -1
  1137. package/esm/methods/sample.js +0 -16
  1138. package/esm/methods/selectColumns.d.ts +0 -3
  1139. package/esm/methods/selectColumns.d.ts.map +0 -1
  1140. package/esm/methods/selectColumns.js +0 -19
  1141. package/esm/methods/selectRows.d.ts +0 -6
  1142. package/esm/methods/selectRows.d.ts.map +0 -1
  1143. package/esm/methods/selectRows.js +0 -34
  1144. package/esm/methods/selectTables.d.ts +0 -4
  1145. package/esm/methods/selectTables.d.ts.map +0 -1
  1146. package/esm/methods/selectTables.js +0 -31
  1147. package/esm/methods/setTypes.d.ts +0 -5
  1148. package/esm/methods/setTypes.d.ts.map +0 -1
  1149. package/esm/methods/setTypes.js +0 -30
  1150. package/esm/methods/shortestPath.d.ts +0 -14
  1151. package/esm/methods/shortestPath.d.ts.map +0 -1
  1152. package/esm/methods/shortestPath.js +0 -458
  1153. package/esm/methods/similarityMahalanobis.d.ts +0 -7
  1154. package/esm/methods/similarityMahalanobis.d.ts.map +0 -1
  1155. package/esm/methods/similarityMahalanobis.js +0 -114
  1156. package/esm/methods/simplify.d.ts +0 -6
  1157. package/esm/methods/simplify.d.ts.map +0 -1
  1158. package/esm/methods/simplify.js +0 -38
  1159. package/esm/methods/skip.d.ts +0 -3
  1160. package/esm/methods/skip.d.ts.map +0 -1
  1161. package/esm/methods/skip.js +0 -11
  1162. package/esm/methods/sort.d.ts +0 -9
  1163. package/esm/methods/sort.d.ts.map +0 -1
  1164. package/esm/methods/sort.js +0 -35
  1165. package/esm/methods/splitExtract.d.ts +0 -3
  1166. package/esm/methods/splitExtract.d.ts.map +0 -1
  1167. package/esm/methods/splitExtract.js +0 -21
  1168. package/esm/methods/splitSpread.d.ts +0 -5
  1169. package/esm/methods/splitSpread.d.ts.map +0 -1
  1170. package/esm/methods/splitSpread.js +0 -84
  1171. package/esm/methods/stream.d.ts +0 -8
  1172. package/esm/methods/stream.d.ts.map +0 -1
  1173. package/esm/methods/stream.js +0 -60
  1174. package/esm/methods/summarize.d.ts +0 -15
  1175. package/esm/methods/summarize.d.ts.map +0 -1
  1176. package/esm/methods/summarize.js +0 -147
  1177. package/esm/methods/topologicalSort.d.ts +0 -7
  1178. package/esm/methods/topologicalSort.d.ts.map +0 -1
  1179. package/esm/methods/topologicalSort.js +0 -164
  1180. package/esm/methods/trim.d.ts +0 -6
  1181. package/esm/methods/trim.d.ts.map +0 -1
  1182. package/esm/methods/trim.js +0 -39
  1183. package/esm/methods/truncate.d.ts +0 -3
  1184. package/esm/methods/truncate.d.ts.map +0 -1
  1185. package/esm/methods/truncate.js +0 -11
  1186. package/esm/methods/umap.d.ts +0 -5
  1187. package/esm/methods/umap.d.ts.map +0 -1
  1188. package/esm/methods/umap.js +0 -129
  1189. package/esm/methods/union.d.ts +0 -3
  1190. package/esm/methods/union.d.ts.map +0 -1
  1191. package/esm/methods/union.js +0 -19
  1192. package/esm/methods/unnest.d.ts +0 -3
  1193. package/esm/methods/unnest.d.ts.map +0 -1
  1194. package/esm/methods/unnest.js +0 -15
  1195. package/esm/methods/unnestGeo.d.ts +0 -3
  1196. package/esm/methods/unnestGeo.d.ts.map +0 -1
  1197. package/esm/methods/unnestGeo.js +0 -18
  1198. package/esm/methods/updateColumn.d.ts +0 -3
  1199. package/esm/methods/updateColumn.d.ts.map +0 -1
  1200. package/esm/methods/updateColumn.js +0 -15
  1201. package/esm/methods/updateWithJS.d.ts +0 -9
  1202. package/esm/methods/updateWithJS.d.ts.map +0 -1
  1203. package/esm/methods/updateWithJS.js +0 -188
  1204. package/esm/methods/upper.d.ts +0 -3
  1205. package/esm/methods/upper.d.ts.map +0 -1
  1206. package/esm/methods/upper.js +0 -14
  1207. package/esm/methods/wider.d.ts +0 -5
  1208. package/esm/methods/wider.d.ts.map +0 -1
  1209. package/esm/methods/wider.js +0 -23
  1210. package/esm/methods/writeDB.d.ts +0 -6
  1211. package/esm/methods/writeDB.d.ts.map +0 -1
  1212. package/esm/methods/writeDB.js +0 -99
  1213. package/esm/methods/writeData.d.ts +0 -7
  1214. package/esm/methods/writeData.d.ts.map +0 -1
  1215. package/esm/methods/writeData.js +0 -80
  1216. package/esm/methods/zScore.d.ts +0 -6
  1217. package/esm/methods/zScore.d.ts.map +0 -1
  1218. package/esm/methods/zScore.js +0 -29
  1219. package/esm/package.json +0 -3
  1220. package/script/_dnt.polyfills.d.ts +0 -18
  1221. package/script/_dnt.polyfills.d.ts.map +0 -1
  1222. package/script/_dnt.polyfills.js +0 -16
  1223. package/script/class/SDAError.d.ts +0 -63
  1224. package/script/class/SDAError.d.ts.map +0 -1
  1225. package/script/class/SDAError.js +0 -86
  1226. package/script/class/Simple.d.ts +0 -90
  1227. package/script/class/Simple.d.ts.map +0 -1
  1228. package/script/class/Simple.js +0 -116
  1229. package/script/class/SimpleDB.d.ts +0 -726
  1230. package/script/class/SimpleDB.d.ts.map +0 -1
  1231. package/script/class/SimpleDB.js +0 -1171
  1232. package/script/class/SimpleTable.d.ts +0 -7801
  1233. package/script/class/SimpleTable.d.ts.map +0 -1
  1234. package/script/class/SimpleTable.js +0 -7954
  1235. package/script/helpers/LogValue.d.ts +0 -8
  1236. package/script/helpers/LogValue.d.ts.map +0 -1
  1237. package/script/helpers/LogValue.js +0 -26
  1238. package/script/helpers/appendColumnBatches.d.ts +0 -3
  1239. package/script/helpers/appendColumnBatches.d.ts.map +0 -1
  1240. package/script/helpers/appendColumnBatches.js +0 -24
  1241. package/script/helpers/assertColumnsExist.d.ts +0 -16
  1242. package/script/helpers/assertColumnsExist.d.ts.map +0 -1
  1243. package/script/helpers/assertColumnsExist.js +0 -27
  1244. package/script/helpers/assertNewColumns.d.ts +0 -17
  1245. package/script/helpers/assertNewColumns.d.ts.map +0 -1
  1246. package/script/helpers/assertNewColumns.js +0 -28
  1247. package/script/helpers/assertSameDatabase.d.ts +0 -11
  1248. package/script/helpers/assertSameDatabase.d.ts.map +0 -1
  1249. package/script/helpers/assertSameDatabase.js +0 -16
  1250. package/script/helpers/asyncOperationContext.d.ts +0 -19
  1251. package/script/helpers/asyncOperationContext.d.ts.map +0 -1
  1252. package/script/helpers/asyncOperationContext.js +0 -45
  1253. package/script/helpers/buildApproximateMutualReachabilityMst.d.ts +0 -45
  1254. package/script/helpers/buildApproximateMutualReachabilityMst.d.ts.map +0 -1
  1255. package/script/helpers/buildApproximateMutualReachabilityMst.js +0 -219
  1256. package/script/helpers/buildChronologicalGraphComponentsSql.d.ts +0 -14
  1257. package/script/helpers/buildChronologicalGraphComponentsSql.d.ts.map +0 -1
  1258. package/script/helpers/buildChronologicalGraphComponentsSql.js +0 -174
  1259. package/script/helpers/buildExactMutualReachabilityMst.d.ts +0 -28
  1260. package/script/helpers/buildExactMutualReachabilityMst.d.ts.map +0 -1
  1261. package/script/helpers/buildExactMutualReachabilityMst.js +0 -103
  1262. package/script/helpers/buildFuzzyMatchSql.d.ts +0 -9
  1263. package/script/helpers/buildFuzzyMatchSql.d.ts.map +0 -1
  1264. package/script/helpers/buildFuzzyMatchSql.js +0 -20
  1265. package/script/helpers/buildGraphTemporalCostStateSql.d.ts +0 -12
  1266. package/script/helpers/buildGraphTemporalCostStateSql.d.ts.map +0 -1
  1267. package/script/helpers/buildGraphTemporalCostStateSql.js +0 -106
  1268. package/script/helpers/buildGraphTemporalReachabilitySql.d.ts +0 -13
  1269. package/script/helpers/buildGraphTemporalReachabilitySql.d.ts.map +0 -1
  1270. package/script/helpers/buildGraphTemporalReachabilitySql.js +0 -76
  1271. package/script/helpers/buildSparseMutualReachabilityMst.d.ts +0 -10
  1272. package/script/helpers/buildSparseMutualReachabilityMst.d.ts.map +0 -1
  1273. package/script/helpers/buildSparseMutualReachabilityMst.js +0 -50
  1274. package/script/helpers/buildUmapGraph.d.ts +0 -21
  1275. package/script/helpers/buildUmapGraph.d.ts.map +0 -1
  1276. package/script/helpers/buildUmapGraph.js +0 -67
  1277. package/script/helpers/buildVectorNeighbors.d.ts +0 -45
  1278. package/script/helpers/buildVectorNeighbors.d.ts.map +0 -1
  1279. package/script/helpers/buildVectorNeighbors.js +0 -176
  1280. package/script/helpers/buildWeakGraphComponentsSql.d.ts +0 -3
  1281. package/script/helpers/buildWeakGraphComponentsSql.d.ts.map +0 -1
  1282. package/script/helpers/buildWeakGraphComponentsSql.js +0 -38
  1283. package/script/helpers/cacheDatabase.d.ts +0 -5
  1284. package/script/helpers/cacheDatabase.d.ts.map +0 -1
  1285. package/script/helpers/cacheDatabase.js +0 -118
  1286. package/script/helpers/cacheDiagnostics.d.ts +0 -4
  1287. package/script/helpers/cacheDiagnostics.d.ts.map +0 -1
  1288. package/script/helpers/cacheDiagnostics.js +0 -29
  1289. package/script/helpers/cacheTableDependencies.d.ts +0 -28
  1290. package/script/helpers/cacheTableDependencies.d.ts.map +0 -1
  1291. package/script/helpers/cacheTableDependencies.js +0 -275
  1292. package/script/helpers/camelCase.d.ts +0 -32
  1293. package/script/helpers/camelCase.d.ts.map +0 -1
  1294. package/script/helpers/camelCase.js +0 -53
  1295. package/script/helpers/capitalize.d.ts +0 -30
  1296. package/script/helpers/capitalize.d.ts.map +0 -1
  1297. package/script/helpers/capitalize.js +0 -38
  1298. package/script/helpers/cleanCache.d.ts +0 -3
  1299. package/script/helpers/cleanCache.d.ts.map +0 -1
  1300. package/script/helpers/cleanCache.js +0 -20
  1301. package/script/helpers/cleanPath.d.ts +0 -2
  1302. package/script/helpers/cleanPath.d.ts.map +0 -1
  1303. package/script/helpers/cleanPath.js +0 -6
  1304. package/script/helpers/cleanSQL.d.ts +0 -2
  1305. package/script/helpers/cleanSQL.d.ts.map +0 -1
  1306. package/script/helpers/cleanSQL.js +0 -275
  1307. package/script/helpers/clusterHdbscan.d.ts +0 -18
  1308. package/script/helpers/clusterHdbscan.d.ts.map +0 -1
  1309. package/script/helpers/clusterHdbscan.js +0 -346
  1310. package/script/helpers/computeCovariance.d.ts +0 -16
  1311. package/script/helpers/computeCovariance.d.ts.map +0 -1
  1312. package/script/helpers/computeCovariance.js +0 -105
  1313. package/script/helpers/computeMahalanobisDistances.d.ts +0 -14
  1314. package/script/helpers/computeMahalanobisDistances.d.ts.map +0 -1
  1315. package/script/helpers/computeMahalanobisDistances.js +0 -93
  1316. package/script/helpers/createDirectory.d.ts +0 -16
  1317. package/script/helpers/createDirectory.d.ts.map +0 -1
  1318. package/script/helpers/createDirectory.js +0 -27
  1319. package/script/helpers/csvFormat.d.ts +0 -3
  1320. package/script/helpers/csvFormat.d.ts.map +0 -1
  1321. package/script/helpers/csvFormat.js +0 -168
  1322. package/script/helpers/dataToArrays.d.ts +0 -53
  1323. package/script/helpers/dataToArrays.d.ts.map +0 -1
  1324. package/script/helpers/dataToArrays.js +0 -60
  1325. package/script/helpers/ensureSpatial.d.ts +0 -7
  1326. package/script/helpers/ensureSpatial.d.ts.map +0 -1
  1327. package/script/helpers/ensureSpatial.js +0 -23
  1328. package/script/helpers/extractTypes.d.ts +0 -6
  1329. package/script/helpers/extractTypes.d.ts.map +0 -1
  1330. package/script/helpers/extractTypes.js +0 -9
  1331. package/script/helpers/extractZipEntryToFile.d.ts +0 -3
  1332. package/script/helpers/extractZipEntryToFile.d.ts.map +0 -1
  1333. package/script/helpers/extractZipEntryToFile.js +0 -229
  1334. package/script/helpers/factorCovariance.d.ts +0 -17
  1335. package/script/helpers/factorCovariance.d.ts.map +0 -1
  1336. package/script/helpers/factorCovariance.js +0 -194
  1337. package/script/helpers/fileCache.d.ts +0 -15
  1338. package/script/helpers/fileCache.d.ts.map +0 -1
  1339. package/script/helpers/fileCache.js +0 -135
  1340. package/script/helpers/findGeoColumn.d.ts +0 -17
  1341. package/script/helpers/findGeoColumn.d.ts.map +0 -1
  1342. package/script/helpers/findGeoColumn.js +0 -24
  1343. package/script/helpers/findGeoColumnFromSchema.d.ts +0 -23
  1344. package/script/helpers/findGeoColumnFromSchema.d.ts.map +0 -1
  1345. package/script/helpers/findGeoColumnFromSchema.js +0 -37
  1346. package/script/helpers/fitUmapCurve.d.ts +0 -2
  1347. package/script/helpers/fitUmapCurve.d.ts.map +0 -1
  1348. package/script/helpers/fitUmapCurve.js +0 -69
  1349. package/script/helpers/flushAllTables.d.ts +0 -23
  1350. package/script/helpers/flushAllTables.d.ts.map +0 -1
  1351. package/script/helpers/flushAllTables.js +0 -413
  1352. package/script/helpers/foldIdentifier.d.ts +0 -3
  1353. package/script/helpers/foldIdentifier.d.ts.map +0 -1
  1354. package/script/helpers/foldIdentifier.js +0 -7
  1355. package/script/helpers/formatDate.d.ts +0 -40
  1356. package/script/helpers/formatDate.d.ts.map +0 -1
  1357. package/script/helpers/formatDate.js +0 -78
  1358. package/script/helpers/formatMissingTables.d.ts +0 -22
  1359. package/script/helpers/formatMissingTables.d.ts.map +0 -1
  1360. package/script/helpers/formatMissingTables.js +0 -38
  1361. package/script/helpers/formatNumber.d.ts +0 -55
  1362. package/script/helpers/formatNumber.d.ts.map +0 -1
  1363. package/script/helpers/formatNumber.js +0 -140
  1364. package/script/helpers/geometryFromJSON.d.ts +0 -3
  1365. package/script/helpers/geometryFromJSON.d.ts.map +0 -1
  1366. package/script/helpers/geometryFromJSON.js +0 -7
  1367. package/script/helpers/getCombinations.d.ts +0 -3
  1368. package/script/helpers/getCombinations.d.ts.map +0 -1
  1369. package/script/helpers/getCombinations.js +0 -26
  1370. package/script/helpers/getCurrentDatabase.d.ts +0 -3
  1371. package/script/helpers/getCurrentDatabase.d.ts.map +0 -1
  1372. package/script/helpers/getCurrentDatabase.js +0 -13
  1373. package/script/helpers/getDbFileType.d.ts +0 -2
  1374. package/script/helpers/getDbFileType.d.ts.map +0 -1
  1375. package/script/helpers/getDbFileType.js +0 -12
  1376. package/script/helpers/getDbIndexes.d.ts +0 -4
  1377. package/script/helpers/getDbIndexes.d.ts.map +0 -1
  1378. package/script/helpers/getDbIndexes.js +0 -7
  1379. package/script/helpers/getExtension.d.ts +0 -2
  1380. package/script/helpers/getExtension.d.ts.map +0 -1
  1381. package/script/helpers/getExtension.js +0 -12
  1382. package/script/helpers/getGraphEdgeIdColumn.d.ts +0 -9
  1383. package/script/helpers/getGraphEdgeIdColumn.d.ts.map +0 -1
  1384. package/script/helpers/getGraphEdgeIdColumn.js +0 -31
  1385. package/script/helpers/getGraphEndpointColumns.d.ts +0 -11
  1386. package/script/helpers/getGraphEndpointColumns.d.ts.map +0 -1
  1387. package/script/helpers/getGraphEndpointColumns.js +0 -166
  1388. package/script/helpers/getGraphWeightColumn.d.ts +0 -10
  1389. package/script/helpers/getGraphWeightColumn.d.ts.map +0 -1
  1390. package/script/helpers/getGraphWeightColumn.js +0 -46
  1391. package/script/helpers/getIdenticalColumns.d.ts +0 -2
  1392. package/script/helpers/getIdenticalColumns.d.ts.map +0 -1
  1393. package/script/helpers/getIdenticalColumns.js +0 -6
  1394. package/script/helpers/getStatExpression.d.ts +0 -10
  1395. package/script/helpers/getStatExpression.d.ts.map +0 -1
  1396. package/script/helpers/getStatExpression.js +0 -80
  1397. package/script/helpers/graphRouteResultSchema.d.ts +0 -4
  1398. package/script/helpers/graphRouteResultSchema.d.ts.map +0 -1
  1399. package/script/helpers/graphRouteResultSchema.js +0 -19
  1400. package/script/helpers/graphRouteResultSelect.d.ts +0 -4
  1401. package/script/helpers/graphRouteResultSelect.d.ts.map +0 -1
  1402. package/script/helpers/graphRouteResultSelect.js +0 -31
  1403. package/script/helpers/hasGeometryColumn.d.ts +0 -21
  1404. package/script/helpers/hasGeometryColumn.d.ts.map +0 -1
  1405. package/script/helpers/hasGeometryColumn.js +0 -25
  1406. package/script/helpers/index.d.ts +0 -24
  1407. package/script/helpers/index.d.ts.map +0 -1
  1408. package/script/helpers/index.js +0 -37
  1409. package/script/helpers/indexDefinitions.d.ts +0 -30
  1410. package/script/helpers/indexDefinitions.d.ts.map +0 -1
  1411. package/script/helpers/indexDefinitions.js +0 -10
  1412. package/script/helpers/indexQueries.d.ts +0 -3
  1413. package/script/helpers/indexQueries.d.ts.map +0 -1
  1414. package/script/helpers/indexQueries.js +0 -42
  1415. package/script/helpers/initialUmapCoordinates.d.ts +0 -2
  1416. package/script/helpers/initialUmapCoordinates.d.ts.map +0 -1
  1417. package/script/helpers/initialUmapCoordinates.js +0 -11
  1418. package/script/helpers/inspectGraphConnectivity.d.ts +0 -10
  1419. package/script/helpers/inspectGraphConnectivity.d.ts.map +0 -1
  1420. package/script/helpers/inspectGraphConnectivity.js +0 -58
  1421. package/script/helpers/keepNumericalColumns.d.ts +0 -4
  1422. package/script/helpers/keepNumericalColumns.d.ts.map +0 -1
  1423. package/script/helpers/keepNumericalColumns.js +0 -15
  1424. package/script/helpers/loadOsmFile.d.ts +0 -8
  1425. package/script/helpers/loadOsmFile.d.ts.map +0 -1
  1426. package/script/helpers/loadOsmFile.js +0 -26
  1427. package/script/helpers/logData.d.ts +0 -6
  1428. package/script/helpers/logData.d.ts.map +0 -1
  1429. package/script/helpers/logData.js +0 -60
  1430. package/script/helpers/makeLogConverter.d.ts +0 -5
  1431. package/script/helpers/makeLogConverter.d.ts.map +0 -1
  1432. package/script/helpers/makeLogConverter.js +0 -70
  1433. package/script/helpers/mergeOptions.d.ts +0 -71
  1434. package/script/helpers/mergeOptions.d.ts.map +0 -1
  1435. package/script/helpers/mergeOptions.js +0 -56
  1436. package/script/helpers/normalizeCacheCode.d.ts +0 -8
  1437. package/script/helpers/normalizeCacheCode.d.ts.map +0 -1
  1438. package/script/helpers/normalizeCacheCode.js +0 -334
  1439. package/script/helpers/observeQuery.d.ts +0 -9
  1440. package/script/helpers/observeQuery.d.ts.map +0 -1
  1441. package/script/helpers/observeQuery.js +0 -52
  1442. package/script/helpers/optimizeUmapLayout.d.ts +0 -7
  1443. package/script/helpers/optimizeUmapLayout.d.ts.map +0 -1
  1444. package/script/helpers/optimizeUmapLayout.js +0 -99
  1445. package/script/helpers/osmCache.d.ts +0 -13
  1446. package/script/helpers/osmCache.d.ts.map +0 -1
  1447. package/script/helpers/osmCache.js +0 -193
  1448. package/script/helpers/osmFiles.d.ts +0 -18
  1449. package/script/helpers/osmFiles.d.ts.map +0 -1
  1450. package/script/helpers/osmFiles.js +0 -274
  1451. package/script/helpers/parseDuckDBType.d.ts +0 -2
  1452. package/script/helpers/parseDuckDBType.d.ts.map +0 -1
  1453. package/script/helpers/parseDuckDBType.js +0 -41
  1454. package/script/helpers/parseTypes.d.ts +0 -2
  1455. package/script/helpers/parseTypes.d.ts.map +0 -1
  1456. package/script/helpers/parseTypes.js +0 -44
  1457. package/script/helpers/parseValue.d.ts +0 -20
  1458. package/script/helpers/parseValue.d.ts.map +0 -1
  1459. package/script/helpers/parseValue.js +0 -41
  1460. package/script/helpers/pendingOps.d.ts +0 -153
  1461. package/script/helpers/pendingOps.d.ts.map +0 -1
  1462. package/script/helpers/pendingOps.js +0 -2
  1463. package/script/helpers/prepareDbExtensions.d.ts +0 -4
  1464. package/script/helpers/prepareDbExtensions.d.ts.map +0 -1
  1465. package/script/helpers/prepareDbExtensions.js +0 -28
  1466. package/script/helpers/prepareGeometry.d.ts +0 -3
  1467. package/script/helpers/prepareGeometry.d.ts.map +0 -1
  1468. package/script/helpers/prepareGeometry.js +0 -102
  1469. package/script/helpers/prepareGraphMetricOptions.d.ts +0 -14
  1470. package/script/helpers/prepareGraphMetricOptions.d.ts.map +0 -1
  1471. package/script/helpers/prepareGraphMetricOptions.js +0 -44
  1472. package/script/helpers/prepareGraphRouteSql.d.ts +0 -31
  1473. package/script/helpers/prepareGraphRouteSql.d.ts.map +0 -1
  1474. package/script/helpers/prepareGraphRouteSql.js +0 -127
  1475. package/script/helpers/prepareGraphStarts.d.ts +0 -9
  1476. package/script/helpers/prepareGraphStarts.d.ts.map +0 -1
  1477. package/script/helpers/prepareGraphStarts.js +0 -71
  1478. package/script/helpers/prepareGraphTemporalSql.d.ts +0 -31
  1479. package/script/helpers/prepareGraphTemporalSql.d.ts.map +0 -1
  1480. package/script/helpers/prepareGraphTemporalSql.js +0 -168
  1481. package/script/helpers/prepareGraphTraversal.d.ts +0 -19
  1482. package/script/helpers/prepareGraphTraversal.d.ts.map +0 -1
  1483. package/script/helpers/prepareGraphTraversal.js +0 -87
  1484. package/script/helpers/prepareJSON.d.ts +0 -3
  1485. package/script/helpers/prepareJSON.d.ts.map +0 -1
  1486. package/script/helpers/prepareJSON.js +0 -53
  1487. package/script/helpers/prepareNumericFeatures.d.ts +0 -41
  1488. package/script/helpers/prepareNumericFeatures.d.ts.map +0 -1
  1489. package/script/helpers/prepareNumericFeatures.js +0 -217
  1490. package/script/helpers/prepareUmapLayoutOptions.d.ts +0 -14
  1491. package/script/helpers/prepareUmapLayoutOptions.d.ts.map +0 -1
  1492. package/script/helpers/prepareUmapLayoutOptions.js +0 -29
  1493. package/script/helpers/prepareValueFilters.d.ts +0 -11
  1494. package/script/helpers/prepareValueFilters.d.ts.map +0 -1
  1495. package/script/helpers/prepareValueFilters.js +0 -18
  1496. package/script/helpers/prettyDuration.d.ts +0 -61
  1497. package/script/helpers/prettyDuration.d.ts.map +0 -1
  1498. package/script/helpers/prettyDuration.js +0 -154
  1499. package/script/helpers/printTable.d.ts +0 -55
  1500. package/script/helpers/printTable.d.ts.map +0 -1
  1501. package/script/helpers/printTable.js +0 -230
  1502. package/script/helpers/publishPreparedColumns.d.ts +0 -37
  1503. package/script/helpers/publishPreparedColumns.d.ts.map +0 -1
  1504. package/script/helpers/publishPreparedColumns.js +0 -103
  1505. package/script/helpers/queryDB.d.ts +0 -65
  1506. package/script/helpers/queryDB.d.ts.map +0 -1
  1507. package/script/helpers/queryDB.js +0 -98
  1508. package/script/helpers/queryDbFile.d.ts +0 -8
  1509. package/script/helpers/queryDbFile.d.ts.map +0 -1
  1510. package/script/helpers/queryDbFile.js +0 -18
  1511. package/script/helpers/queueAsyncBarrier.d.ts +0 -56
  1512. package/script/helpers/queueAsyncBarrier.d.ts.map +0 -1
  1513. package/script/helpers/queueAsyncBarrier.js +0 -60
  1514. package/script/helpers/queueGraphResult.d.ts +0 -18
  1515. package/script/helpers/queueGraphResult.d.ts.map +0 -1
  1516. package/script/helpers/queueGraphResult.js +0 -45
  1517. package/script/helpers/queueOp.d.ts +0 -18
  1518. package/script/helpers/queueOp.d.ts.map +0 -1
  1519. package/script/helpers/queueOp.js +0 -76
  1520. package/script/helpers/quoteIdentifier.d.ts +0 -17
  1521. package/script/helpers/quoteIdentifier.d.ts.map +0 -1
  1522. package/script/helpers/quoteIdentifier.js +0 -21
  1523. package/script/helpers/quoteQualifiedIdentifier.d.ts +0 -20
  1524. package/script/helpers/quoteQualifiedIdentifier.d.ts.map +0 -1
  1525. package/script/helpers/quoteQualifiedIdentifier.js +0 -28
  1526. package/script/helpers/readDbMetadata.d.ts +0 -5
  1527. package/script/helpers/readDbMetadata.d.ts.map +0 -1
  1528. package/script/helpers/readDbMetadata.js +0 -61
  1529. package/script/helpers/readMutationRows.d.ts +0 -9
  1530. package/script/helpers/readMutationRows.d.ts.map +0 -1
  1531. package/script/helpers/readMutationRows.js +0 -97
  1532. package/script/helpers/readScalarNumber.d.ts +0 -3
  1533. package/script/helpers/readScalarNumber.d.ts.map +0 -1
  1534. package/script/helpers/readScalarNumber.js +0 -7
  1535. package/script/helpers/referencedTables.d.ts +0 -9
  1536. package/script/helpers/referencedTables.d.ts.map +0 -1
  1537. package/script/helpers/referencedTables.js +0 -28
  1538. package/script/helpers/removeColumnsNow.d.ts +0 -8
  1539. package/script/helpers/removeColumnsNow.d.ts.map +0 -1
  1540. package/script/helpers/removeColumnsNow.js +0 -21
  1541. package/script/helpers/resolveOutputTable.d.ts +0 -9
  1542. package/script/helpers/resolveOutputTable.d.ts.map +0 -1
  1543. package/script/helpers/resolveOutputTable.js +0 -17
  1544. package/script/helpers/rewind.d.ts +0 -3
  1545. package/script/helpers/rewind.d.ts.map +0 -1
  1546. package/script/helpers/rewind.js +0 -1295
  1547. package/script/helpers/runQuery.d.ts +0 -17
  1548. package/script/helpers/runQuery.d.ts.map +0 -1
  1549. package/script/helpers/runQuery.js +0 -148
  1550. package/script/helpers/scanSQL.d.ts +0 -7
  1551. package/script/helpers/scanSQL.d.ts.map +0 -1
  1552. package/script/helpers/scanSQL.js +0 -74
  1553. package/script/helpers/selectFuzzyReplacements.d.ts +0 -11
  1554. package/script/helpers/selectFuzzyReplacements.d.ts.map +0 -1
  1555. package/script/helpers/selectFuzzyReplacements.js +0 -127
  1556. package/script/helpers/serializeCacheInputs.d.ts +0 -8
  1557. package/script/helpers/serializeCacheInputs.d.ts.map +0 -1
  1558. package/script/helpers/serializeCacheInputs.js +0 -121
  1559. package/script/helpers/setDbProps.d.ts +0 -6
  1560. package/script/helpers/setDbProps.d.ts.map +0 -1
  1561. package/script/helpers/setDbProps.js +0 -26
  1562. package/script/helpers/splitGraphemes.d.ts +0 -2
  1563. package/script/helpers/splitGraphemes.d.ts.map +0 -1
  1564. package/script/helpers/splitGraphemes.js +0 -9
  1565. package/script/helpers/stabilizeCosineVectors.d.ts +0 -14
  1566. package/script/helpers/stabilizeCosineVectors.d.ts.map +0 -1
  1567. package/script/helpers/stabilizeCosineVectors.js +0 -40
  1568. package/script/helpers/statCanCache.d.ts +0 -6
  1569. package/script/helpers/statCanCache.d.ts.map +0 -1
  1570. package/script/helpers/statCanCache.js +0 -78
  1571. package/script/helpers/stringToArray.d.ts +0 -17
  1572. package/script/helpers/stringToArray.d.ts.map +0 -1
  1573. package/script/helpers/stringToArray.js +0 -29
  1574. package/script/helpers/stringifyDates.d.ts +0 -5
  1575. package/script/helpers/stringifyDates.d.ts.map +0 -1
  1576. package/script/helpers/stringifyDates.js +0 -17
  1577. package/script/helpers/stringifyDatesInvert.d.ts +0 -5
  1578. package/script/helpers/stringifyDatesInvert.d.ts.map +0 -1
  1579. package/script/helpers/stringifyDatesInvert.js +0 -17
  1580. package/script/helpers/tableGeneration.d.ts +0 -18
  1581. package/script/helpers/tableGeneration.d.ts.map +0 -1
  1582. package/script/helpers/tableGeneration.js +0 -39
  1583. package/script/helpers/tableRegistry.d.ts +0 -11
  1584. package/script/helpers/tableRegistry.d.ts.map +0 -1
  1585. package/script/helpers/tableRegistry.js +0 -66
  1586. package/script/helpers/toDuckDBValue.d.ts +0 -4
  1587. package/script/helpers/toDuckDBValue.d.ts.map +0 -1
  1588. package/script/helpers/toDuckDBValue.js +0 -18
  1589. package/script/helpers/umapRandom.d.ts +0 -2
  1590. package/script/helpers/umapRandom.d.ts.map +0 -1
  1591. package/script/helpers/umapRandom.js +0 -13
  1592. package/script/helpers/unifyColumns.d.ts +0 -12
  1593. package/script/helpers/unifyColumns.d.ts.map +0 -1
  1594. package/script/helpers/unifyColumns.js +0 -39
  1595. package/script/helpers/updateColumnsWithJS.d.ts +0 -58
  1596. package/script/helpers/updateColumnsWithJS.d.ts.map +0 -1
  1597. package/script/helpers/updateColumnsWithJS.js +0 -153
  1598. package/script/helpers/validateGraphRouteResultSchema.d.ts +0 -4
  1599. package/script/helpers/validateGraphRouteResultSchema.d.ts.map +0 -1
  1600. package/script/helpers/validateGraphRouteResultSchema.js +0 -21
  1601. package/script/helpers/validateGraphTemporalEvents.d.ts +0 -7
  1602. package/script/helpers/validateGraphTemporalEvents.d.ts.map +0 -1
  1603. package/script/helpers/validateGraphTemporalEvents.js +0 -53
  1604. package/script/helpers/validateNumericalAnalysis.d.ts +0 -29
  1605. package/script/helpers/validateNumericalAnalysis.d.ts.map +0 -1
  1606. package/script/helpers/validateNumericalAnalysis.js +0 -59
  1607. package/script/helpers/validateVectorRowIds.d.ts +0 -4
  1608. package/script/helpers/validateVectorRowIds.d.ts.map +0 -1
  1609. package/script/helpers/validateVectorRowIds.js +0 -19
  1610. package/script/helpers/vectorDistanceExpression.d.ts +0 -6
  1611. package/script/helpers/vectorDistanceExpression.d.ts.map +0 -1
  1612. package/script/helpers/vectorDistanceExpression.js +0 -14
  1613. package/script/helpers/wrapString.d.ts +0 -40
  1614. package/script/helpers/wrapString.d.ts.map +0 -1
  1615. package/script/helpers/wrapString.js +0 -103
  1616. package/script/helpers/writeDataAsArrays.d.ts +0 -3
  1617. package/script/helpers/writeDataAsArrays.d.ts.map +0 -1
  1618. package/script/helpers/writeDataAsArrays.js +0 -19
  1619. package/script/helpers/writeDbMetadata.d.ts +0 -4
  1620. package/script/helpers/writeDbMetadata.d.ts.map +0 -1
  1621. package/script/helpers/writeDbMetadata.js +0 -15
  1622. package/script/helpers/writeGeoData.d.ts +0 -9
  1623. package/script/helpers/writeGeoData.d.ts.map +0 -1
  1624. package/script/helpers/writeGeoData.js +0 -173
  1625. package/script/helpers/writeZip.d.ts +0 -15
  1626. package/script/helpers/writeZip.d.ts.map +0 -1
  1627. package/script/helpers/writeZip.js +0 -293
  1628. package/script/index.d.ts +0 -35
  1629. package/script/index.d.ts.map +0 -1
  1630. package/script/index.js +0 -43
  1631. package/script/methods/accumulate.d.ts +0 -5
  1632. package/script/methods/accumulate.d.ts.map +0 -1
  1633. package/script/methods/accumulate.js +0 -43
  1634. package/script/methods/addBoundingBox.d.ts +0 -6
  1635. package/script/methods/addBoundingBox.d.ts.map +0 -1
  1636. package/script/methods/addBoundingBox.js +0 -32
  1637. package/script/methods/addCharacterCount.d.ts +0 -3
  1638. package/script/methods/addCharacterCount.d.ts.map +0 -1
  1639. package/script/methods/addCharacterCount.js +0 -21
  1640. package/script/methods/addColumn.d.ts +0 -3
  1641. package/script/methods/addColumn.d.ts.map +0 -1
  1642. package/script/methods/addColumn.js +0 -30
  1643. package/script/methods/addGeoClosedStatus.d.ts +0 -5
  1644. package/script/methods/addGeoClosedStatus.d.ts.map +0 -1
  1645. package/script/methods/addGeoClosedStatus.js +0 -27
  1646. package/script/methods/addGeoNoise.d.ts +0 -7
  1647. package/script/methods/addGeoNoise.d.ts.map +0 -1
  1648. package/script/methods/addGeoNoise.js +0 -141
  1649. package/script/methods/addGeoType.d.ts +0 -5
  1650. package/script/methods/addGeoType.d.ts.map +0 -1
  1651. package/script/methods/addGeoType.js +0 -27
  1652. package/script/methods/addGeoValidity.d.ts +0 -5
  1653. package/script/methods/addGeoValidity.d.ts.map +0 -1
  1654. package/script/methods/addGeoValidity.js +0 -27
  1655. package/script/methods/addId.d.ts +0 -5
  1656. package/script/methods/addId.d.ts.map +0 -1
  1657. package/script/methods/addId.js +0 -44
  1658. package/script/methods/addNoise.d.ts +0 -5
  1659. package/script/methods/addNoise.d.ts.map +0 -1
  1660. package/script/methods/addNoise.js +0 -59
  1661. package/script/methods/addRowNumber.d.ts +0 -5
  1662. package/script/methods/addRowNumber.d.ts.map +0 -1
  1663. package/script/methods/addRowNumber.js +0 -32
  1664. package/script/methods/addSummaryRows.d.ts +0 -14
  1665. package/script/methods/addSummaryRows.d.ts.map +0 -1
  1666. package/script/methods/addSummaryRows.js +0 -161
  1667. package/script/methods/addVertexCount.d.ts +0 -5
  1668. package/script/methods/addVertexCount.d.ts.map +0 -1
  1669. package/script/methods/addVertexCount.js +0 -27
  1670. package/script/methods/addWordCount.d.ts +0 -3
  1671. package/script/methods/addWordCount.d.ts.map +0 -1
  1672. package/script/methods/addWordCount.js +0 -21
  1673. package/script/methods/aggregateGeo.d.ts +0 -7
  1674. package/script/methods/aggregateGeo.d.ts.map +0 -1
  1675. package/script/methods/aggregateGeo.js +0 -75
  1676. package/script/methods/area.d.ts +0 -7
  1677. package/script/methods/area.d.ts.map +0 -1
  1678. package/script/methods/area.js +0 -31
  1679. package/script/methods/bins.d.ts +0 -5
  1680. package/script/methods/bins.d.ts.map +0 -1
  1681. package/script/methods/bins.js +0 -109
  1682. package/script/methods/bm25.d.ts +0 -17
  1683. package/script/methods/bm25.d.ts.map +0 -1
  1684. package/script/methods/bm25.js +0 -68
  1685. package/script/methods/buffer.d.ts +0 -5
  1686. package/script/methods/buffer.d.ts.map +0 -1
  1687. package/script/methods/buffer.js +0 -30
  1688. package/script/methods/cache.d.ts +0 -7
  1689. package/script/methods/cache.d.ts.map +0 -1
  1690. package/script/methods/cache.js +0 -328
  1691. package/script/methods/capitalize.d.ts +0 -3
  1692. package/script/methods/capitalize.d.ts.map +0 -1
  1693. package/script/methods/capitalize.js +0 -21
  1694. package/script/methods/centroid.d.ts +0 -5
  1695. package/script/methods/centroid.d.ts.map +0 -1
  1696. package/script/methods/centroid.js +0 -30
  1697. package/script/methods/clone.d.ts +0 -9
  1698. package/script/methods/clone.d.ts.map +0 -1
  1699. package/script/methods/clone.js +0 -41
  1700. package/script/methods/cloneColumn.d.ts +0 -3
  1701. package/script/methods/cloneColumn.d.ts.map +0 -1
  1702. package/script/methods/cloneColumn.js +0 -24
  1703. package/script/methods/cloneColumnWithOffset.d.ts +0 -6
  1704. package/script/methods/cloneColumnWithOffset.d.ts.map +0 -1
  1705. package/script/methods/cloneColumnWithOffset.js +0 -41
  1706. package/script/methods/columnProportions.d.ts +0 -7
  1707. package/script/methods/columnProportions.d.ts.map +0 -1
  1708. package/script/methods/columnProportions.js +0 -34
  1709. package/script/methods/commonNeighbors.d.ts +0 -10
  1710. package/script/methods/commonNeighbors.d.ts.map +0 -1
  1711. package/script/methods/commonNeighbors.js +0 -140
  1712. package/script/methods/concatenate.d.ts +0 -5
  1713. package/script/methods/concatenate.d.ts.map +0 -1
  1714. package/script/methods/concatenate.js +0 -31
  1715. package/script/methods/connectedComponents.d.ts +0 -9
  1716. package/script/methods/connectedComponents.d.ts.map +0 -1
  1717. package/script/methods/connectedComponents.js +0 -186
  1718. package/script/methods/convert.d.ts +0 -13
  1719. package/script/methods/convert.d.ts.map +0 -1
  1720. package/script/methods/convert.js +0 -124
  1721. package/script/methods/correlations.d.ts +0 -9
  1722. package/script/methods/correlations.d.ts.map +0 -1
  1723. package/script/methods/correlations.js +0 -92
  1724. package/script/methods/coveredBy.d.ts +0 -3
  1725. package/script/methods/coveredBy.d.ts.map +0 -1
  1726. package/script/methods/coveredBy.js +0 -22
  1727. package/script/methods/createFtsIndex.d.ts +0 -24
  1728. package/script/methods/createFtsIndex.d.ts.map +0 -1
  1729. package/script/methods/createFtsIndex.js +0 -74
  1730. package/script/methods/createPoints.d.ts +0 -5
  1731. package/script/methods/createPoints.d.ts.map +0 -1
  1732. package/script/methods/createPoints.js +0 -29
  1733. package/script/methods/createVssIndex.d.ts +0 -9
  1734. package/script/methods/createVssIndex.d.ts.map +0 -1
  1735. package/script/methods/createVssIndex.js +0 -65
  1736. package/script/methods/crossJoin.d.ts +0 -5
  1737. package/script/methods/crossJoin.d.ts.map +0 -1
  1738. package/script/methods/crossJoin.js +0 -41
  1739. package/script/methods/degree.d.ts +0 -9
  1740. package/script/methods/degree.d.ts.map +0 -1
  1741. package/script/methods/degree.js +0 -141
  1742. package/script/methods/difference.d.ts +0 -3
  1743. package/script/methods/difference.d.ts.map +0 -1
  1744. package/script/methods/difference.js +0 -25
  1745. package/script/methods/distance.d.ts +0 -7
  1746. package/script/methods/distance.d.ts.map +0 -1
  1747. package/script/methods/distance.js +0 -54
  1748. package/script/methods/distances.d.ts +0 -14
  1749. package/script/methods/distances.d.ts.map +0 -1
  1750. package/script/methods/distances.js +0 -457
  1751. package/script/methods/extractDatePart.d.ts +0 -7
  1752. package/script/methods/extractDatePart.d.ts.map +0 -1
  1753. package/script/methods/extractDatePart.js +0 -44
  1754. package/script/methods/extractLatLon.d.ts +0 -3
  1755. package/script/methods/extractLatLon.d.ts.map +0 -1
  1756. package/script/methods/extractLatLon.js +0 -22
  1757. package/script/methods/fill.d.ts +0 -7
  1758. package/script/methods/fill.d.ts.map +0 -1
  1759. package/script/methods/fill.js +0 -63
  1760. package/script/methods/fillHoles.d.ts +0 -3
  1761. package/script/methods/fillHoles.d.ts.map +0 -1
  1762. package/script/methods/fillHoles.js +0 -25
  1763. package/script/methods/filter.d.ts +0 -3
  1764. package/script/methods/filter.d.ts.map +0 -1
  1765. package/script/methods/filter.js +0 -20
  1766. package/script/methods/findCycles.d.ts +0 -13
  1767. package/script/methods/findCycles.d.ts.map +0 -1
  1768. package/script/methods/findCycles.js +0 -376
  1769. package/script/methods/firstChars.d.ts +0 -3
  1770. package/script/methods/firstChars.d.ts.map +0 -1
  1771. package/script/methods/firstChars.js +0 -17
  1772. package/script/methods/fixGeo.d.ts +0 -3
  1773. package/script/methods/fixGeo.d.ts.map +0 -1
  1774. package/script/methods/fixGeo.js +0 -28
  1775. package/script/methods/flipCoordinates.d.ts +0 -3
  1776. package/script/methods/flipCoordinates.d.ts.map +0 -1
  1777. package/script/methods/flipCoordinates.js +0 -28
  1778. package/script/methods/fuzzyClean.d.ts +0 -7
  1779. package/script/methods/fuzzyClean.d.ts.map +0 -1
  1780. package/script/methods/fuzzyClean.js +0 -100
  1781. package/script/methods/fuzzyJoin.d.ts +0 -8
  1782. package/script/methods/fuzzyJoin.d.ts.map +0 -1
  1783. package/script/methods/fuzzyJoin.js +0 -153
  1784. package/script/methods/getBottom.d.ts +0 -8
  1785. package/script/methods/getBottom.d.ts.map +0 -1
  1786. package/script/methods/getBottom.js +0 -29
  1787. package/script/methods/getBoundingBox.d.ts +0 -3
  1788. package/script/methods/getBoundingBox.d.ts.map +0 -1
  1789. package/script/methods/getBoundingBox.js +0 -25
  1790. package/script/methods/getCharacterCount.d.ts +0 -3
  1791. package/script/methods/getCharacterCount.d.ts.map +0 -1
  1792. package/script/methods/getCharacterCount.js +0 -23
  1793. package/script/methods/getColumns.d.ts +0 -3
  1794. package/script/methods/getColumns.d.ts.map +0 -1
  1795. package/script/methods/getColumns.js +0 -22
  1796. package/script/methods/getData.d.ts +0 -9
  1797. package/script/methods/getData.d.ts.map +0 -1
  1798. package/script/methods/getData.js +0 -29
  1799. package/script/methods/getDescription.d.ts +0 -9
  1800. package/script/methods/getDescription.d.ts.map +0 -1
  1801. package/script/methods/getDescription.js +0 -28
  1802. package/script/methods/getFirstRow.d.ts +0 -7
  1803. package/script/methods/getFirstRow.d.ts.map +0 -1
  1804. package/script/methods/getFirstRow.js +0 -22
  1805. package/script/methods/getGeoData.d.ts +0 -17
  1806. package/script/methods/getGeoData.d.ts.map +0 -1
  1807. package/script/methods/getGeoData.js +0 -40
  1808. package/script/methods/getHash.d.ts +0 -3
  1809. package/script/methods/getHash.d.ts.map +0 -1
  1810. package/script/methods/getHash.js +0 -45
  1811. package/script/methods/getLastRow.d.ts +0 -7
  1812. package/script/methods/getLastRow.d.ts.map +0 -1
  1813. package/script/methods/getLastRow.js +0 -29
  1814. package/script/methods/getMax.d.ts +0 -3
  1815. package/script/methods/getMax.d.ts.map +0 -1
  1816. package/script/methods/getMax.js +0 -24
  1817. package/script/methods/getMean.d.ts +0 -5
  1818. package/script/methods/getMean.d.ts.map +0 -1
  1819. package/script/methods/getMean.js +0 -26
  1820. package/script/methods/getMedian.d.ts +0 -5
  1821. package/script/methods/getMedian.d.ts.map +0 -1
  1822. package/script/methods/getMedian.js +0 -26
  1823. package/script/methods/getMin.d.ts +0 -3
  1824. package/script/methods/getMin.d.ts.map +0 -1
  1825. package/script/methods/getMin.js +0 -24
  1826. package/script/methods/getQuantile.d.ts +0 -5
  1827. package/script/methods/getQuantile.d.ts.map +0 -1
  1828. package/script/methods/getQuantile.js +0 -26
  1829. package/script/methods/getRow.d.ts +0 -7
  1830. package/script/methods/getRow.d.ts.map +0 -1
  1831. package/script/methods/getRow.js +0 -13
  1832. package/script/methods/getRowCount.d.ts +0 -5
  1833. package/script/methods/getRowCount.d.ts.map +0 -1
  1834. package/script/methods/getRowCount.js +0 -22
  1835. package/script/methods/getSchema.d.ts +0 -5
  1836. package/script/methods/getSchema.d.ts.map +0 -1
  1837. package/script/methods/getSchema.js +0 -18
  1838. package/script/methods/getSkew.d.ts +0 -5
  1839. package/script/methods/getSkew.d.ts.map +0 -1
  1840. package/script/methods/getSkew.js +0 -26
  1841. package/script/methods/getStdDev.d.ts +0 -5
  1842. package/script/methods/getStdDev.d.ts.map +0 -1
  1843. package/script/methods/getStdDev.js +0 -26
  1844. package/script/methods/getSum.d.ts +0 -3
  1845. package/script/methods/getSum.d.ts.map +0 -1
  1846. package/script/methods/getSum.js +0 -24
  1847. package/script/methods/getTableNames.d.ts +0 -3
  1848. package/script/methods/getTableNames.d.ts.map +0 -1
  1849. package/script/methods/getTableNames.js +0 -21
  1850. package/script/methods/getTop.d.ts +0 -7
  1851. package/script/methods/getTop.d.ts.map +0 -1
  1852. package/script/methods/getTop.js +0 -21
  1853. package/script/methods/getTypes.d.ts +0 -5
  1854. package/script/methods/getTypes.d.ts.map +0 -1
  1855. package/script/methods/getTypes.js +0 -20
  1856. package/script/methods/getUniques.d.ts +0 -3
  1857. package/script/methods/getUniques.d.ts.map +0 -1
  1858. package/script/methods/getUniques.js +0 -24
  1859. package/script/methods/getValues.d.ts +0 -3
  1860. package/script/methods/getValues.d.ts.map +0 -1
  1861. package/script/methods/getValues.js +0 -23
  1862. package/script/methods/getVariance.d.ts +0 -5
  1863. package/script/methods/getVariance.d.ts.map +0 -1
  1864. package/script/methods/getVariance.js +0 -26
  1865. package/script/methods/hdbscan.d.ts +0 -5
  1866. package/script/methods/hdbscan.d.ts.map +0 -1
  1867. package/script/methods/hdbscan.js +0 -214
  1868. package/script/methods/indexValues.d.ts +0 -27
  1869. package/script/methods/indexValues.d.ts.map +0 -1
  1870. package/script/methods/indexValues.js +0 -287
  1871. package/script/methods/insertRows.d.ts +0 -5
  1872. package/script/methods/insertRows.d.ts.map +0 -1
  1873. package/script/methods/insertRows.js +0 -47
  1874. package/script/methods/insertTables.d.ts +0 -5
  1875. package/script/methods/insertTables.d.ts.map +0 -1
  1876. package/script/methods/insertTables.js +0 -105
  1877. package/script/methods/intersection.d.ts +0 -3
  1878. package/script/methods/intersection.d.ts.map +0 -1
  1879. package/script/methods/intersection.js +0 -25
  1880. package/script/methods/intersects.d.ts +0 -3
  1881. package/script/methods/intersects.d.ts.map +0 -1
  1882. package/script/methods/intersects.js +0 -22
  1883. package/script/methods/join.d.ts +0 -7
  1884. package/script/methods/join.d.ts.map +0 -1
  1885. package/script/methods/join.js +0 -104
  1886. package/script/methods/joinGeo.d.ts +0 -12
  1887. package/script/methods/joinGeo.d.ts.map +0 -1
  1888. package/script/methods/joinGeo.js +0 -143
  1889. package/script/methods/keepValues.d.ts +0 -5
  1890. package/script/methods/keepValues.d.ts.map +0 -1
  1891. package/script/methods/keepValues.js +0 -41
  1892. package/script/methods/lastChars.d.ts +0 -3
  1893. package/script/methods/lastChars.d.ts.map +0 -1
  1894. package/script/methods/lastChars.js +0 -17
  1895. package/script/methods/length.d.ts +0 -7
  1896. package/script/methods/length.d.ts.map +0 -1
  1897. package/script/methods/length.js +0 -31
  1898. package/script/methods/linearRegressions.d.ts +0 -9
  1899. package/script/methods/linearRegressions.d.ts.map +0 -1
  1900. package/script/methods/linearRegressions.js +0 -103
  1901. package/script/methods/linesToPolygons.d.ts +0 -3
  1902. package/script/methods/linesToPolygons.d.ts.map +0 -1
  1903. package/script/methods/linesToPolygons.js +0 -23
  1904. package/script/methods/loadArray.d.ts +0 -19
  1905. package/script/methods/loadArray.d.ts.map +0 -1
  1906. package/script/methods/loadArray.js +0 -253
  1907. package/script/methods/loadDB.d.ts +0 -3
  1908. package/script/methods/loadDB.d.ts.map +0 -1
  1909. package/script/methods/loadDB.js +0 -66
  1910. package/script/methods/loadData.d.ts +0 -52
  1911. package/script/methods/loadData.d.ts.map +0 -1
  1912. package/script/methods/loadData.js +0 -158
  1913. package/script/methods/loadGeoData.d.ts +0 -9
  1914. package/script/methods/loadGeoData.d.ts.map +0 -1
  1915. package/script/methods/loadGeoData.js +0 -75
  1916. package/script/methods/loadOpenStreetMap.d.ts +0 -24
  1917. package/script/methods/loadOpenStreetMap.d.ts.map +0 -1
  1918. package/script/methods/loadOpenStreetMap.js +0 -375
  1919. package/script/methods/loadSample.d.ts +0 -9
  1920. package/script/methods/loadSample.d.ts.map +0 -1
  1921. package/script/methods/loadSample.js +0 -48
  1922. package/script/methods/loadStatCanData.d.ts +0 -10
  1923. package/script/methods/loadStatCanData.d.ts.map +0 -1
  1924. package/script/methods/loadStatCanData.js +0 -137
  1925. package/script/methods/loadYahooFinanceData.d.ts +0 -10
  1926. package/script/methods/loadYahooFinanceData.d.ts.map +0 -1
  1927. package/script/methods/loadYahooFinanceData.js +0 -139
  1928. package/script/methods/log.d.ts +0 -7
  1929. package/script/methods/log.d.ts.map +0 -1
  1930. package/script/methods/log.js +0 -66
  1931. package/script/methods/logBottom.d.ts +0 -5
  1932. package/script/methods/logBottom.d.ts.map +0 -1
  1933. package/script/methods/logBottom.js +0 -15
  1934. package/script/methods/longer.d.ts +0 -3
  1935. package/script/methods/longer.d.ts.map +0 -1
  1936. package/script/methods/longer.js +0 -29
  1937. package/script/methods/lower.d.ts +0 -3
  1938. package/script/methods/lower.d.ts.map +0 -1
  1939. package/script/methods/lower.js +0 -20
  1940. package/script/methods/neighbors.d.ts +0 -9
  1941. package/script/methods/neighbors.d.ts.map +0 -1
  1942. package/script/methods/neighbors.js +0 -120
  1943. package/script/methods/nest.d.ts +0 -3
  1944. package/script/methods/nest.d.ts.map +0 -1
  1945. package/script/methods/nest.js +0 -29
  1946. package/script/methods/normalize.d.ts +0 -7
  1947. package/script/methods/normalize.d.ts.map +0 -1
  1948. package/script/methods/normalize.js +0 -47
  1949. package/script/methods/normalizeString.d.ts +0 -5
  1950. package/script/methods/normalizeString.d.ts.map +0 -1
  1951. package/script/methods/normalizeString.js +0 -29
  1952. package/script/methods/normalizeVector.d.ts +0 -5
  1953. package/script/methods/normalizeVector.d.ts.map +0 -1
  1954. package/script/methods/normalizeVector.js +0 -138
  1955. package/script/methods/outliersIQR.d.ts +0 -5
  1956. package/script/methods/outliersIQR.d.ts.map +0 -1
  1957. package/script/methods/outliersIQR.js +0 -43
  1958. package/script/methods/pad.d.ts +0 -6
  1959. package/script/methods/pad.d.ts.map +0 -1
  1960. package/script/methods/pad.js +0 -61
  1961. package/script/methods/paths.d.ts +0 -13
  1962. package/script/methods/paths.d.ts.map +0 -1
  1963. package/script/methods/paths.js +0 -333
  1964. package/script/methods/perimeter.d.ts +0 -7
  1965. package/script/methods/perimeter.d.ts.map +0 -1
  1966. package/script/methods/perimeter.js +0 -31
  1967. package/script/methods/quantiles.d.ts +0 -5
  1968. package/script/methods/quantiles.d.ts.map +0 -1
  1969. package/script/methods/quantiles.js +0 -28
  1970. package/script/methods/randomPoint.d.ts +0 -6
  1971. package/script/methods/randomPoint.d.ts.map +0 -1
  1972. package/script/methods/randomPoint.js +0 -111
  1973. package/script/methods/ranks.d.ts +0 -7
  1974. package/script/methods/ranks.d.ts.map +0 -1
  1975. package/script/methods/ranks.js +0 -28
  1976. package/script/methods/reachable.d.ts +0 -11
  1977. package/script/methods/reachable.d.ts.map +0 -1
  1978. package/script/methods/reachable.js +0 -170
  1979. package/script/methods/reducePrecision.d.ts +0 -5
  1980. package/script/methods/reducePrecision.d.ts.map +0 -1
  1981. package/script/methods/reducePrecision.js +0 -30
  1982. package/script/methods/removeColumns.d.ts +0 -3
  1983. package/script/methods/removeColumns.d.ts.map +0 -1
  1984. package/script/methods/removeColumns.js +0 -19
  1985. package/script/methods/removeDuplicates.d.ts +0 -5
  1986. package/script/methods/removeDuplicates.d.ts.map +0 -1
  1987. package/script/methods/removeDuplicates.js +0 -23
  1988. package/script/methods/removeMissing.d.ts +0 -7
  1989. package/script/methods/removeMissing.d.ts.map +0 -1
  1990. package/script/methods/removeMissing.js +0 -86
  1991. package/script/methods/removeRows.d.ts +0 -3
  1992. package/script/methods/removeRows.d.ts.map +0 -1
  1993. package/script/methods/removeRows.js +0 -20
  1994. package/script/methods/removeTable.d.ts +0 -3
  1995. package/script/methods/removeTable.d.ts.map +0 -1
  1996. package/script/methods/removeTable.js +0 -20
  1997. package/script/methods/removeTables.d.ts +0 -4
  1998. package/script/methods/removeTables.d.ts.map +0 -1
  1999. package/script/methods/removeTables.js +0 -34
  2000. package/script/methods/removeValues.d.ts +0 -5
  2001. package/script/methods/removeValues.d.ts.map +0 -1
  2002. package/script/methods/removeValues.js +0 -41
  2003. package/script/methods/renameColumns.d.ts +0 -7
  2004. package/script/methods/renameColumns.d.ts.map +0 -1
  2005. package/script/methods/renameColumns.js +0 -33
  2006. package/script/methods/renameTable.d.ts +0 -3
  2007. package/script/methods/renameTable.d.ts.map +0 -1
  2008. package/script/methods/renameTable.js +0 -22
  2009. package/script/methods/repeatRows.d.ts +0 -5
  2010. package/script/methods/repeatRows.d.ts.map +0 -1
  2011. package/script/methods/repeatRows.js +0 -25
  2012. package/script/methods/replace.d.ts +0 -8
  2013. package/script/methods/replace.d.ts.map +0 -1
  2014. package/script/methods/replace.js +0 -75
  2015. package/script/methods/replaceNulls.d.ts +0 -3
  2016. package/script/methods/replaceNulls.d.ts.map +0 -1
  2017. package/script/methods/replaceNulls.js +0 -42
  2018. package/script/methods/reproject.d.ts +0 -5
  2019. package/script/methods/reproject.d.ts.map +0 -1
  2020. package/script/methods/reproject.js +0 -27
  2021. package/script/methods/rolling.d.ts +0 -6
  2022. package/script/methods/rolling.d.ts.map +0 -1
  2023. package/script/methods/rolling.js +0 -48
  2024. package/script/methods/round.d.ts +0 -6
  2025. package/script/methods/round.d.ts.map +0 -1
  2026. package/script/methods/round.js +0 -28
  2027. package/script/methods/rowProportions.d.ts +0 -7
  2028. package/script/methods/rowProportions.d.ts.map +0 -1
  2029. package/script/methods/rowProportions.js +0 -40
  2030. package/script/methods/rowRanks.d.ts +0 -9
  2031. package/script/methods/rowRanks.d.ts.map +0 -1
  2032. package/script/methods/rowRanks.js +0 -119
  2033. package/script/methods/rowToText.d.ts +0 -3
  2034. package/script/methods/rowToText.d.ts.map +0 -1
  2035. package/script/methods/rowToText.js +0 -33
  2036. package/script/methods/rowToVector.d.ts +0 -5
  2037. package/script/methods/rowToVector.d.ts.map +0 -1
  2038. package/script/methods/rowToVector.js +0 -83
  2039. package/script/methods/sample.d.ts +0 -5
  2040. package/script/methods/sample.d.ts.map +0 -1
  2041. package/script/methods/sample.js +0 -22
  2042. package/script/methods/selectColumns.d.ts +0 -3
  2043. package/script/methods/selectColumns.d.ts.map +0 -1
  2044. package/script/methods/selectColumns.js +0 -25
  2045. package/script/methods/selectRows.d.ts +0 -6
  2046. package/script/methods/selectRows.d.ts.map +0 -1
  2047. package/script/methods/selectRows.js +0 -40
  2048. package/script/methods/selectTables.d.ts +0 -4
  2049. package/script/methods/selectTables.d.ts.map +0 -1
  2050. package/script/methods/selectTables.js +0 -37
  2051. package/script/methods/setTypes.d.ts +0 -5
  2052. package/script/methods/setTypes.d.ts.map +0 -1
  2053. package/script/methods/setTypes.js +0 -36
  2054. package/script/methods/shortestPath.d.ts +0 -14
  2055. package/script/methods/shortestPath.d.ts.map +0 -1
  2056. package/script/methods/shortestPath.js +0 -497
  2057. package/script/methods/similarityMahalanobis.d.ts +0 -7
  2058. package/script/methods/similarityMahalanobis.d.ts.map +0 -1
  2059. package/script/methods/similarityMahalanobis.js +0 -120
  2060. package/script/methods/simplify.d.ts +0 -6
  2061. package/script/methods/simplify.d.ts.map +0 -1
  2062. package/script/methods/simplify.js +0 -44
  2063. package/script/methods/skip.d.ts +0 -3
  2064. package/script/methods/skip.d.ts.map +0 -1
  2065. package/script/methods/skip.js +0 -17
  2066. package/script/methods/sort.d.ts +0 -9
  2067. package/script/methods/sort.d.ts.map +0 -1
  2068. package/script/methods/sort.js +0 -41
  2069. package/script/methods/splitExtract.d.ts +0 -3
  2070. package/script/methods/splitExtract.d.ts.map +0 -1
  2071. package/script/methods/splitExtract.js +0 -27
  2072. package/script/methods/splitSpread.d.ts +0 -5
  2073. package/script/methods/splitSpread.d.ts.map +0 -1
  2074. package/script/methods/splitSpread.js +0 -90
  2075. package/script/methods/stream.d.ts +0 -8
  2076. package/script/methods/stream.d.ts.map +0 -1
  2077. package/script/methods/stream.js +0 -66
  2078. package/script/methods/summarize.d.ts +0 -15
  2079. package/script/methods/summarize.d.ts.map +0 -1
  2080. package/script/methods/summarize.js +0 -186
  2081. package/script/methods/topologicalSort.d.ts +0 -7
  2082. package/script/methods/topologicalSort.d.ts.map +0 -1
  2083. package/script/methods/topologicalSort.js +0 -170
  2084. package/script/methods/trim.d.ts +0 -6
  2085. package/script/methods/trim.d.ts.map +0 -1
  2086. package/script/methods/trim.js +0 -45
  2087. package/script/methods/truncate.d.ts +0 -3
  2088. package/script/methods/truncate.d.ts.map +0 -1
  2089. package/script/methods/truncate.js +0 -17
  2090. package/script/methods/umap.d.ts +0 -5
  2091. package/script/methods/umap.d.ts.map +0 -1
  2092. package/script/methods/umap.js +0 -135
  2093. package/script/methods/union.d.ts +0 -3
  2094. package/script/methods/union.d.ts.map +0 -1
  2095. package/script/methods/union.js +0 -25
  2096. package/script/methods/unnest.d.ts +0 -3
  2097. package/script/methods/unnest.d.ts.map +0 -1
  2098. package/script/methods/unnest.js +0 -21
  2099. package/script/methods/unnestGeo.d.ts +0 -3
  2100. package/script/methods/unnestGeo.d.ts.map +0 -1
  2101. package/script/methods/unnestGeo.js +0 -24
  2102. package/script/methods/updateColumn.d.ts +0 -3
  2103. package/script/methods/updateColumn.d.ts.map +0 -1
  2104. package/script/methods/updateColumn.js +0 -21
  2105. package/script/methods/updateWithJS.d.ts +0 -9
  2106. package/script/methods/updateWithJS.d.ts.map +0 -1
  2107. package/script/methods/updateWithJS.js +0 -194
  2108. package/script/methods/upper.d.ts +0 -3
  2109. package/script/methods/upper.d.ts.map +0 -1
  2110. package/script/methods/upper.js +0 -20
  2111. package/script/methods/wider.d.ts +0 -5
  2112. package/script/methods/wider.d.ts.map +0 -1
  2113. package/script/methods/wider.js +0 -29
  2114. package/script/methods/writeDB.d.ts +0 -6
  2115. package/script/methods/writeDB.d.ts.map +0 -1
  2116. package/script/methods/writeDB.js +0 -105
  2117. package/script/methods/writeData.d.ts +0 -7
  2118. package/script/methods/writeData.d.ts.map +0 -1
  2119. package/script/methods/writeData.js +0 -86
  2120. package/script/methods/zScore.d.ts +0 -6
  2121. package/script/methods/zScore.d.ts.map +0 -1
  2122. package/script/methods/zScore.js +0 -35
  2123. package/script/package.json +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimpleDB-d3LMXBzY.mjs","names":["crypto","findDuplicate","execute","execute","round","pad","formatDate","getRowCount","crypto","normalize","isArray","ChecksumTransform","capitalize","capitalize","getCurrentDatabase","isRecord","CACHE_FORMAT_VERSION","crypto","logCacheMiss","capitalize","date","join","execute","integerTypes","validateInputs","validateInputs","validateEndpoints","crypto","crypto","CACHE_DIRECTORY","crypto","assertOptions","crypto","join","getRowCount"],"sources":["../src/helpers/quoteIdentifier.ts","../src/helpers/LogValue.ts","../src/helpers/makeLogConverter.ts","../src/class/SDAError.ts","../src/helpers/stringifyUnknown.ts","../src/helpers/observeQuery.ts","../src/helpers/runQuery.ts","../src/helpers/tableGeneration.ts","../src/helpers/scanSQL.ts","../src/helpers/foldIdentifier.ts","../src/helpers/referencedTables.ts","../src/helpers/asyncOperationContext.ts","../src/helpers/cleanSQL.ts","../src/helpers/mergeOptions.ts","../src/helpers/queryDB.ts","../src/helpers/ensureSpatial.ts","../src/helpers/extractTypes.ts","../src/helpers/flushAllTables.ts","../src/helpers/cacheTableDependencies.ts","../src/helpers/tableRegistry.ts","../src/helpers/queueOp.ts","../src/helpers/readScalarNumber.ts","../src/helpers/vectorDistanceExpression.ts","../src/helpers/stabilizeCosineVectors.ts","../src/helpers/validateVectorRowIds.ts","../src/helpers/buildVectorNeighbors.ts","../src/helpers/buildUmapGraph.ts","../src/helpers/prepareNumericFeatures.ts","../src/helpers/fitUmapCurve.ts","../src/helpers/prepareUmapLayoutOptions.ts","../src/helpers/umapRandom.ts","../src/helpers/optimizeUmapLayout.ts","../src/helpers/initialUmapCoordinates.ts","../src/helpers/appendColumnBatches.ts","../src/methods/umap.ts","../src/helpers/buildSparseMutualReachabilityMst.ts","../src/helpers/inspectGraphConnectivity.ts","../src/helpers/buildApproximateMutualReachabilityMst.ts","../src/helpers/buildExactMutualReachabilityMst.ts","../src/helpers/clusterHdbscan.ts","../src/helpers/publishPreparedColumns.ts","../src/methods/hdbscan.ts","../src/helpers/splitGraphemes.ts","../src/helpers/wrapString.ts","../src/helpers/printTable.ts","../src/helpers/logData.ts","../src/methods/getBottom.ts","../src/methods/logBottom.ts","../src/helpers/quoteQualifiedIdentifier.ts","../src/methods/getData.ts","../src/helpers/formatNumber.ts","../src/methods/log.ts","../src/helpers/csvFormat.ts","../src/methods/getDescription.ts","../src/helpers/stringToArray.ts","../src/methods/removeMissing.ts","../src/methods/getColumns.ts","../src/methods/getRow.ts","../src/methods/getRowCount.ts","../src/methods/getCharacterCount.ts","../src/helpers/assertNewColumns.ts","../src/methods/addCharacterCount.ts","../src/methods/addWordCount.ts","../src/methods/getTypes.ts","../src/methods/getHash.ts","../src/methods/getValues.ts","../src/methods/getUniques.ts","../src/methods/getFirstRow.ts","../src/methods/getLastRow.ts","../src/methods/getTop.ts","../src/methods/getMin.ts","../src/methods/getMax.ts","../src/methods/getMean.ts","../src/methods/getMedian.ts","../src/methods/getSum.ts","../src/methods/getSkew.ts","../src/methods/getStdDev.ts","../src/methods/getVariance.ts","../src/methods/getQuantile.ts","../src/methods/cloneColumn.ts","../src/helpers/rewind.ts","../src/methods/getGeoData.ts","../src/helpers/createDirectory.ts","../src/helpers/getExtension.ts","../src/helpers/hasGeometryColumn.ts","../src/helpers/stringifyDates.ts","../src/helpers/stringifyDatesInvert.ts","../src/helpers/cleanPath.ts","../src/helpers/writeZip.ts","../src/helpers/writeGeoData.ts","../src/methods/splitSpread.ts","../src/helpers/getStatExpression.ts","../src/helpers/resolveOutputTable.ts","../src/methods/summarize.ts","../src/helpers/assertColumnsExist.ts","../src/helpers/keepNumericalColumns.ts","../src/methods/addSummaryRows.ts","../src/helpers/getCombinations.ts","../src/helpers/validateNumericalAnalysis.ts","../src/methods/correlations.ts","../src/methods/linearRegressions.ts","../src/helpers/capitalize.ts","../src/helpers/findGeoColumnFromSchema.ts","../src/helpers/getIdenticalColumns.ts","../src/helpers/assertSameDatabase.ts","../src/methods/joinGeo.ts","../src/helpers/prettyDuration.ts","../src/helpers/normalizeCacheCode.ts","../src/helpers/formatDate.ts","../src/helpers/cacheDiagnostics.ts","../src/helpers/serializeCacheInputs.ts","../src/helpers/indexDefinitions.ts","../src/helpers/parseValue.ts","../src/helpers/indexQueries.ts","../src/helpers/cacheDatabase.ts","../src/helpers/queryDbFile.ts","../src/helpers/readDbMetadata.ts","../src/helpers/readCacheSources.ts","../src/methods/cache.ts","../src/helpers/camelCase.ts","../src/methods/fill.ts","../src/helpers/prepareGeometry.ts","../src/helpers/prepareJSON.ts","../src/helpers/geometryFromJSON.ts","../src/helpers/parseTypes.ts","../src/helpers/parseDuckDBType.ts","../src/methods/loadArray.ts","../src/class/Simple.ts","../src/methods/join.ts","../src/helpers/buildFuzzyMatchSql.ts","../src/methods/fuzzyJoin.ts","../src/helpers/selectFuzzyReplacements.ts","../src/methods/fuzzyClean.ts","../src/helpers/findGeoColumn.ts","../src/methods/createFtsIndex.ts","../src/methods/createVssIndex.ts","../src/methods/bm25.ts","../src/methods/loadSample.ts","../src/methods/normalizeString.ts","../src/methods/distance.ts","../src/methods/extractLatLon.ts","../src/methods/coveredBy.ts","../src/methods/intersects.ts","../src/methods/normalize.ts","../src/helpers/toDuckDBValue.ts","../src/methods/indexValues.ts","../src/methods/zScore.ts","../src/methods/rolling.ts","../src/methods/accumulate.ts","../src/methods/columnProportions.ts","../src/methods/rowProportions.ts","../src/methods/rowRanks.ts","../src/methods/quantiles.ts","../src/methods/ranks.ts","../src/methods/updateColumn.ts","../src/methods/nest.ts","../src/methods/repeatRows.ts","../src/methods/unnest.ts","../src/methods/concatenate.ts","../src/methods/lastChars.ts","../src/methods/firstChars.ts","../src/methods/splitExtract.ts","../src/methods/truncate.ts","../src/methods/capitalize.ts","../src/methods/upper.ts","../src/methods/lower.ts","../src/methods/removeTable.ts","../src/methods/wider.ts","../src/methods/removeRows.ts","../src/helpers/prepareValueFilters.ts","../src/methods/removeValues.ts","../src/methods/keepValues.ts","../src/methods/filter.ts","../src/methods/removeDuplicates.ts","../src/methods/sample.ts","../src/methods/skip.ts","../src/methods/selectColumns.ts","../src/methods/sort.ts","../src/methods/loadData.ts","../src/methods/renameTable.ts","../src/helpers/dataToArrays.ts","../src/helpers/writeDataAsArrays.ts","../src/methods/writeData.ts","../src/methods/getBoundingBox.ts","../src/methods/linesToPolygons.ts","../src/methods/aggregateGeo.ts","../src/methods/addBoundingBox.ts","../src/methods/unnestGeo.ts","../src/methods/randomPoint.ts","../src/methods/centroid.ts","../src/methods/simplify.ts","../src/methods/union.ts","../src/methods/fillHoles.ts","../src/methods/difference.ts","../src/methods/intersection.ts","../src/methods/buffer.ts","../src/methods/perimeter.ts","../src/methods/length.ts","../src/methods/area.ts","../src/methods/reproject.ts","../src/methods/reducePrecision.ts","../src/methods/addGeoNoise.ts","../src/methods/flipCoordinates.ts","../src/methods/addGeoType.ts","../src/methods/addGeoClosedStatus.ts","../src/methods/fixGeo.ts","../src/methods/addVertexCount.ts","../src/methods/addGeoValidity.ts","../src/methods/createPoints.ts","../src/methods/stream.ts","../src/helpers/readMutationRows.ts","../src/methods/updateWithJS.ts","../src/methods/getSchema.ts","../src/methods/outliersIQR.ts","../src/methods/bins.ts","../src/methods/round.ts","../src/methods/addNoise.ts","../src/methods/rowToText.ts","../src/methods/rowToVector.ts","../src/methods/normalizeVector.ts","../src/helpers/factorCovariance.ts","../src/helpers/computeCovariance.ts","../src/helpers/computeMahalanobisDistances.ts","../src/methods/similarityMahalanobis.ts","../src/methods/replaceNulls.ts","../src/methods/pad.ts","../src/methods/replace.ts","../src/methods/crossJoin.ts","../src/methods/addId.ts","../src/helpers/prepareGraphStarts.ts","../src/helpers/getGraphEndpointColumns.ts","../src/helpers/prepareGraphTraversal.ts","../src/helpers/queueGraphResult.ts","../src/methods/neighbors.ts","../src/helpers/buildGraphTemporalReachabilitySql.ts","../src/helpers/prepareGraphTemporalSql.ts","../src/helpers/validateGraphTemporalEvents.ts","../src/methods/reachable.ts","../src/helpers/buildGraphTemporalCostStateSql.ts","../src/helpers/getGraphWeightColumn.ts","../src/helpers/prepareGraphMetricOptions.ts","../src/methods/distances.ts","../src/helpers/getGraphEdgeIdColumn.ts","../src/helpers/validateGraphRouteResultSchema.ts","../src/helpers/prepareGraphRouteSql.ts","../src/helpers/graphRouteResultSchema.ts","../src/helpers/graphRouteResultSelect.ts","../src/methods/shortestPath.ts","../src/methods/paths.ts","../src/helpers/buildChronologicalGraphComponentsSql.ts","../src/helpers/buildWeakGraphComponentsSql.ts","../src/methods/connectedComponents.ts","../src/methods/topologicalSort.ts","../src/methods/degree.ts","../src/methods/commonNeighbors.ts","../src/methods/findCycles.ts","../src/methods/addRowNumber.ts","../src/methods/addColumn.ts","../src/methods/extractDatePart.ts","../src/methods/removeColumns.ts","../src/methods/convert.ts","../src/methods/longer.ts","../src/methods/renameColumns.ts","../src/methods/trim.ts","../src/methods/selectRows.ts","../src/methods/cloneColumnWithOffset.ts","../src/methods/clone.ts","../src/helpers/removeColumnsNow.ts","../src/helpers/unifyColumns.ts","../src/methods/insertTables.ts","../src/methods/insertRows.ts","../src/helpers/osmFiles.ts","../src/methods/loadGeoData.ts","../src/helpers/loadOsmFile.ts","../src/helpers/fileCache.ts","../src/helpers/osmCache.ts","../src/methods/loadOpenStreetMap.ts","../src/helpers/extractZipEntryToFile.ts","../src/helpers/statCanCache.ts","../src/methods/loadStatCanData.ts","../src/methods/loadYahooFinanceData.ts","../src/methods/setTypes.ts","../src/class/SimpleTable.ts","../src/helpers/cleanCache.ts","../src/methods/getTableNames.ts","../src/helpers/getDbFileType.ts","../src/helpers/getCurrentDatabase.ts","../src/helpers/getDbIndexes.ts","../src/helpers/writeDbMetadata.ts","../src/helpers/prepareDbExtensions.ts","../src/helpers/setDbProps.ts","../src/methods/removeTables.ts","../src/helpers/formatMissingTables.ts","../src/methods/selectTables.ts","../src/methods/loadDB.ts","../src/methods/writeDB.ts","../src/class/SimpleDB.ts"],"sourcesContent":["/**\n * Quotes one SQL identifier and escapes embedded double quotes.\n * Use this for library-generated table, column, schema, database, and alias\n * names. User-authored SQL expressions must remain unmodified.\n *\n * @example\n * ```ts\n * quoteIdentifier('people \"archive\"');\n * // '\"people \"\"archive\"\"\"'\n * ```\n *\n * @param identifier - The identifier to quote.\n *\n * @returns The identifier wrapped in double quotes with embedded quotes doubled.\n */\nexport default function quoteIdentifier(identifier: string): string {\n return `\"${identifier.replaceAll('\"', '\"\"')}\"`;\n}\n","/** Internal display metadata; never returned by public data extraction. */\nexport default class LogValue {\n readonly text: string;\n readonly jsType: string;\n readonly category: \"number\" | \"string\" | \"date\" | \"boolean\" | \"null\";\n\n constructor(\n text: string,\n jsType: string,\n category: \"number\" | \"string\" | \"date\" | \"boolean\" | \"null\",\n ) {\n this.text = text;\n this.jsType = jsType;\n this.category = category;\n }\n}\n","import { type DuckDBType, DuckDBTypeId, type DuckDBValue } from \"@duckdb/node-api\";\nimport LogValue from \"./LogValue.ts\";\n\n/** Formats native temporal values before extraction can discard precision. */\nexport default function makeLogConverter(\n type: DuckDBType,\n convert: (value: DuckDBValue) => unknown,\n): (value: DuckDBValue) => LogValue {\n const sqlType = type.toString();\n const floatArray = sqlType.includes(\"FLOAT[\");\n const placeholder = sqlType.toLowerCase().includes(\"geometry\") || floatArray;\n const temporal = [\n DuckDBTypeId.DATE,\n DuckDBTypeId.TIME,\n DuckDBTypeId.TIME_TZ,\n DuckDBTypeId.TIME_NS,\n DuckDBTypeId.TIMESTAMP,\n DuckDBTypeId.TIMESTAMP_TZ,\n DuckDBTypeId.TIMESTAMP_S,\n DuckDBTypeId.TIMESTAMP_MS,\n DuckDBTypeId.TIMESTAMP_NS,\n ].includes(type.typeId);\n const numeric =\n !placeholder &&\n /^(TINYINT|SMALLINT|INTEGER|BIGINT|HUGEINT|UTINYINT|USMALLINT|UINTEGER|UBIGINT|UHUGEINT|FLOAT|DOUBLE|DECIMAL|BIGNUM)(\\(|$)/.test(\n sqlType,\n );\n const jsType = placeholder\n ? \"string\"\n : type.typeId === DuckDBTypeId.DATE || type.typeId === DuckDBTypeId.TIMESTAMP\n ? \"object\"\n : temporal\n ? \"string\"\n : type.typeId === DuckDBTypeId.BOOLEAN\n ? \"boolean\"\n : numeric\n ? /^(DECIMAL|BIGNUM)/.test(sqlType)\n ? \"string\"\n : \"number\"\n : [\n DuckDBTypeId.LIST,\n DuckDBTypeId.ARRAY,\n DuckDBTypeId.STRUCT,\n DuckDBTypeId.MAP,\n DuckDBTypeId.UNION,\n DuckDBTypeId.INTERVAL,\n ].includes(type.typeId)\n ? \"object\"\n : \"string\";\n return (value) => {\n if (value === null) return new LogValue(\"null\", jsType, \"null\");\n // TIMESTAMPTZ uses the existing UTC converter, independent of process timezone.\n const converted = floatArray\n ? `<${sqlType}>`\n : temporal && type.typeId !== DuckDBTypeId.TIMESTAMP_TZ\n ? String(value)\n : convert(value);\n const text =\n typeof converted === \"object\" && converted !== null\n ? JSON.stringify(converted)\n : String(converted);\n return new LogValue(\n text,\n // NaN and infinities are strings in the public JSON conversion.\n temporal ? jsType : typeof converted,\n temporal ? \"date\" : numeric ? \"number\" : jsType === \"boolean\" ? \"boolean\" : \"string\",\n );\n };\n}\n","/**\n * An error thrown when a SQL query fails. It carries the SDA method that\n * triggered the query, the parameters passed to it, the SQL query itself,\n * and the original error as `cause`.\n *\n * @example\n * ```ts\n * try {\n * await table.selectColumns(\"aColumnThatDoesNotExist\").run();\n * } catch (error) {\n * if (error instanceof SDAError) {\n * console.log(error.method); // \"selectColumns()\"\n * console.log(error.query); // The SQL query that failed\n * console.log(error.cause); // The original DuckDB error\n * }\n * }\n * ```\n */\nexport default class SDAError extends Error {\n /**\n * The SDA method that triggered the failing query.\n */\n method: string | null;\n /**\n * The parameters passed to the method.\n */\n parameters: { [key: string]: unknown } | null;\n /**\n * The SQL query that failed.\n */\n query: string;\n\n /**\n * Creates an error that preserves the failing query and its original cause.\n *\n * @example\n * ```ts\n * const error = new SDAError({\n * method: \"example()\",\n * parameters: { column: \"missing\" },\n * query: \"SELECT missing FROM data\",\n * cause: new Error(\"Column not found\"),\n * });\n * console.log(error.method, error.cause);\n * ```\n *\n * @param options - Details of the failed query.\n * @param options.method - The SDA method that triggered the query, or `null`.\n * @param options.parameters - The method's arguments, or `null`.\n * @param options.query - The SQL statement that failed.\n * @param options.cause - The original error thrown while executing the query.\n */\n constructor(options: {\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n query: string;\n cause: unknown;\n }) {\n let causeMessage =\n options.cause instanceof Error ? options.cause.message : String(options.cause);\n if (causeMessage.includes(\"connection disconnected\")) {\n causeMessage =\n \"Database connection closed before all operations finished. Did you forget to add `await`?\";\n }\n super(\n options.method === null ? causeMessage : `${causeMessage}\\nSDA method: ${options.method}`,\n { cause: options.cause },\n );\n this.name = \"SDAError\";\n this.method = options.method;\n this.parameters = options.parameters;\n this.query = options.query;\n }\n}\n","/**\n * Converts an unknown value to text with JavaScript's primitive-conversion\n * semantics. The default hint matches string concatenation; the string hint\n * matches String(value). Template mode uses the string hint but rejects symbols,\n * matching template interpolation. Explicit object conversion also preserves\n * custom valueOf, toString, and Symbol.toPrimitive implementations.\n */\nexport default function stringifyUnknown(\n value: unknown,\n mode: \"string\" | \"default\" | \"template\" = \"string\",\n): string {\n const hint = mode === \"default\" ? \"default\" : \"string\";\n if (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n const convert: unknown = Reflect.get(value, Symbol.toPrimitive);\n if (convert !== null && convert !== undefined) {\n if (typeof convert !== \"function\")\n throw new TypeError(\"Cannot convert object to primitive value\");\n const primitive: unknown = Reflect.apply(convert, value, [hint]);\n return stringifyPrimitive(primitive, false);\n }\n const methods = hint === \"string\" ? [\"toString\", \"valueOf\"] : [\"valueOf\", \"toString\"];\n for (const name of methods) {\n const method: unknown = Reflect.get(value, name);\n if (typeof method === \"function\") {\n const primitive: unknown = Reflect.apply(method, value, []);\n if (\n primitive === null ||\n (typeof primitive !== \"object\" && typeof primitive !== \"function\")\n ) {\n return stringifyPrimitive(primitive, false);\n }\n }\n }\n throw new TypeError(\"Cannot convert object to primitive value\");\n }\n return stringifyPrimitive(value, mode === \"string\");\n}\n\nfunction stringifyPrimitive(value: unknown, allowSymbol: boolean): string {\n if (value === null) return \"null\";\n switch (typeof value) {\n case \"string\":\n return value;\n case \"undefined\":\n return \"undefined\";\n case \"number\":\n case \"bigint\":\n case \"boolean\":\n return String(value);\n case \"symbol\":\n if (allowSymbol) return String(value);\n throw new TypeError(\"Cannot convert a Symbol value to a string\");\n default:\n throw new TypeError(\"Cannot convert object to primitive value\");\n }\n}\n","import stringifyUnknown from \"./stringifyUnknown.ts\";\nimport type { DuckDBConnection, DuckDBValue } from \"@duckdb/node-api\";\n\nconst explainableStatements = new Set([\n \"CREATE\",\n \"DELETE\",\n \"FROM\",\n \"INSERT\",\n \"MERGE\",\n \"SELECT\",\n \"UPDATE\",\n \"WITH\",\n]);\n\n/**\n * Logs optional SQL diagnostics without changing the statement that will run.\n */\nexport default async function observeQuery(\n connection: DuckDBConnection,\n query: string,\n values: DuckDBValue[],\n options: { logSQL: boolean; explainSQL: boolean },\n): Promise<void> {\n if (options.explainSQL && (await canExplain(connection, query))) {\n try {\n const explain = `EXPLAIN ${query}`;\n const result =\n values.length === 0 ? await connection.run(explain) : await connection.run(explain, values);\n const rows = await result.getRowsJS();\n const plan = rows.map((row) => stringifyUnknown(row[1] ?? row[0] ?? \"\")).join(\"\\n\");\n console.log(`EXPLAIN ${query}\\n${plan}`);\n } catch (error) {\n console.warn(\n `SDA: Could not explain the following SQL; executing it normally.\\n${query}\\n${String(\n error,\n )}`,\n );\n }\n }\n\n // Keep this immediately before connection.run()/stream() so the last SQL\n // diagnostic identifies the statement responsible for an execution error.\n if (options.logSQL) {\n console.log(query);\n if (values.length > 0) {\n console.log(\"Bound values:\", values);\n }\n }\n}\n\nasync function canExplain(connection: DuckDBConnection, query: string): Promise<boolean> {\n const keyword = query\n .trimStart()\n .match(/^([A-Za-z]+)/)?.[1]\n .toUpperCase();\n if (keyword === undefined || !explainableStatements.has(keyword)) {\n return false;\n }\n try {\n return (await connection.extractStatements(query)).count === 1;\n } catch {\n return false;\n }\n}\n","import makeLogConverter from \"./makeLogConverter.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport {\n type DuckDBConnection,\n type DuckDBDateValue,\n type DuckDBTimestampTZValue,\n DuckDBTimestampValue,\n type DuckDBType,\n DuckDBTypeId,\n type DuckDBValue,\n type DuckDBValueConverter,\n type Json,\n JsonDuckDBValueConverter,\n} from \"@duckdb/node-api\";\nimport SDAError from \"../class/SDAError.ts\";\nimport observeQuery from \"./observeQuery.ts\";\n\ntype RunQueryOptions = {\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n table?: string | null;\n values?: DuckDBValue[];\n logSQL: boolean;\n explainSQL: boolean;\n};\n\nconst msPerDay = 24 * 60 * 60 * 1000;\nconst maxSafeInteger = BigInt(Number.MAX_SAFE_INTEGER);\nconst minSafeInteger = BigInt(Number.MIN_SAFE_INTEGER);\n\nfunction makeIntegerConverter(columnName: string, tableName: string | null) {\n return (value: DuckDBValue) => {\n if (value === null) {\n return null;\n }\n const bigintValue = value as bigint;\n if (bigintValue > maxSafeInteger || bigintValue < minSafeInteger) {\n throw new RangeError(\n `SDA: Column ${quoteIdentifier(columnName)}${\n tableName === null ? \"\" : ` of table ${quoteIdentifier(tableName)}`\n } contains ${bigintValue} outside JavaScript's safe integer range (Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER). Cast the column to VARCHAR to retrieve exact digits.`,\n );\n }\n return Number(bigintValue);\n };\n}\n\nfunction utcTimestampTzValue(value: DuckDBValue): string | null {\n if (value === null) {\n return null;\n }\n const timestamp = new DuckDBTimestampValue((value as DuckDBTimestampTZValue).micros).toString();\n return timestamp === \"infinity\" || timestamp === \"-infinity\" ? timestamp : `${timestamp}+00`;\n}\n\nconst utcJsonValueConverter: DuckDBValueConverter<Json> = (value, type, _converter) =>\n type.typeId === DuckDBTypeId.TIMESTAMP_TZ\n ? utcTimestampTzValue(value)\n : JsonDuckDBValueConverter(value, type, utcJsonValueConverter);\n\nexport function makeConverter(\n type: DuckDBType,\n columnName: string,\n tableName: string | null = null,\n): (value: DuckDBValue) => unknown {\n const typeString = type.toString();\n if (typeString.toLowerCase().includes(\"geometry\")) {\n const placeholder = `GEOM(${typeString.replace(\"GEOMETRY('\", \"\").replace(\"')\", \"\")})`;\n return (value) => (value === null ? null : placeholder);\n }\n switch (type.typeId) {\n case DuckDBTypeId.DATE:\n return (value) =>\n value === null ? null : new Date((value as DuckDBDateValue).days * msPerDay);\n case DuckDBTypeId.TIMESTAMP:\n return (value) => {\n if (value === null) {\n return null;\n }\n const micros = (value as DuckDBTimestampValue).micros;\n // Floor division, so sub-millisecond precision truncates toward\n // the past for dates before the epoch too.\n const ms = micros >= 0n ? micros / 1000n : (micros - 999n) / 1000n;\n return new Date(Number(ms));\n };\n case DuckDBTypeId.TIMESTAMP_TZ:\n return utcTimestampTzValue;\n case DuckDBTypeId.BIGINT:\n case DuckDBTypeId.HUGEINT:\n case DuckDBTypeId.UBIGINT:\n case DuckDBTypeId.UHUGEINT:\n return makeIntegerConverter(columnName, tableName);\n default:\n return (value) => utcJsonValueConverter(value, type, utcJsonValueConverter);\n }\n}\n\nexport default async function runQuery(\n query: string,\n connection: DuckDBConnection,\n returnData: boolean,\n options: RunQueryOptions,\n): Promise<\n | {\n [key: string]: unknown;\n }[]\n | null\n> {\n const values = options.values ?? [];\n try {\n await observeQuery(connection, query, values, options);\n if (returnData) {\n const result =\n values.length === 0 ? await connection.run(query) : await connection.run(query, values);\n const columnNames = result.deduplicatedColumnNames();\n const columnTypes = result.columnTypes();\n if (\n options.method === \"getData()\" &&\n columnTypes.some((type) => type.toString().toLowerCase().includes(\"geometry\"))\n ) {\n throw new Error(\"The query returns geometry columns. Use getGeoData() instead.\");\n }\n const logging = options.method === \"log()\" || options.method === \"logBottom()\";\n const converters = columnTypes.map((type, i) => {\n const converter = makeConverter(type, columnNames[i], options.table ?? null);\n return logging ? makeLogConverter(type, converter) : converter;\n });\n const columnCount = columnNames.length;\n // The result is converted chunk by chunk, so no intermediate row-major\n // copy of the whole result is materialized.\n const rows: { [key: string]: unknown }[] = [];\n while (true) {\n const chunk = await result.fetchChunk();\n if (chunk === null || chunk === undefined || chunk.rowCount === 0) {\n break;\n }\n const base = rows.length;\n for (let i = 0; i < chunk.rowCount; i++) {\n rows.push({});\n }\n for (let j = 0; j < columnCount; j++) {\n const columnName = columnNames[j];\n const converter = converters[j];\n if (columnName === \"__proto__\") {\n // This valid SQL identifier must define data, not invoke Node's\n // legacy Object.prototype setter. Keep ordinary columns fast.\n chunk.visitColumnValues(j, (value, rowIndex) => {\n Object.defineProperty(rows[base + rowIndex], columnName, {\n value: converter(value),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n });\n } else {\n chunk.visitColumnValues(j, (value, rowIndex) => {\n rows[base + rowIndex][columnName] = converter(value);\n });\n }\n }\n }\n return rows;\n } else {\n if (values.length === 0) {\n await connection.run(query);\n } else {\n await connection.run(query, values);\n }\n return null;\n }\n } catch (error) {\n throw new SDAError({\n method: options.method,\n parameters: options.parameters,\n query,\n cause: error,\n });\n }\n}\n","import crypto from \"node:crypto\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\ndeclare const tableGenerationIdBrand: unique symbol;\n\n/** An opaque identifier for one in-process or cached table generation. */\nexport type TableGenerationId = string & {\n readonly [tableGenerationIdBrand]: true;\n};\n\nconst generations = new WeakMap<SimpleTable, TableGenerationId>();\n\n/** Returns an established generation without creating one for a new table. */\nexport function peekTableGeneration(table: SimpleTable): TableGenerationId | undefined {\n return generations.get(table);\n}\n\n/** Creates a new table generation identifier. */\nexport function createTableGenerationId(): TableGenerationId {\n return crypto.randomUUID() as TableGenerationId;\n}\n\n/** Returns the current in-process generation identifier for a table. */\nexport function getTableGeneration(table: SimpleTable): TableGenerationId {\n let generation = generations.get(table);\n if (generation === undefined) {\n generation = createTableGenerationId();\n generations.set(table, generation);\n }\n return generation;\n}\n\n/** Gives a table a new generation after it may have changed. */\nexport function markTableChanged(table: SimpleTable): TableGenerationId {\n const generation = createTableGenerationId();\n generations.set(table, generation);\n return generation;\n}\n\n/** Restores the generation persisted with a cached table artifact. */\nexport function restoreTableGeneration(table: SimpleTable, generation: TableGenerationId): void {\n generations.set(table, generation);\n}\n","type Token = { text: string; kind: \"sql\" | \"quoted\" | \"trivia\" };\n\n// Keep opaque SQL regions byte-for-byte intact. Only SQL tokens participate in\n// normalization; parameter values never enter this module.\nexport default function scanSQL(query: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n while (i < query.length) {\n const start = i;\n let kind: Token[\"kind\"] = \"sql\";\n const rest = query.slice(i);\n if (/\\s/.test(query[i])) {\n kind = \"trivia\";\n while (i < query.length && /\\s/.test(query[i])) i++;\n } else if (rest.startsWith(\"--\")) {\n kind = \"trivia\";\n while (i < query.length && !/[\\r\\n]/.test(query[i])) i++;\n } else if (rest.startsWith(\"/*\")) {\n kind = \"trivia\";\n i += 2;\n let depth = 1;\n while (i < query.length && depth > 0) {\n if (query.startsWith(\"/*\", i)) {\n depth++;\n i += 2;\n } else if (query.startsWith(\"*/\", i)) {\n depth--;\n i += 2;\n } else i++;\n }\n } else if (/^[eE]'/.test(rest) || query[i] === \"'\" || query[i] === '\"') {\n kind = \"quoted\";\n const escaped = /^[eE]'/.test(rest);\n if (escaped) i++;\n const quote = query[i++];\n while (i < query.length) {\n if (escaped && query[i] === \"\\\\\") i = Math.min(i + 2, query.length);\n else if (query[i++] === quote) {\n if (query[i] === quote) i++;\n else break;\n }\n }\n } else {\n // DuckDB permits non-ASCII characters in dollar tags, including\n // combining marks and characters outside the Unicode letter categories.\n const dollar = rest.match(/^\\$(?:[A-Za-z_\\u0080-\\uFFFF][A-Za-z_0-9\\u0080-\\uFFFF]*)?\\$/)?.[0];\n if (dollar) {\n kind = \"quoted\";\n const end = query.indexOf(dollar, i + dollar.length);\n i = end === -1 ? query.length : end + dollar.length;\n } else {\n const token = rest.match(\n /^(?:[\\p{L}_][\\p{L}\\p{N}_$]*|\\$(?:[0-9]+|[\\p{L}_][\\p{L}\\p{N}_]*)|!==|===|==|!=|<>|<=|>=|&&|\\|\\||::)/u,\n )?.[0];\n i += token?.length ?? 1;\n }\n }\n tokens.push({ text: query.slice(start, i), kind });\n }\n return tokens;\n}\n","/** Matches DuckDB's ASCII case folding for quoted and unquoted identifiers. */\nexport default function foldIdentifier(identifier: string): string {\n return identifier.replace(/[A-Z]/g, (letter) => letter.toLowerCase());\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport scanSQL from \"./scanSQL.ts\";\nimport foldIdentifier from \"./foldIdentifier.ts\";\nimport { getRegisteredTables } from \"./tableRegistry.ts\";\n\n/**\n * Finds registered table identifiers in SQL, excluding literals and comments.\n * Matching is conservative: column names and aliases also count as references.\n * DuckDB folds ASCII letters in both quoted and unquoted identifiers.\n */\nexport default function referencedTables(sql: readonly string[], sdb: SimpleDB): SimpleTable[] {\n const identifiers = new Set<string>();\n for (const fragment of sql) {\n for (const token of scanSQL(fragment)) {\n if (token.kind === \"quoted\" && token.text.startsWith('\"')) {\n identifiers.add(foldIdentifier(token.text.slice(1, -1).replaceAll('\"\"', '\"')));\n } else if (token.kind === \"sql\" && /^[\\p{L}_][\\p{L}\\p{N}_$]*$/u.test(token.text)) {\n identifiers.add(foldIdentifier(token.text));\n }\n }\n }\n return getRegisteredTables(sdb).filter((table) => identifiers.has(foldIdentifier(table.name)));\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { PendingOp } from \"./pendingOps.ts\";\n\nexport type PendingEntry = {\n table: SimpleTable;\n op: PendingOp;\n};\n\nexport type AsyncOperationFrame = {\n sdb: SimpleDB;\n entries: PendingEntry[];\n drainPromise: Promise<void> | null;\n open: boolean;\n};\n\nconst operationContext = new AsyncLocalStorage<AsyncOperationFrame[]>();\nconst drainContext = new AsyncLocalStorage<Set<AsyncOperationFrame>>();\n\nexport function getAsyncOperationFrame(sdb: SimpleDB): AsyncOperationFrame | undefined {\n return operationContext.getStore()?.findLast((frame) => frame.sdb === sdb && frame.open);\n}\n\nexport function captureAsyncOperation(sdb: SimpleDB, entry: PendingEntry): boolean {\n const frame = getAsyncOperationFrame(sdb);\n if (frame === undefined) {\n return false;\n }\n frame.entries.push(entry);\n return true;\n}\n\nexport async function runWithAsyncOperationFrame<T>(\n sdb: SimpleDB,\n fn: (frame: AsyncOperationFrame) => Promise<T>,\n): Promise<T> {\n const frame: AsyncOperationFrame = {\n sdb,\n entries: [],\n drainPromise: null,\n open: true,\n };\n const frames = [...(operationContext.getStore() ?? []), frame];\n try {\n return await operationContext.run(frames, () => fn(frame));\n } finally {\n frame.open = false;\n frame.entries.length = 0;\n }\n}\n\nexport function isDrainingAsyncOperationFrame(frame: AsyncOperationFrame): boolean {\n return drainContext.getStore()?.has(frame) ?? false;\n}\n\nexport function runWhileDrainingAsyncOperationFrame<T>(\n frame: AsyncOperationFrame,\n fn: () => Promise<T>,\n): Promise<T> {\n const draining = new Set(drainContext.getStore());\n draining.add(frame);\n return drainContext.run(draining, fn);\n}\n","import scanSQL from \"./scanSQL.ts\";\n\nexport default function cleanSQL(query: string, syntax: \"js\" | \"sql\" = \"js\"): string {\n if (syntax === \"sql\") return query;\n const tokens = scanSQL(query);\n const significant = tokens.filter((token) => token.kind !== \"trivia\");\n const original = significant.map((token) =>\n token.kind === \"sql\" ? token.text.toUpperCase() : \"\",\n );\n const pairs = new Map<number, number>();\n const stack: number[] = [];\n for (let i = 0; i < original.length; i++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[i])) stack.push(i);\n else if (\n stack.length &&\n ((original[i] === \")\" && original[stack[stack.length - 1]] === \"(\") ||\n (original[i] === \"]\" && original[stack[stack.length - 1]] === \"[\") ||\n (original[i] === \"END\" && original[stack[stack.length - 1]] === \"CASE\"))\n ) {\n const start = stack.pop()!;\n pairs.set(start, i);\n pairs.set(i, start);\n }\n }\n const betweenAnd = new Set<number>();\n for (let i = 0; i < original.length; i++) {\n if (original[i] !== \"BETWEEN\") continue;\n for (let j = i + 1; j < original.length; j++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[j])) {\n j = pairs.get(j) ?? original.length;\n } else if ([\")\", \"]\", \"END\", \";\"].includes(original[j])) break;\n else if (original[j] === \"AND\") {\n betweenAnd.add(j);\n break;\n }\n }\n }\n const comparisons = new Set([\n \"=\",\n \"==\",\n \"===\",\n \"!=\",\n \"!==\",\n \"<>\",\n \"<\",\n \">\",\n \"<=\",\n \">=\",\n \"IS\",\n \"IN\",\n \"LIKE\",\n \"ILIKE\",\n \"BETWEEN\",\n ]);\n const boundaries = new Set([\n \"SELECT\",\n \"FROM\",\n \"WHERE\",\n \"HAVING\",\n \"QUALIFY\",\n \"GROUP\",\n \"ORDER\",\n \"LIMIT\",\n \"RETURNING\",\n \"UNION\",\n \"EXCEPT\",\n \"INTERSECT\",\n \"WHEN\",\n \"THEN\",\n \"ELSE\",\n \"AS\",\n \"AND\",\n \"OR\",\n \"&&\",\n \",\",\n \";\",\n ]);\n const textTypes = new Set([\"VARCHAR\", \"CHAR\", \"BPCHAR\", \"TEXT\", \"STRING\"]);\n\n function range(\n pipe: number,\n start: number,\n end: number,\n stop: (i: number) => boolean,\n ): [number, number] {\n let left = pipe - 1;\n while (left >= start && !stop(left)) {\n if ([\")\", \"]\", \"END\"].includes(original[left])) {\n left = pairs.get(left) ?? start;\n }\n left--;\n }\n let right = pipe + 1;\n while (right < end && !stop(right)) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[right])) {\n right = pairs.get(right) ?? end;\n }\n right++;\n }\n return [left + 1, right];\n }\n\n function predicate(start: number, end: number): boolean {\n if (original[start] === \"(\" && pairs.get(start) === end - 1) {\n return predicate(start + 1, end - 1);\n }\n for (let i = start; i < end; i++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[i])) i = pairs.get(i) ?? end;\n else if (comparisons.has(original[i])) return true;\n }\n return false;\n }\n\n // Only infer types that are explicit in the expression. Never infer a\n // column's or an arbitrary function's type from its name or argument types.\n function isTextType(start: number, end: number): boolean {\n return (\n textTypes.has(original[start]) &&\n (start + 1 === end || (original[start + 1] === \"(\" && pairs.get(start + 1) === end - 1))\n );\n }\n\n function concatenable(start: number, end: number): boolean {\n if (start >= end) return false;\n let cast: number | undefined;\n let pipe: number | undefined;\n for (let i = start; i < end; i++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[i])) i = pairs.get(i) ?? end;\n else if (comparisons.has(original[i])) return false;\n else if (original[i] === \"||\") pipe ??= i;\n else if (original[i] === \"::\") cast = i;\n }\n if (pipe !== undefined) {\n return concatenable(start, pipe) || concatenable(pipe + 1, end);\n }\n // The final cast determines the result type, including casts to BOOLEAN.\n if (cast !== undefined) {\n return isTextType(cast + 1, end);\n }\n if (original[start] === \"(\" && pairs.get(start) === end - 1) {\n return concatenable(start + 1, end - 1);\n }\n if (original[start] === \"[\" && pairs.get(start) === end - 1) return true;\n if (end === start + 1) {\n return significant[start].kind === \"quoted\" && !significant[start].text.startsWith('\"');\n }\n if (original[start + 1] === \"(\" && pairs.get(start + 1) === end - 1) {\n if ([\"CONCAT\", \"CONCAT_WS\"].includes(original[start])) return true;\n if ([\"CAST\", \"TRY_CAST\"].includes(original[start])) {\n for (let i = start + 2; i < end - 1; i++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[i])) {\n i = pairs.get(i) ?? end;\n } else if (original[i] === \"AS\") {\n return isTextType(i + 1, end - 1);\n }\n }\n }\n }\n return false;\n }\n\n function obviousConcatenation(pipe: number, start: number, end: number): boolean {\n const [left, right] = range(\n pipe,\n start,\n end,\n (i) => (boundaries.has(original[i]) && !betweenAnd.has(i)) || original[i] === \"||\",\n );\n // A literal in a comparison is not evidence that the comparison returns text.\n if (predicate(left, pipe) && predicate(pipe + 1, right)) return false;\n const [groupStart, groupEnd] = range(\n pipe,\n start,\n end,\n (i) => boundaries.has(original[i]) || comparisons.has(original[i]),\n );\n let operand = groupStart;\n for (let i = groupStart; i <= groupEnd; i++) {\n if ([\"(\", \"[\", \"CASE\"].includes(original[i])) {\n i = pairs.get(i) ?? groupEnd;\n } else if (i === groupEnd || original[i] === \"||\") {\n // Do not use the RHS literal of a preceding comparison to infer OR's\n // meaning (text = 'a' || active). Other operands can still prove concat.\n if (\n !(\n operand === groupStart &&\n (comparisons.has(original[groupStart - 1]) || betweenAnd.has(groupStart - 1))\n ) &&\n concatenable(operand, i)\n )\n return true;\n operand = i + 1;\n }\n }\n return false;\n }\n\n function normalize(start: number, end: number) {\n let statement: string | undefined = original[start];\n let inSetClause = false;\n let assignmentTarget = false;\n for (let i = start; i < end; i++) {\n const word = original[i];\n if (statement === undefined) statement = word;\n // Nested queries are visited separately below. Look through statement\n // prefixes to find the outer command that can introduce assignments.\n if (\n [\"WITH\", \"EXPLAIN\", \"PREPARE\"].includes(statement) &&\n [\"SELECT\", \"INSERT\", \"UPDATE\", \"DELETE\", \"MERGE\"].includes(word)\n )\n statement = word;\n if (word === \"UPDATE\" && [\"DO\", \"THEN\"].includes(original[i - 1])) statement = word;\n if ([\"(\", \"[\", \"CASE\"].includes(word)) {\n const close = pairs.get(i);\n if (close !== undefined) {\n normalize(i + 1, close);\n i = close;\n continue;\n }\n }\n if ([\"WHERE\", \"HAVING\", \"QUALIFY\", \"WHEN\"].includes(word)) {\n statement = word;\n inSetClause = false;\n assignmentTarget = false;\n } else if (\n [\n \"THEN\",\n \"ELSE\",\n \"SELECT\",\n \"FROM\",\n \"GROUP\",\n \"ORDER\",\n \"LIMIT\",\n \"RETURNING\",\n \"UNION\",\n \"EXCEPT\",\n \"INTERSECT\",\n \";\",\n ].includes(word)\n ) {\n statement = word;\n inSetClause = false;\n assignmentTarget = false;\n } else if (\n word === \"SET\" &&\n !inSetClause &&\n (statement === \"UPDATE\" ||\n (statement === \"SET\" && (original[i + 1] === \"VARIABLE\" || original[i + 2] === \"=\")))\n ) {\n inSetClause = true;\n assignmentTarget = true;\n } else if (word === \",\" && inSetClause) assignmentTarget = true;\n if (word === \";\") statement = undefined;\n\n // Preserve only the assignment operator itself. Comparisons in its RHS\n // still use shorthand, even when they are not wrapped in parentheses.\n const assignment = assignmentTarget && [\"=\", \"==\", \"===\"].includes(word);\n if (assignment) assignmentTarget = false;\n\n const token = significant[i];\n if ([\"==\", \"===\"].includes(word)) token.text = \"=\";\n else if (word === \"!==\") token.text = \"!=\";\n else if (word === \"&&\") token.text = \" AND \";\n else if (word === \"||\" && !obviousConcatenation(i, start, end)) {\n token.text = \" OR \";\n }\n if (original[i + 1] === \"NULL\" && !assignment) {\n if ([\"=\", \"==\", \"===\"].includes(word)) token.text = \" IS \";\n else if ([\"!=\", \"!==\"].includes(word)) token.text = \" IS NOT \";\n }\n }\n }\n normalize(0, significant.length);\n return tokens\n .map((token) => token.text)\n .join(\"\")\n .trim();\n}\n","import type { DuckDBValue as NativeDuckDBValue } from \"@duckdb/node-api\";\n\n/** @internal DuckDB owns this type; retain its exact binding contract without re-exporting it. */\ntype DuckDBValue = NativeDuckDBValue;\n\n/**\n * Combines a table or database's logging defaults with query-specific options.\n * Use this helper with `queryDB()` when implementing an extension.\n *\n * @example\n * ```ts\n * import { mergeOptions } from \"@nshiab/simple-data-analysis-core/helpers\";\n *\n * const options = mergeOptions(sdb, {\n * table: null,\n * method: \"example()\",\n * parameters: null,\n * returnData: true,\n * });\n * console.log(options.rowsToLog, options.returnData);\n * ```\n *\n * @param simple - The logging defaults from a table or database.\n *\n * @param simple.rowsToLog - The default number of rows to display.\n *\n * @param simple.charsToLog - The default maximum characters to display per cell.\n *\n * @param options - Query-specific settings, which take precedence over defaults.\n *\n * @param options.table - The table name used for diagnostics, or `null`.\n *\n * @param options.method - The calling method used for diagnostics, or `null`.\n *\n * @param options.parameters - Arguments included in error diagnostics, or `null`.\n *\n * @param options.rowsToLog - Overrides the default number of displayed rows.\n *\n * @param options.returnData - Whether to return converted rows. Defaults to false.\n *\n * @param options.values - DuckDB-native values bound to SQL placeholders, in order.\n *\n * @param options.noClean - Whether to preserve the SQL text without cleaning it.\n *\n * @returns The merged query options without modifying either argument.\n */\nexport default function mergeOptions(\n simple: { rowsToLog: number; charsToLog: number | undefined },\n options: {\n table: string | null;\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n rowsToLog?: number;\n returnData?: boolean;\n values?: DuckDBValue[];\n noClean?: boolean;\n },\n): {\n table: string | null;\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n rowsToLog: number;\n charsToLog: number | undefined;\n returnData: boolean;\n values?: DuckDBValue[];\n noClean?: boolean;\n} {\n return {\n table: options.table,\n method: options.method,\n parameters: options.parameters,\n rowsToLog: options.rowsToLog ?? simple.rowsToLog,\n charsToLog: simple.charsToLog,\n returnData: options.returnData ?? false,\n values: options.values,\n noClean: options.noClean,\n };\n}\n","import type { DuckDBValue as NativeDuckDBValue } from \"@duckdb/node-api\";\nimport SimpleTable from \"../class/SimpleTable.ts\";\nimport SimpleDB from \"../class/SimpleDB.ts\";\nimport cleanSQL from \"./cleanSQL.ts\";\nimport flushAllTables from \"./flushAllTables.ts\";\nimport { recordCacheTableAccess } from \"./cacheTableDependencies.ts\";\n\n/** @internal DuckDB owns this type; retain its exact binding contract without re-exporting it. */\ntype DuckDBValue = NativeDuckDBValue;\n\n/**\n * Executes SQL for a table or database after flushing all queued operations.\n * Starts the database on first use and applies its SQL logging settings.\n * Extension authors can construct `options` with `mergeOptions()`.\n *\n * @example\n * ```ts\n * import { mergeOptions, queryDB, quoteIdentifier } from \"@nshiab/simple-data-analysis-core/helpers\";\n *\n * await table.loadArray([{ answer: 0 }]).run();\n * const query = `UPDATE ${quoteIdentifier(table.name)} SET answer = ?`;\n * await queryDB(table, query, mergeOptions(table, {\n * table: table.name,\n * method: \"example()\",\n * parameters: null,\n * values: [42],\n * }));\n * await table.log();\n * ```\n *\n * @param simple - The table or database that owns the query.\n *\n * @param query - The SQL statement to execute.\n *\n * @param options - Query execution and diagnostic settings.\n *\n * @param options.table - The table name used for diagnostics, or `null`.\n *\n * @param options.method - The calling method used for diagnostics, or `null`.\n *\n * @param options.parameters - Arguments included in error diagnostics, or `null`.\n *\n * @param options.rowsToLog - The caller's row-display limit, retained for compatibility.\n *\n * @param options.charsToLog - The caller's per-cell display limit, retained for compatibility.\n *\n * @param options.returnData - Whether to convert and return the result rows.\n *\n * @param options.values - DuckDB-native values bound to SQL placeholders, in order.\n *\n * @param options.noClean - Whether to preserve the SQL text without cleaning it.\n *\n * @returns Converted rows when `returnData` is true, otherwise `null`.\n */\nexport default async function queryDB(\n simple: SimpleTable | SimpleDB,\n query: string,\n options: {\n table: string | null;\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n rowsToLog: number;\n charsToLog: number | undefined;\n returnData: boolean;\n values?: DuckDBValue[];\n noClean?: boolean;\n },\n): Promise<\n | {\n [key: string]: unknown;\n }[]\n | null\n> {\n if (simple instanceof SimpleTable) {\n recordCacheTableAccess(simple);\n }\n const sdb = simple instanceof SimpleTable ? simple.sdb : simple;\n if (sdb.lifecycleState === \"closed\") {\n throw new Error(`${options.method ?? \"The query\"} cannot run because its SimpleDB is closed.`);\n }\n if (simple instanceof SimpleDB && simple.connection === undefined) {\n await simple.start();\n } else if (simple instanceof SimpleTable && simple.connection === undefined) {\n await simple.sdb.start();\n simple.db = simple.sdb.db;\n simple.connection = simple.sdb.connection;\n }\n if (simple.connection === undefined) {\n throw new Error(\"simple.connection is undefined\");\n }\n\n // Observing executes: any query touching the database first flushes the\n // operations queued by sync builder methods, preserving program order.\n await flushAllTables(simple instanceof SimpleTable ? simple.sdb : simple);\n\n if (options.noClean !== true) {\n query = cleanSQL(query, sdb.expressionSyntax);\n }\n\n const executionOptions = {\n ...options,\n logSQL: sdb.logSQL,\n explainSQL: sdb.explainSQL,\n };\n\n if (options.returnData) {\n const data = await simple.runQuery(query, simple.connection, true, executionOptions);\n if (data === null) {\n throw new Error(\"data is null\");\n }\n return data;\n } else {\n await simple.runQuery(query, simple.connection, false, executionOptions);\n return null;\n }\n}\n","import mergeOptions from \"./mergeOptions.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Loads the spatial extension once per connection, so geospatial operations\n * can fuse as plain SELECT fragments instead of each being multi-statement.\n */\nexport default async function ensureSpatial(simpleTable: SimpleTable): Promise<void> {\n if (simpleTable.sdb.spatialLoaded) {\n return;\n }\n await queryDB(\n simpleTable,\n `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;`,\n mergeOptions(simpleTable, {\n table: null,\n method: null,\n parameters: null,\n }),\n );\n simpleTable.sdb.spatialLoaded = true;\n}\n","export default function extractTypes(\n types:\n | {\n [key: string]: unknown;\n }[]\n | null,\n) {\n const rows = (types ?? []) as {\n column_name: string;\n column_type: string;\n }[];\n // Define own properties so valid names such as __proto__ do not invoke\n // Object.prototype setters in Node.js.\n return Object.fromEntries(\n rows.filter((row) => row.column_name).map((row) => [row.column_name, row.column_type]),\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { FusableOp, PendingOp, RelationalOp, TableSchema } from \"./pendingOps.ts\";\nimport cleanSQL from \"./cleanSQL.ts\";\nimport referencedTables from \"./referencedTables.ts\";\nimport ensureSpatial from \"./ensureSpatial.ts\";\nimport extractTypes from \"./extractTypes.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport { getRegisteredTables } from \"./tableRegistry.ts\";\nimport {\n type AsyncOperationFrame,\n getAsyncOperationFrame,\n isDrainingAsyncOperationFrame,\n type PendingEntry,\n runWhileDrainingAsyncOperationFrame,\n runWithAsyncOperationFrame,\n} from \"./asyncOperationContext.ts\";\n\n/**\n * The databases whose flush is executing on the current async call chain.\n * Queries issued by the flush itself (fused statements, barriers, DESCRIBE)\n * re-enter flushAllTables through queryDB and must not trigger a new flush,\n * while queries from concurrent observers must wait for the in-flight flush\n * instead of reading mid-flush state.\n */\nconst flushContext = new AsyncLocalStorage<Set<SimpleDB>>();\n\n/**\n * Runs `fn` with `sdb` exempt from the top-level flush. Queries issued by an\n * asynchronous barrier can still drain operations queued inside that barrier.\n * Used by the flush itself and by connection setup, whose queries must run\n * before any queued operation.\n */\nexport function runExemptFromFlush<T>(sdb: SimpleDB, fn: () => Promise<T>): Promise<T> {\n const exempt = new Set(flushContext.getStore());\n exempt.add(sdb);\n return flushContext.run(exempt, fn);\n}\n\n/**\n * Executes the pending operations of all tables in program order: every\n * queued operation carries a database-wide sequence number, so operations\n * on different tables replay exactly in the order the user queued them,\n * like immediate execution would. Consecutive fusable operations on the\n * same table compose as CTEs into a single statement; barriers execute\n * in order between fused segments.\n *\n * Every query execution point goes through this (via queryDB). Only one\n * flush runs at a time: concurrent observers wait for the in-flight flush,\n * then flush whatever queued in the meantime, so an awaited observer always\n * answers from fully executed state.\n */\nexport default async function flushAllTables(sdb: SimpleDB): Promise<void> {\n const frame = getAsyncOperationFrame(sdb);\n if (frame !== undefined) {\n if (!isDrainingAsyncOperationFrame(frame)) {\n await drainAsyncOperationFrame(frame);\n }\n return;\n }\n if (flushContext.getStore()?.has(sdb)) {\n // A query issued by the top-level flush itself.\n return;\n }\n while (sdb.flushPromise !== null) {\n // Another observer's flush is running: wait for it instead of reading\n // mid-flush state, then flush anything queued in the meantime.\n try {\n await sdb.flushPromise;\n } catch {\n // The error belongs to the observer that started that flush; this\n // observer only cares that the flush is over.\n }\n }\n if (sdb.pendingCount === 0) {\n return;\n }\n const promise = runExemptFromFlush(sdb, () => flush(sdb));\n sdb.flushPromise = promise;\n try {\n await promise;\n } finally {\n sdb.flushPromise = null;\n }\n}\n\n/**\n * An open run of consecutive fusable operations on one table, accumulated\n * while the flush walks the program-order replay. A segment closes when the\n * replay moves to another table, reaches a barrier or dependency through\n * user-supplied SQL, or reaches the end. Keeping only contiguous operations\n * together preserves database-wide failure order.\n */\ntype Segment = {\n table: SimpleTable;\n ops: RelationalOp[];\n};\n\ntype CompiledCte = {\n alias: string;\n select: string;\n values: import(\"@duckdb/node-api\").DuckDBValue[];\n};\n\ntype CompiledOp = {\n cte: CompiledCte;\n schema: TableSchema | null;\n};\n\nasync function flush(sdb: SimpleDB): Promise<void> {\n // Take ownership of every queue upfront, in program order.\n const entries: PendingEntry[] = [];\n for (const table of getRegisteredTables(sdb)) {\n for (const op of table.pendingOps.splice(0, table.pendingOps.length)) {\n entries.push({ table, op });\n }\n }\n sdb.pendingCount = 0;\n await replayEntries(sdb, entries);\n}\n\nasync function replayEntries(sdb: SimpleDB, pendingEntries: PendingEntry[]): Promise<void> {\n const entries: (PendingEntry | null)[] = [...pendingEntries].sort(\n (a, b) => a.op.sequence - b.op.sequence,\n );\n\n let open: Segment | null = null;\n // The table whose operation is executing, for error attribution: on\n // failure, that table's chain aborts and the other tables' pending work\n // goes back to their queues.\n let executing: SimpleTable | null = null;\n // The entry being dispatched, if it is neither executed nor part of an\n // open segment yet.\n let current: { table: SimpleTable; op: PendingOp } | null = null;\n\n const runOpenSegment = async () => {\n if (open === null) {\n return;\n }\n const segment = open;\n open = null;\n executing = segment.table;\n await runSegment(segment.table, segment.ops);\n executing = null;\n };\n\n let index = 0;\n try {\n for (; index < entries.length; index++) {\n const entry = entries[index]!;\n // Release the reference: a consumed operation (and whatever its\n // closures capture, like loadArray data) must not stay alive for the\n // rest of the flush.\n entries[index] = null;\n current = entry;\n const { table, op } = entry;\n\n if (open !== null && open.table !== table) {\n await runOpenSegment();\n }\n\n if (op.kind === \"barrier\") {\n // A barrier is multi-statement by nature and can read or write any\n // table, so everything pending executes first.\n await runOpenSegment();\n executing = table;\n await op.execute();\n executing = null;\n current = null;\n continue;\n }\n\n if (op.kind === \"asyncBarrier\") {\n // An asynchronous extension barrier also captures and drains builder\n // operations queued by its callback before replay continues.\n await runOpenSegment();\n executing = table;\n await runAsyncBarrier(table, op);\n executing = null;\n current = null;\n continue;\n }\n\n const reads = op.rawSQL === undefined ? [] : referencedTables(op.rawSQL, sdb);\n\n if (op.kind === \"fusable\" && reads.includes(table)) {\n // User-supplied SQL referencing the operation's own table must read\n // the state produced by the previous steps, which a fused chain\n // can't provide (the name would resolve to the pre-chain table). So\n // the chain materializes and the operation runs on its own.\n await runOpenSegment();\n executing = table;\n await runStepwise(table, op);\n executing = null;\n current = null;\n continue;\n }\n\n const sourceSegment: Segment | null = open;\n const segmentSource = sourceSegment?.ops[0];\n if (\n op.kind === \"fusable\" &&\n segmentSource?.kind === \"source\" &&\n (op.requiresMaterializedInput || (op.needsSpatial && segmentSource.schema === undefined))\n ) {\n // Materialize only the external source when this operation needs a\n // stable physical input, or when a spatial operation would otherwise\n // make DuckDB scan an unknown source once for schema inference and\n // again for execution. Earlier transforms remain open and fuse with\n // this operation.\n const source: RelationalOp = segmentSource;\n const pending: RelationalOp[] = sourceSegment?.ops.slice(1) ?? [];\n open = null;\n executing = table;\n await runSegment(table, [source]);\n executing = null;\n open = { table, ops: [...pending, op] };\n current = null;\n continue;\n }\n\n if (op.kind === \"source\") {\n // A source replaces the target table from an external relation. It\n // starts a new segment rather than consuming any segment already open\n // on the same table. A source may read that materialized table itself\n // (for example, an in-place join) and still fuse with downstream steps.\n await runOpenSegment();\n open = { table, ops: [op] };\n current = null;\n continue;\n }\n\n if (open === null) {\n open = { table, ops: [] };\n }\n open.ops.push(op);\n current = null;\n }\n await runOpenSegment();\n } catch (error) {\n // The failing table's chain aborts, like a v1 script stopping at the\n // failing line. The other tables' pending work was queued successfully\n // and goes back to their queues, to execute at their next observation.\n const failing = executing;\n const requeue = (table: SimpleTable, op: PendingOp) => {\n if (table !== failing) {\n table.pendingOps.push(op);\n sdb.pendingCount++;\n }\n };\n if (current !== null) {\n requeue(current.table, current.op);\n }\n if (open !== null) {\n for (const op of open.ops) {\n requeue(open.table, op);\n }\n }\n for (let i = index + 1; i < entries.length; i++) {\n const entry = entries[i];\n if (entry !== null) {\n requeue(entry.table, entry.op);\n }\n }\n throw error;\n }\n}\n\nasync function runAsyncBarrier(\n table: SimpleTable,\n op: Extract<PendingOp, { kind: \"asyncBarrier\" }>,\n): Promise<void> {\n await runWithAsyncOperationFrame(table.sdb, async (frame) => {\n await op.execute();\n await drainAsyncOperationFrame(frame);\n });\n}\n\nasync function drainAsyncOperationFrame(frame: AsyncOperationFrame): Promise<void> {\n while (frame.drainPromise !== null) {\n try {\n await frame.drainPromise;\n } catch {\n // The observer that started the drain receives its failure. A concurrent\n // observer waits for that drain to finish, then handles remaining work.\n }\n }\n if (frame.entries.length === 0) {\n return;\n }\n\n // Start on the next microtask so drainPromise is visible before replay can\n // re-enter user code or another observer can attempt the same drain.\n const promise = Promise.resolve().then(() =>\n runWhileDrainingAsyncOperationFrame(frame, async () => {\n while (frame.entries.length > 0) {\n const entries = frame.entries.splice(0, frame.entries.length);\n await replayEntries(frame.sdb, entries);\n }\n }),\n );\n frame.drainPromise = promise;\n try {\n await promise;\n } finally {\n if (frame.drainPromise === promise) {\n frame.drainPromise = null;\n }\n }\n}\n\nasync function runSegment(table: SimpleTable, ops: RelationalOp[]): Promise<void> {\n if (ops.length === 1) {\n await runStepwise(table, ops[0]);\n return;\n }\n\n if (ops.some(needsSpatial)) {\n await ensureSpatial(table);\n }\n\n // Normalize each fragment once using the database syntax before composition.\n const ctes: CompiledCte[] = [];\n // The schema of the next fragment's input, reused while operations declare\n // they preserve it, so a run of same-shape steps costs at most one\n // DESCRIBE round-trip.\n let schema: TableSchema | null = null;\n for (let i = 0; i < ops.length; i++) {\n const op = ops[i];\n try {\n const compiled = await compileOp(table, op, ctes, schema);\n ctes.push(compiled.cte);\n schema = compiled.schema;\n } catch (error) {\n // Flush-time validation (or a broken earlier fragment surfacing at\n // DESCRIBE) fails the chain at this operation. The steps before it\n // already succeeded in program order, so they execute before the\n // error propagates — like a v1 script failing at this line.\n if (ctes.length > 0) {\n await executeFused(table, ops.slice(0, i), ctes);\n }\n throw error;\n }\n }\n await executeFused(table, ops, ctes);\n}\n\nasync function compileOp(\n table: SimpleTable,\n op: RelationalOp,\n ctes: CompiledCte[],\n schema: TableSchema | null,\n): Promise<CompiledOp> {\n // Source relations can read tables named s1, s2, etc. A generated CTE must\n // not shadow those physical inputs, including in later chain fragments.\n const usedNames = new Set([\n ...getRegisteredTables(table.sdb).map((input) => input.name.toLowerCase()),\n ...ctes.map((cte) => cte.alias),\n ]);\n let aliasIndex = ctes.length + 1;\n while (usedNames.has(`s${aliasIndex}`)) aliasIndex++;\n const alias = `s${aliasIndex}`;\n if (op.kind === \"source\") {\n return {\n cte: {\n alias,\n select: cleanSQL(await op.buildSelect(), table.sdb.expressionSyntax),\n values: [],\n },\n schema: op.schema ?? null,\n };\n }\n\n const input =\n ctes.length === 0 ? quoteIdentifier(table.name) : quoteIdentifier(ctes[ctes.length - 1].alias);\n const inputSchema = op.needsSchema && schema === null ? await describeChain(table, ctes) : schema;\n const buildSchema = inputSchema ?? {};\n const outputSchema =\n inputSchema === null\n ? null\n : op.outputSchema !== undefined\n ? op.outputSchema(inputSchema)\n : op.preservesSchema === true\n ? inputSchema\n : null;\n return {\n cte: {\n alias,\n select: cleanSQL(op.buildSelect(input, buildSchema), table.sdb.expressionSyntax),\n values: resolveValues(op, buildSchema),\n },\n schema: outputSchema,\n };\n}\n\nasync function executeFused(\n table: SimpleTable,\n ops: RelationalOp[],\n ctes: CompiledCte[],\n): Promise<void> {\n // A trailing line comment must end before the generated CTE delimiter.\n const query = `CREATE OR REPLACE TABLE ${quoteIdentifier(table.name)} AS WITH ${ctes\n .map((c) => `${quoteIdentifier(c.alias)} AS (${c.select}\\n)`)\n .join(\", \")} SELECT * FROM ${quoteIdentifier(ctes[ctes.length - 1].alias)}`;\n\n try {\n await queryDB(\n table,\n query,\n mergeOptions(table, {\n table: table.name,\n method: ops.map((op) => op.method).join(\" + \"),\n parameters: Object.fromEntries(\n ops.map((op, i) => [`${i + 1}. ${op.method}`, op.parameters]),\n ),\n values: ctes.flatMap((cte) => cte.values),\n noClean: true,\n }),\n );\n } catch (fusedError) {\n // Re-run the segment step by step to pinpoint the culprit method and\n // report it exactly as immediate execution would have.\n for (const op of ops) {\n await runStepwise(table, op);\n }\n // Every step succeeded on its own: the failure came from the fusion\n // itself. The table now holds the correct stepwise result, so we warn\n // instead of throwing.\n console.warn(\n `The fused query for ${ops\n .map((op) => op.method)\n .join(\n \" + \",\n )} failed, but running the methods one by one succeeded. Please report this as a bug to https://github.com/nshiab/simple-data-analysis-core/issues.\\n${\n fusedError instanceof Error ? fusedError.message : String(fusedError)\n }`,\n );\n }\n}\n\nasync function runStepwise(table: SimpleTable, op: RelationalOp): Promise<void> {\n if (needsSpatial(op)) {\n await ensureSpatial(table);\n }\n // Compilation is shared with the fused path, so both paths execute the same\n // cleaned fragment with the same bound values and schema handling.\n const compiled = await compileOp(table, op, [], null);\n await queryDB(\n table,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(table.name)} AS ${compiled.cte.select}`,\n mergeOptions(table, {\n table: table.name,\n method: op.method,\n parameters: op.parameters,\n values: compiled.cte.values,\n noClean: true,\n }),\n );\n}\n\nfunction needsSpatial(op: RelationalOp): boolean {\n return op.needsSpatial === true;\n}\n\nfunction resolveValues(op: FusableOp, schema: TableSchema) {\n return typeof op.values === \"function\" ? op.values(schema) : (op.values ?? []);\n}\n\n/**\n * Returns the schema at the current point in the fused chain. With no CTEs\n * yet, this describes the table itself; otherwise it describes the output of\n * the last fragment. DESCRIBE is planning-only, so no data is computed.\n */\nasync function describeChain(table: SimpleTable, ctes: CompiledCte[]): Promise<TableSchema> {\n const select =\n ctes.length === 0\n ? `SELECT * FROM ${quoteIdentifier(table.name)}`\n : `WITH ${ctes\n .map((c) => `${quoteIdentifier(c.alias)} AS (${c.select}\\n)`)\n .join(\", \")} SELECT * FROM ${quoteIdentifier(ctes[ctes.length - 1].alias)}`;\n const query =\n ctes.length === 0 ? `DESCRIBE ${quoteIdentifier(table.name)}` : `DESCRIBE ${select}`;\n const values = ctes.flatMap((cte) => cte.values);\n const types = await queryDB(\n table,\n query,\n mergeOptions(table, {\n table: table.name,\n method: null,\n parameters: null,\n returnData: true,\n values,\n noClean: true,\n }),\n );\n return extractTypes(types);\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport referencedTables from \"./referencedTables.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { PendingOp, PendingOpInput } from \"./pendingOps.ts\";\nimport {\n getAsyncOperationFrame,\n runWhileDrainingAsyncOperationFrame,\n} from \"./asyncOperationContext.ts\";\nimport flushAllTables, { runExemptFromFlush } from \"./flushAllTables.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport { getRegisteredTables, retainRegisteredTables } from \"./tableRegistry.ts\";\nimport {\n getTableGeneration,\n peekTableGeneration,\n type TableGenerationId,\n} from \"./tableGeneration.ts\";\n\nexport type CacheTableDependency = {\n tableName: string;\n generationId: TableGenerationId;\n};\n\ntype CacheTableSnapshot = {\n tableName: string;\n generationId: TableGenerationId | undefined;\n};\n\ntype CacheComputation = {\n cachedTable: SimpleTable;\n availableBeforeCompute: Map<SimpleTable, CacheTableSnapshot>;\n accessed: Set<SimpleTable>;\n created: Set<SimpleTable>;\n queued: Set<number>;\n open: boolean;\n};\n\nconst dependencyContext = new AsyncLocalStorage<CacheComputation[]>();\n\n/** Keeps deferred callbacks in their originating cache scope across observers. */\nexport function captureCacheTableOperation(op: PendingOpInput): PendingOpInput {\n if (op.kind === \"barrier\" || op.kind === \"asyncBarrier\") {\n return { ...op, execute: bindCacheContext(op.execute) };\n }\n if (op.kind === \"source\") {\n return { ...op, buildSelect: bindCacheContext(op.buildSelect) };\n }\n return {\n ...op,\n buildSelect: bindCacheContext(op.buildSelect),\n outputSchema: op.outputSchema === undefined ? undefined : bindCacheContext(op.outputSchema),\n values: typeof op.values === \"function\" ? bindCacheContext(op.values) : op.values,\n };\n}\n\nfunction bindCacheContext<Args extends unknown[], Result>(\n callback: (...args: Args) => Result,\n): (...args: Args) => Result {\n // Capture only the cache scope: a snapshot of all AsyncLocalStorage stores\n // would also capture stale flush exemptions and async operation frames.\n // An empty scope keeps unrelated work out of the observer's cache callback.\n const frames = dependencyContext.getStore() ?? [];\n return (...args) => dependencyContext.run(frames, () => callback(...args));\n}\n\n/** Rejects mutations before they can queue work or execute SQL. */\nexport function assertCacheTableMutation(table: SimpleTable): void {\n for (const frame of dependencyContext.getStore() ?? []) {\n if (frame.open && table !== frame.cachedTable && frame.availableBeforeCompute.has(table)) {\n throw new Error(cacheTableMutationMessage(frame.cachedTable, [table.name]));\n }\n }\n}\n\n/** Tracks callback-owned handles so failure cleanup does not touch other work. */\nexport function recordCacheTableCreation(table: SimpleTable): void {\n for (const frame of dependencyContext.getStore() ?? []) {\n if (\n frame.open &&\n table.sdb === frame.cachedTable.sdb &&\n !frame.availableBeforeCompute.has(table)\n ) {\n frame.created.add(table);\n }\n }\n}\n\n/** Tracks queued work across nested callbacks, including async barriers. */\nexport function recordCacheTableOperation(table: SimpleTable, op: PendingOp): void {\n for (const frame of dependencyContext.getStore() ?? []) {\n if (frame.open && table.sdb === frame.cachedTable.sdb) {\n frame.queued.add(op.sequence);\n }\n }\n}\n\n/** Records a table read when a cache computation is observing dependencies. */\nexport function recordCacheTableAccess(table: SimpleTable): void {\n for (const frame of dependencyContext.getStore() ?? []) {\n if (frame.open && table.sdb === frame.cachedTable.sdb) {\n frame.accessed.add(table);\n }\n }\n}\n\n/** Records registered tables named in user-supplied SQL fragments. */\nexport function recordCacheTableReferences(table: SimpleTable, sql: readonly string[]): void {\n if (dependencyContext.getStore() === undefined) {\n return;\n }\n for (const candidate of referencedTables(sql, table.sdb)) {\n recordCacheTableAccess(candidate);\n }\n}\n\n/** Runs a cache computation while collecting the tables it reads. */\nexport async function captureCacheTableDependencies(\n cachedTable: SimpleTable,\n compute: () => Promise<void>,\n): Promise<CacheTableDependency[]> {\n const availableBeforeCompute = new Map(\n getRegisteredTables(cachedTable.sdb).map((table) => [\n table,\n {\n tableName: table.name,\n generationId: peekTableGeneration(table),\n },\n ]),\n );\n const accessed = new Set<SimpleTable>();\n const frame: CacheComputation = {\n cachedTable,\n availableBeforeCompute,\n accessed,\n created: new Set(),\n queued: new Set(),\n open: true,\n };\n try {\n await dependencyContext.run([...(dependencyContext.getStore() ?? []), frame], async () => {\n await compute();\n // A callback can queue a whole computation without observing it.\n // Reject leaked handles before executing that pending computation.\n assertCacheTableCleanup(frame);\n await flushAllTables(cachedTable.sdb);\n // Async barriers may create tables during the final flush.\n assertCacheTableCleanup(frame);\n });\n } catch (error) {\n await cleanupCacheComputation(frame);\n throw error;\n } finally {\n frame.open = false;\n }\n\n return [...accessed]\n .filter((table) => table !== cachedTable && availableBeforeCompute.has(table))\n .map((table) => {\n const snapshot = availableBeforeCompute.get(table);\n if (snapshot === undefined) {\n throw new Error(\"A cache table dependency snapshot is missing.\");\n }\n return {\n tableName: snapshot.tableName,\n generationId: snapshot.generationId ?? getTableGeneration(table),\n };\n })\n .sort((left, right) => left.tableName.localeCompare(right.tableName));\n}\n\nfunction assertCacheTableCleanup(frame: CacheComputation): void {\n const created = getRegisteredTables(frame.cachedTable.sdb).filter((table) =>\n frame.created.has(table),\n );\n if (created.length > 0) {\n throw new Error(cacheTableCleanupMessage(created.map((table) => table.name)));\n }\n}\n\nasync function cleanupCacheComputation(frame: CacheComputation): Promise<void> {\n const sdb = frame.cachedTable.sdb;\n // Drop only this callback's pending operations, preserving other queues and\n // their database-wide ordering. A nested failure also discards work captured\n // by an enclosing async barrier, which is stored outside pendingOps.\n for (const table of getRegisteredTables(sdb)) {\n const retained = table.pendingOps.filter((op) => !frame.queued.has(op.sequence));\n sdb.pendingCount -= table.pendingOps.length - retained.length;\n table.pendingOps.splice(0, table.pendingOps.length, ...retained);\n }\n const operationFrame = getAsyncOperationFrame(sdb);\n if (operationFrame !== undefined) {\n operationFrame.entries = operationFrame.entries.filter(\n (entry) => !frame.queued.has(entry.op.sequence),\n );\n }\n const created = getRegisteredTables(sdb).filter((table) => frame.created.has(table));\n if (created.length === 0) return;\n // Observers inside compute may already have materialized temporary tables.\n // Cleanup must not flush work requeued after an execution error.\n const removeCreatedTables = () =>\n runExemptFromFlush(sdb, async () => {\n for (const table of created) {\n await sdb.customQuery(`DROP TABLE IF EXISTS ${quoteIdentifier(table.name)};`);\n }\n });\n if (operationFrame === undefined) {\n await removeCreatedTables();\n } else {\n // Async frames take precedence over the database-wide flush exemption.\n // Suppress their drain too, without consuming unrelated captured work.\n await runWhileDrainingAsyncOperationFrame(operationFrame, removeCreatedTables);\n }\n retainRegisteredTables(sdb, (table) => !frame.created.has(table));\n}\n\nfunction cacheTableMutationMessage(\n cachedTable: SimpleTable,\n changedTables: readonly string[],\n): string {\n const tables = changedTables.map((name) => JSON.stringify(name)).join(\", \");\n const cachedTableName = JSON.stringify(cachedTable.name);\n if (changedTables.length === 1) {\n return `cache() called on ${cachedTableName} cannot modify pre-existing table ${tables}. Modify ${tables} outside this cache() call.`;\n }\n return `cache() called on ${cachedTableName} cannot modify pre-existing tables ${tables}. Modify these tables outside this cache() call.`;\n}\n\nfunction cacheTableCleanupMessage(createdTables: readonly string[]): string {\n const tables = createdTables.map((name) => JSON.stringify(name)).join(\", \");\n if (createdTables.length === 1) {\n return `cache() created table ${tables} but did not remove it. Call removeTable() on ${tables} before the callback finishes to avoid downstream errors when the cache is loaded and this table is not recreated.`;\n }\n return `cache() created tables ${tables} but did not remove them. Call removeTable() on these tables before the callback finishes to avoid downstream errors when the cache is loaded and these tables are not recreated.`;\n}\n\n/** Checks persisted dependencies against the current registered tables. */\nexport function cacheTableDependenciesMatch(\n cachedTable: SimpleTable,\n dependencies: readonly CacheTableDependency[] | undefined,\n): boolean {\n if (dependencies === undefined) {\n return false;\n }\n const registered = getRegisteredTables(cachedTable.sdb);\n return dependencies.every((dependency) => {\n const table = registered.find((candidate) => candidate.name === dependency.tableName);\n return table !== undefined && getTableGeneration(table) === dependency.generationId;\n });\n}\n\n/** Describes changed or unavailable table dependencies for verbose logging. */\nexport function changedCacheTableDependenciesMessage(\n cachedTable: SimpleTable,\n dependencies: readonly CacheTableDependency[],\n): string {\n const registered = getRegisteredTables(cachedTable.sdb);\n const changed: CacheTableDependency[] = [];\n const unchanged: CacheTableDependency[] = [];\n for (const dependency of dependencies) {\n const table = registered.find((candidate) => candidate.name === dependency.tableName);\n if (table === undefined || getTableGeneration(table) !== dependency.generationId) {\n changed.push(dependency);\n } else {\n unchanged.push(dependency);\n }\n }\n\n return [\n cacheTableDependencyStatusMessage(\"changed\", changed),\n cacheTableDependencyStatusMessage(\"unchanged\", unchanged),\n ]\n .filter((message) => message.length > 0)\n .join(\"\\n\");\n}\n\n/** Lists unchanged dependencies for cache-hit verbose logging. */\nexport function unchangedCacheTableDependenciesMessage(\n dependencies: readonly CacheTableDependency[],\n): string {\n return cacheTableDependencyStatusMessage(\"unchanged\", dependencies);\n}\n\nfunction cacheTableDependencyStatusMessage(\n status: \"changed\" | \"unchanged\",\n dependencies: readonly CacheTableDependency[],\n): string {\n if (dependencies.length === 0) {\n return \"\";\n }\n return `Table dependencies ${status}: ${dependencies\n .map((dependency) => JSON.stringify(dependency.tableName))\n .join(\", \")}.`;\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { markTableChanged } from \"./tableGeneration.ts\";\nimport { recordCacheTableCreation } from \"./cacheTableDependencies.ts\";\nimport foldIdentifier from \"./foldIdentifier.ts\";\n\nconst registries = new WeakMap<object, SimpleTable[]>();\n\nfunction getMutableTables<Table extends SimpleTable>(simpleDB: SimpleDB<Table>): Table[] {\n const tables = registries.get(simpleDB);\n if (tables === undefined) {\n throw new Error(\"The table registry has not been initialized.\");\n }\n return tables as Table[];\n}\n\nexport function initializeTableRegistry<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n): void {\n registries.set(simpleDB, []);\n}\n\nexport function getRegisteredTables<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n): readonly Table[] {\n return getMutableTables(simpleDB);\n}\n\nexport function listRegisteredTables<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n): readonly Table[] {\n return [...getMutableTables(simpleDB)];\n}\n\nexport function registerTable<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n table: Table,\n): void {\n const TableClass = simpleDB.tableClass;\n if (!(table instanceof TableClass)) {\n throw new Error(`The table must be an instance of ${TableClass.name}.`);\n }\n\n const tables = getMutableTables(simpleDB);\n assertTableNameAvailable(simpleDB, table.name);\n tables.push(table);\n recordCacheTableCreation(table);\n}\n\nexport function ensureTableRegistered<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n table: Table,\n): void {\n const tables = getMutableTables(simpleDB);\n if (!tables.includes(table)) {\n registerTable(simpleDB, table);\n }\n}\n\n/** Prevents distinct handles from owning the same DuckDB table name. */\nexport function assertTableNameAvailable(\n simpleDB: SimpleDB,\n name: string,\n renamedTable?: SimpleTable,\n): void {\n const normalizedName = foldIdentifier(name);\n if (\n getRegisteredTables(simpleDB).some(\n (table) => table !== renamedTable && foldIdentifier(table.name) === normalizedName,\n )\n ) {\n throw new Error(`Table ${name} already exists.`);\n }\n}\n\nexport function retainRegisteredTables<Table extends SimpleTable>(\n simpleDB: SimpleDB<Table>,\n predicate: (table: Table) => boolean,\n): void {\n const tables = getMutableTables(simpleDB);\n const retained = tables.filter(predicate);\n const retainedSet = new Set(retained);\n for (const table of tables) {\n if (!retainedSet.has(table)) {\n markTableChanged(table);\n }\n }\n tables.splice(0, tables.length, ...retained);\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { PendingOpInput } from \"./pendingOps.ts\";\nimport { ensureTableRegistered, getRegisteredTables } from \"./tableRegistry.ts\";\nimport { markTableChanged } from \"./tableGeneration.ts\";\nimport {\n assertCacheTableMutation,\n captureCacheTableOperation,\n recordCacheTableOperation,\n recordCacheTableReferences,\n} from \"./cacheTableDependencies.ts\";\nimport { captureAsyncOperation } from \"./asyncOperationContext.ts\";\n\n/**\n * Queues an internal relational operation, barrier, or asynchronous barrier.\n *\n * @internal\n */\nexport default function queueOp(simpleTable: SimpleTable, op: PendingOpInput): void {\n assertCacheTableMutation(simpleTable);\n const sdb = simpleTable.sdb;\n if (sdb.lifecycleState !== \"open\") {\n throw new Error(\n `${op.method} cannot queue work because its SimpleDB is ${sdb.lifecycleState}.`,\n );\n }\n let capturedOp: PendingOpInput = captureCacheTableOperation({\n ...op,\n parameters: op.parameters === null ? null : structuredClone(op.parameters),\n });\n if (capturedOp.kind === \"fusable\" || capturedOp.kind === \"source\") {\n capturedOp = {\n ...capturedOp,\n rawSQL: capturedOp.rawSQL === undefined ? undefined : [...capturedOp.rawSQL],\n };\n if (capturedOp.rawSQL !== undefined) {\n recordCacheTableReferences(simpleTable, capturedOp.rawSQL);\n }\n }\n if (\n capturedOp.kind === \"fusable\" &&\n capturedOp.values !== undefined &&\n typeof capturedOp.values !== \"function\"\n ) {\n capturedOp = {\n ...capturedOp,\n values: [...capturedOp.values],\n };\n }\n // A table de-registered by removeTable()/removeTables()/selectTables() that\n // queues new work comes back under the flush's responsibility, like v1\n // methods recreating a removed table.\n ensureTableRegistered(sdb, simpleTable);\n markTableChanged(simpleTable);\n const queuedOp = {\n ...capturedOp,\n sequence: sdb.opSequence++,\n };\n recordCacheTableOperation(simpleTable, queuedOp);\n if (captureAsyncOperation(sdb, { table: simpleTable, op: queuedOp })) {\n return;\n }\n simpleTable.pendingOps.push(queuedOp);\n sdb.pendingCount++;\n}\n\n/**\n * Empties every table's pending queue without executing it and returns what\n * was dropped, so close() can report forgotten work after cleaning up.\n */\nexport function discardAllPending(sdb: SimpleDB): { table: SimpleTable; methods: string[] }[] {\n const discarded: { table: SimpleTable; methods: string[] }[] = [];\n for (const table of getRegisteredTables(sdb)) {\n if (table.pendingOps.length > 0) {\n discarded.push({\n table,\n methods: table.pendingOps.map((op) => op.method),\n });\n sdb.pendingCount -= table.pendingOps.length;\n table.pendingOps.length = 0;\n }\n }\n return discarded;\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\n\n// For internal queries returning a single numeric value, such as row counts.\nexport default async function readScalarNumber(connection: DuckDBConnection, sql: string) {\n return Number((await connection.runAndReadAll(sql)).getRowsJS()[0][0]);\n}\n","/**\n * Build a DOUBLE-precision distance expression for prepared vector aliases.\n * Cosine callers first stabilize their private rows with stabilizeCosineVectors.\n */\nexport default function vectorDistanceExpression(\n left: string,\n right: string,\n metric: \"euclidean\" | \"cosine\",\n): string {\n if (metric === \"euclidean\") return `array_distance(${left},${right})`;\n // DuckDB can return tiny positive or negative errors for equal/cosine-aligned\n // vectors. Exact equality also makes duplicate behavior deterministic.\n return `CASE WHEN ${left}=${right} THEN 0 ELSE greatest(0,array_cosine_distance(${left},${right})) END`;\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\nimport readScalarNumber from \"./readScalarNumber.ts\";\n\n/**\n * Stabilizes cosine arithmetic in a caller-owned private vector relation.\n * The already-quoted relation has unique vertex ids and a fixed-size DOUBLE\n * vec column. Source data must be retained separately by the caller.\n *\n * Safe vectors keep their existing arithmetic and tie behavior. Outside the\n * safe range, divide by the largest absolute component, then by the resulting\n * length. This preserves direction without overflowing or underflowing norms.\n * The bounds keep squared-norm products between 1e-300 and 1e300, with room\n * for rounding. Only the private vec column changes; no scratch tables remain.\n */\nexport default async function stabilizeCosineVectors(\n connection: DuckDBConnection,\n rows: string,\n): Promise<void> {\n if (\n await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${rows} WHERE vec IS NULL\n OR len(vec)=0 OR list_count(vec)!=len(vec)\n OR NOT list_bool_and(list_transform(vec, value -> isfinite(value)))\n OR list_max(list_transform(vec, value -> abs(value)))=0`,\n )\n ) {\n throw new Error(\"Cosine distance requires finite, non-null values and nonzero vectors.\");\n }\n await connection.run(`WITH magnitudes AS MATERIALIZED (\n SELECT vertex,vec,list_max(list_transform(vec, value -> abs(value))) AS magnitude\n FROM ${rows}\n ), scaled AS MATERIALIZED (\n SELECT vertex,list_transform(vec, value -> value / magnitude) AS vec\n FROM magnitudes\n WHERE magnitude < 1e-75 OR magnitude > 1e75 / sqrt(len(vec))\n ), lengths AS MATERIALIZED (\n SELECT vertex,vec,sqrt(list_sum(list_transform(vec, value -> value * value))) AS norm\n FROM scaled\n )\n UPDATE ${rows} AS target SET vec=cast_to_type(\n list_transform(lengths.vec, value -> value / lengths.norm),target.vec)\n FROM lengths WHERE target.vertex=lengths.vertex`);\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\n\n/** Validate the positional identity contract before bounded vector scans. */\nexport default async function validateVectorRowIds(\n connection: DuckDBConnection,\n rows: string,\n count: number,\n): Promise<void> {\n // Graph state and DuckDB scratch schemas use signed INTEGER vertex ids.\n if (!Number.isSafeInteger(count) || count < 1 || count > 2147483647) {\n throw new Error(\"Vector row count must fit a positive INTEGER vertex count.\");\n }\n const [actual, distinct, minimum, maximum, invalid] = (\n await connection.runAndReadAll(`SELECT count(*),count(DISTINCT vertex),\n min(vertex),max(vertex),count(*) FILTER (\n WHERE vertex IS NULL OR vertex!=trunc(vertex)) FROM ${rows}`)\n ).getRowsJS()[0];\n if (\n Number(actual) !== count ||\n Number(distinct) !== count ||\n Number(minimum) !== 0 ||\n Number(maximum) !== count - 1 ||\n Number(invalid) !== 0\n ) {\n throw new Error(\n `Vector rows must contain exactly ${count} unique integer vertex ids from 0 to ${count - 1}.`,\n );\n }\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\nimport readScalarNumber from \"./readScalarNumber.ts\";\nimport vectorDistanceExpression from \"./vectorDistanceExpression.ts\";\nimport stabilizeCosineVectors from \"./stabilizeCosineVectors.ts\";\nimport validateVectorRowIds from \"./validateVectorRowIds.ts\";\n\n/** Private, already-quoted relation names owned and cleaned up by the caller. */\nexport type VectorNeighborTables = {\n rows: string;\n neighbors: string;\n search: string;\n hnsw: string;\n candidates: string;\n};\n\ntype NeighborInput = {\n count: number;\n dimensions: number;\n neighborCount: number;\n};\n\ntype NeighborOptions = {\n metric: \"euclidean\" | \"cosine\";\n search: \"exact\" | \"hnsw\";\n includeSelf: boolean;\n hnsw?: {\n efConstruction: number;\n efSearch: number;\n connectivity: number;\n candidateCount: number;\n singleThreaded: boolean;\n cosineAsL2: boolean;\n };\n};\n\n/**\n * Materialize ranked vector neighbors without moving source vectors into JS.\n *\n * `neighborCount` is the number of rows produced per source. When `includeSelf`\n * is true, the source is rank 0 and consumes one of those rows. Otherwise all\n * rows are other points. Ranks are zero-based and ties use target id order.\n * Input rows have unique contiguous `vertex` ids from 0 through count-1 and\n * validated, non-null, fixed-size DOUBLE `vec` values. Cosine preparation may\n * rescale this private vec column, preserving direction.\n *\n * The caller owns every supplied scratch relation and must drop them after\n * success or failure. Approximate search only approximates candidate retrieval;\n * candidate distances are recomputed from the DOUBLE source vectors before\n * stable final ranking.\n */\nexport default async function buildVectorNeighbors(\n connection: DuckDBConnection,\n input: NeighborInput,\n options: NeighborOptions,\n names: VectorNeighborTables,\n): Promise<void> {\n const { count, dimensions, neighborCount } = input;\n await validateVectorRowIds(connection, names.rows, count);\n if (!Number.isSafeInteger(dimensions) || dimensions < 1) {\n throw new Error(\"Vector dimensions must be a positive safe integer.\");\n }\n const maximum = count - (options.includeSelf ? 0 : 1);\n if (!Number.isSafeInteger(neighborCount) || neighborCount < 1 || neighborCount > maximum) {\n throw new Error(`Neighbor count must be a safe integer between 1 and ${maximum}.`);\n }\n if (options.metric === \"cosine\") {\n await stabilizeCosineVectors(connection, names.rows);\n }\n // FLOAT representation limits apply only to the HNSW search vectors.\n // Exact Euclidean distance does not require representable squared norms.\n if (options.search === \"hnsw\") {\n const normExpression = `array_inner_product(vec::FLOAT[${dimensions}],vec::FLOAT[${dimensions}])`;\n if (\n await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${names.rows} WHERE NOT isfinite(${normExpression})\n ${options.metric === \"cosine\" ? `OR ${normExpression}=0` : \"\"}`,\n )\n ) {\n throw new Error(\"HNSW requires vectors with finite FLOAT norms (and nonzero cosine norms).\");\n }\n }\n\n const distanceFunction = options.metric === \"cosine\" ? \"array_cosine_distance\" : \"array_distance\";\n // Equal vectors must have exactly zero cosine distance. Positive roundoff can\n // otherwise alter downstream density estimates. Clamp negative roundoff too.\n const exactDistance = vectorDistanceExpression(\"a.vec\", \"b.vec\", options.metric);\n const otherCount = neighborCount - (options.includeSelf ? 1 : 0);\n\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.candidates}\n (source INTEGER, target INTEGER, distance DOUBLE)`);\n if (otherCount > 0) {\n if (options.search === \"exact\") {\n // O(n²d) work with a bounded source batch and top-k heaps. The full\n // distance matrix is never materialized.\n await buildExactCandidates(connection, input, names, exactDistance, otherCount);\n } else {\n await buildHnswCandidates(\n connection,\n input,\n options,\n names,\n distanceFunction,\n exactDistance,\n otherCount,\n );\n }\n }\n\n if (\n await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${names.candidates} WHERE distance IS NULL OR NOT isfinite(distance)`,\n )\n ) {\n throw new Error(\"Distance computation returned a non-finite value.\");\n }\n\n const selfRows = options.includeSelf\n ? `SELECT vertex AS source,vertex AS target,0::DOUBLE AS distance FROM ${names.rows}`\n : \"SELECT NULL::INTEGER AS source,NULL::INTEGER AS target,NULL::DOUBLE AS distance WHERE false\";\n const rankOrder = options.includeSelf\n ? \"CASE WHEN source=target THEN 0 ELSE 1 END,distance,target\"\n : \"distance,target\";\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.neighbors} AS\n SELECT source,target,\n (row_number() OVER (PARTITION BY source ORDER BY ${rankOrder})-1)::INTEGER AS rank,\n greatest(0,distance)::DOUBLE AS distance\n FROM (${selfRows} UNION ALL\n SELECT source,target,distance FROM ${names.candidates})\n QUALIFY row_number() OVER (PARTITION BY source ORDER BY ${rankOrder})\n <= ${neighborCount}`);\n\n const produced = await readScalarNumber(connection, `SELECT count(*) FROM ${names.neighbors}`);\n if (produced !== count * neighborCount) {\n throw new Error(\n `Neighbor search returned ${produced} rows; ${count * neighborCount} were required.`,\n );\n }\n if (\n await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${names.neighbors} WHERE NOT isfinite(distance)`,\n )\n ) {\n throw new Error(\"Distance computation returned a non-finite value.\");\n }\n}\n\nasync function buildHnswCandidates(\n connection: DuckDBConnection,\n input: NeighborInput,\n options: NeighborOptions,\n names: VectorNeighborTables,\n distanceFunction: string,\n exactDistance: string,\n otherCount: number,\n): Promise<void> {\n const { count, dimensions, neighborCount } = input;\n const settings = options.hnsw;\n const cosineAsL2 = options.metric === \"cosine\" && settings?.cosineAsL2;\n // Euclidean distance on unit vectors has the same mathematical ordering as\n // cosine. Computing differences avoids FLOAT dot-product cancellation for\n // near-collinear vectors; final metric distances still use source DOUBLEs.\n const searchVector = cosineAsL2\n ? \"list_transform(vec,x -> x/sqrt(array_inner_product(vec,vec)))\"\n : \"vec\";\n const previousThreads = Number(\n (await connection.runAndReadAll(\"SELECT current_setting('threads')\")).getRowsJS()[0][0],\n );\n try {\n if (settings?.singleThreaded) await connection.run(\"SET threads=1\");\n await connection.run(`INSTALL vss; LOAD vss;\n CREATE OR REPLACE TEMP TABLE ${names.search} AS\n SELECT vertex,${searchVector}::FLOAT[${dimensions}] AS vec\n FROM ${names.rows} ORDER BY vertex;\n CREATE INDEX ${names.hnsw} ON ${names.search} USING HNSW(vec)\n WITH (metric='${options.metric === \"cosine\" && !cosineAsL2 ? \"cosine\" : \"l2sq\"}',\n ef_construction=${settings?.efConstruction ?? 128},\n ef_search=${settings?.efSearch ?? 128},M=${settings?.connectivity ?? 16})`);\n } finally {\n if (settings?.singleThreaded) {\n await connection.run(`SET threads=${previousThreads}`);\n }\n }\n const previous = (\n await connection.runAndReadAll(\"SELECT current_setting('disabled_optimizers')\")\n ).getRowsJS()[0][0];\n if (typeof previous !== \"string\") throw new Error(\"Expected disabled_optimizers to be a string.\");\n const disabled = [\n ...new Set([...previous.split(\",\").filter(Boolean), \"top_n_window_elimination\"]),\n ].join(\",\");\n try {\n await connection.run(`SET disabled_optimizers='${disabled.replaceAll(\"'\", \"''\")}'`);\n // Preserve UMAP's established candidate budget when self is included.\n // Excluding self needs one extra result because HNSW normally returns it.\n const candidateCount =\n settings?.candidateCount ??\n (options.includeSelf\n ? Math.max(otherCount + 1, Math.min(neighborCount + 1, count - 1))\n : Math.min(otherCount + 1, count));\n const candidateDistanceFunction = cosineAsL2 ? \"array_distance\" : distanceFunction;\n const query = `SELECT a.vertex AS source,b.vertex AS target,b.distance\n FROM ${names.search} a,LATERAL (\n SELECT vertex,${candidateDistanceFunction}(vec,a.vec) AS distance\n FROM ${names.search} ORDER BY distance LIMIT ${candidateCount}\n ) b`;\n // Carry ids and scalar distances through the candidate relation. Recompute\n // in DOUBLE against source rows to isolate ANN retrieval from precision.\n const candidates = `SELECT q.source,q.target,${exactDistance} AS distance\n FROM (${query}) q JOIN ${names.rows} a ON q.source=a.vertex\n JOIN ${names.rows} b ON q.target=b.vertex WHERE q.source != q.target`;\n const plan = JSON.stringify(\n (await connection.runAndReadAll(`EXPLAIN ${candidates}`)).getRowsJS(),\n );\n if (!plan.includes(\"HNSW_INDEX_JOIN\")) {\n if (count <= 1000) {\n return await buildExactCandidates(connection, input, names, exactDistance, otherCount);\n }\n throw new Error(\"DuckDB could not use its vector index for neighbor search.\");\n }\n await connection.run(`INSERT INTO ${names.candidates} ${candidates}`);\n } finally {\n await connection.run(`SET disabled_optimizers='${previous.replaceAll(\"'\", \"''\")}'`);\n }\n}\n\nasync function buildExactCandidates(\n connection: DuckDBConnection,\n input: NeighborInput,\n names: VectorNeighborTables,\n exactDistance: string,\n otherCount: number,\n): Promise<void> {\n for (let offset = 0; offset < input.count; offset += 32) {\n const query = `SELECT source,item.target,item.distance FROM (\n SELECT a.vertex AS source,\n CASE WHEN bool_and(isfinite(${exactDistance})) THEN\n min_by(struct_pack(target := b.vertex,distance := ${exactDistance}),\n struct_pack(distance := ${exactDistance},target := b.vertex),\n ${otherCount}) ELSE error('Distance computation returned a non-finite value.') END AS closest\n FROM ${names.rows} a CROSS JOIN ${names.rows} b\n WHERE a.vertex >= ${offset} AND a.vertex < ${offset + 32}\n AND a.vertex != b.vertex GROUP BY a.vertex\n ),UNNEST(closest) AS t(item)`;\n await connection.run(`INSERT INTO ${names.candidates} ${query}`);\n }\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\nimport readScalarNumber from \"./readScalarNumber.ts\";\nimport buildVectorNeighbors, { type VectorNeighborTables } from \"./buildVectorNeighbors.ts\";\n\n// All relation names are private, already-quoted SQL identifiers supplied by\n// the owning UMAP operation. No input vectors cross the JS boundary.\nexport type UmapTables = Omit<VectorNeighborTables, \"neighbors\"> & {\n knn: string;\n scales: string;\n directed: string;\n graph: string;\n};\n\nexport default async function buildUmapGraph(\n connection: DuckDBConnection,\n input: { count: number; dimensions: number; neighbors: number },\n options: { metric: \"euclidean\" | \"cosine\"; search: \"exact\" | \"hnsw\" },\n names: UmapTables,\n) {\n await buildVectorNeighbors(\n connection,\n {\n count: input.count,\n dimensions: input.dimensions,\n neighborCount: input.neighbors,\n },\n { ...options, includeSelf: true },\n { ...names, neighbors: names.knn },\n );\n await buildFuzzyGraph(connection, input.neighbors, names);\n const edges = await readScalarNumber(connection, `SELECT count(*) FROM ${names.graph}`);\n const source = new Uint32Array(edges),\n target = new Uint32Array(edges),\n weight = new Float64Array(edges);\n const rows = await connection.stream(\n `SELECT source,target,weight FROM ${names.graph} ORDER BY source,target`,\n );\n let edge = 0;\n while (true) {\n const chunk = await rows.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n chunk.visitColumnValues(0, (value, row) => (source[edge + row] = Number(value)));\n chunk.visitColumnValues(1, (value, row) => (target[edge + row] = Number(value)));\n chunk.visitColumnValues(2, (value, row) => (weight[edge + row] = Number(value)));\n edge += chunk.rowCount;\n }\n if (edge !== edges) throw new Error(\"Graph changed during transfer.\");\n return { source, target, weight };\n}\n\nasync function buildFuzzyGraph(connection: DuckDBConnection, neighbors: number, names: UmapTables) {\n // Smooth-kNN with local_connectivity=1, bandwidth=1, 64 bisection steps,\n // tolerance 1e-5 and the reference's 1e-3 minimum-distance scale.\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.scales} AS\n SELECT source, coalesce(min(distance) FILTER(WHERE distance>0),0) AS rho,\n avg(distance) AS mean_distance, 0::DOUBLE AS lo, 'Infinity'::DOUBLE AS hi,\n 1::DOUBLE AS sigma, false AS done FROM ${names.knn} GROUP BY source`);\n for (let iteration = 0; iteration < 64; iteration++) {\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.scales} AS\n WITH sums AS (\n SELECT s.*, (SELECT sum(CASE WHEN n.distance <= s.rho THEN 1\n ELSE exp(-(n.distance-s.rho)/s.sigma) END)\n FROM ${names.knn} n WHERE n.source=s.source AND n.target != n.source) AS mass\n FROM ${names.scales} s\n ), bounds AS (\n SELECT * EXCLUDE(lo,hi,done),\n CASE WHEN NOT done AND mass < log2(${neighbors}) THEN sigma ELSE lo END AS lo,\n CASE WHEN NOT done AND mass > log2(${neighbors}) THEN sigma ELSE hi END AS hi,\n done OR abs(mass-log2(${neighbors})) < 1e-5 AS done FROM sums\n ) SELECT source,rho,mean_distance,lo,hi,\n CASE WHEN done THEN sigma WHEN isinf(hi) THEN sigma*2 ELSE (lo+hi)/2 END AS sigma,\n done FROM bounds`);\n }\n await connection.run(`UPDATE ${names.scales} SET sigma=greatest(sigma,0.001 *\n CASE WHEN rho>0 THEN mean_distance ELSE (SELECT avg(distance) FROM ${names.knn}) END);\n CREATE OR REPLACE TEMP TABLE ${names.directed} AS\n SELECT n.source,n.target,CASE WHEN n.distance<=s.rho OR s.sigma=0 THEN 1\n ELSE exp(-(n.distance-s.rho)/s.sigma) END AS weight\n FROM ${names.knn} n JOIN ${names.scales} s USING(source) WHERE n.source != n.target;\n CREATE OR REPLACE TEMP TABLE ${names.graph} AS\n SELECT coalesce(a.source,b.target) AS source, coalesce(a.target,b.source) AS target,\n coalesce(a.weight,0)+coalesce(b.weight,0)-coalesce(a.weight*b.weight,0) AS weight\n FROM ${names.directed} a FULL OUTER JOIN ${names.directed} b\n ON a.source=b.target AND a.target=b.source`);\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport foldIdentifier from \"./foldIdentifier.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nconst NUMERIC_SCALAR_TYPE =\n /^(?:TINYINT|SMALLINT|INTEGER|BIGINT|HUGEINT|UTINYINT|USMALLINT|UINTEGER|UBIGINT|UHUGEINT|BIGNUM|FLOAT|REAL|DOUBLE|DECIMAL\\(\\d+,\\d+\\))$/;\n\n/** Returns whether a DuckDB type is a scalar numeric type. */\nexport function isNumericScalarType(type: string): boolean {\n return NUMERIC_SCALAR_TYPE.test(type);\n}\n\nexport type NumericFeatureInput =\n | { kind: \"scalars\"; columns: string[] }\n | { kind: \"vector\"; column: string };\n\nexport type PreparedNumericFeatures = {\n /** Raw temporary-relation name. Quote it before embedding it in SQL. */\n relation: string;\n /** Raw private row-identity column name. */\n rowIdColumn: string;\n /** Raw private `DOUBLE[d]` feature column name. */\n vectorColumn: string;\n dimensions: number;\n rowCount: number;\n /** Source column names in their original order and spelling. */\n sourceColumns: string[];\n sourceTemporary: boolean;\n /** Drops all scratch state owned by this preparation. Safe to call twice. */\n cleanup: () => Promise<void>;\n};\n\n/**\n * Prepares scalar columns or a vector column as a private `DOUBLE[d]` feature\n * vector while retaining every source column in DuckDB. Converting large\n * integers or exact decimals to DOUBLE can lose precision. The source columns\n * remain unchanged, so callers can publish results from the returned snapshot.\n *\n * The private row identity is positional and distinguishes duplicate rows. A\n * caller owns the returned relation and must invoke `cleanup()` in `finally`.\n * Preparation failures clean up their own scratch state.\n */\nexport default async function prepareNumericFeatures(\n table: SimpleTable,\n input: NumericFeatureInput,\n options: {\n method: string;\n rejectNulls?: boolean;\n rejectNonFinite?: boolean;\n },\n): Promise<PreparedNumericFeatures> {\n const rejectNulls = options.rejectNulls ?? true;\n const rejectNonFinite = options.rejectNonFinite ?? true;\n const types = await table.getTypes();\n // Object.keys(types) sorts integer-like identifiers, which would reorder\n // source columns when algorithms publish from this snapshot.\n const sourceColumns = await table.getColumns();\n const resolveColumn = (requested: string): string => {\n const resolved = sourceColumns.find(\n (column) => foldIdentifier(column) === foldIdentifier(requested),\n );\n if (resolved === undefined) {\n throw new Error(\n `${options.method} could not find column ${quoteIdentifier(\n requested,\n )}. Available columns: ${sourceColumns.map(quoteIdentifier).join(\", \")}.`,\n );\n }\n return resolved;\n };\n\n let selectedColumns: string[];\n let vectorType: { elementType: string; fixedDimensions?: number } | undefined;\n if (input.kind === \"scalars\") {\n if (input.columns.length === 0) {\n throw new Error(`${options.method} requires at least one numeric scalar column.`);\n }\n const duplicate = findDuplicate(input.columns);\n if (duplicate !== undefined) {\n throw new Error(\n `${options.method} received duplicate input column ${quoteIdentifier(\n duplicate,\n )}. Each numeric feature column must be listed once.`,\n );\n }\n selectedColumns = input.columns.map(resolveColumn);\n const nonNumeric = selectedColumns.filter((column) => !isNumericScalarType(types[column]));\n if (nonNumeric.length > 0) {\n throw new Error(\n `${options.method} requires numeric scalar columns. The following input columns are not numeric scalars: ${nonNumeric\n .map((column) => `${quoteIdentifier(column)} (${types[column]})`)\n .join(\", \")}. Convert them to numeric scalar types first.`,\n );\n }\n } else {\n const column = resolveColumn(input.column);\n selectedColumns = [column];\n vectorType = parseNumericVectorType(types[column]);\n if (vectorType === undefined) {\n throw new Error(\n `${options.method} requires a one-dimensional numeric LIST or ARRAY column, but ${quoteIdentifier(\n column,\n )} has type ${types[column]}.`,\n );\n }\n }\n\n const connection = table.connection!;\n const source = quoteIdentifier(table.name);\n const suffix = crypto.randomUUID().replaceAll(\"-\", \"\");\n const relation = `__sda_features_${suffix}`;\n const rowIdColumn = `__sda_row_${suffix}`;\n const vectorColumn = `__sda_vector_${suffix}`;\n const preparedRelation = quoteIdentifier(relation);\n let cleaned = false;\n const cleanup = async () => {\n if (cleaned) return;\n await connection.run(`DROP TABLE IF EXISTS ${preparedRelation}`);\n cleaned = true;\n };\n\n try {\n const tableDetails = (\n await connection.runAndReadAll(\n `SELECT table_oid, temporary FROM duckdb_tables()\n WHERE translate(table_name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = $1\n AND schema_name = current_schema()\n AND database_name IN (current_database(), 'temp')\n ORDER BY temporary DESC LIMIT 1`,\n [foldIdentifier(table.name)],\n )\n ).getRowsJS()[0];\n if (tableDetails === undefined) {\n throw new Error(`${options.method} requires a materialized source table.`);\n }\n const sourceTemporary = Boolean(tableDetails[1]);\n const rowCount = Number(\n (await connection.runAndReadAll(`SELECT count(*) FROM ${source}`)).getRowsJS()[0][0],\n );\n\n let dimensions: number;\n let vectorExpression: string;\n if (input.kind === \"scalars\") {\n dimensions = selectedColumns.length;\n await rejectInvalidScalarRows(connection, source, selectedColumns, types, options.method, {\n rejectNulls,\n rejectNonFinite,\n });\n vectorExpression = `[${selectedColumns\n .map((column) => castToDouble(quoteIdentifier(column), types[column]))\n .join(\", \")}]::DOUBLE[${dimensions}]`;\n } else {\n const column = selectedColumns[0];\n const quotedColumn = quoteIdentifier(column);\n const emptyRows = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(*) FROM ${source}\n WHERE ${quotedColumn} IS NOT NULL AND len(${quotedColumn}) = 0`,\n )\n ).getRowsJS()[0][0],\n );\n if (emptyRows > 0) {\n throw new Error(\n `${options.method} found ${emptyRows} row${\n emptyRows === 1 ? \"\" : \"s\"\n } with an empty vector in column ${quoteIdentifier(\n column,\n )}. Vectors must have a nonzero dimension.`,\n );\n }\n await rejectInvalidVectorRows(\n connection,\n source,\n column,\n vectorType!.elementType,\n options.method,\n { rejectNulls, rejectNonFinite },\n );\n\n if (vectorType?.fixedDimensions !== undefined) {\n dimensions = vectorType.fixedDimensions;\n } else {\n const dimensionRows = (\n await connection.runAndReadAll(\n `SELECT len(${quotedColumn}) AS dimensions\n FROM ${source} WHERE ${quotedColumn} IS NOT NULL LIMIT 1`,\n )\n ).getRowsJS();\n if (dimensionRows.length === 0) {\n throw new Error(\n `${options.method} could not determine a vector dimension for ${quoteIdentifier(\n column,\n )}. Provide at least one non-null, nonempty vector.`,\n );\n }\n dimensions = Number(dimensionRows[0][0]);\n }\n\n const distinctDimensions = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(DISTINCT len(${quotedColumn})) FROM ${source}\n WHERE ${quotedColumn} IS NOT NULL`,\n )\n ).getRowsJS()[0][0],\n );\n if (distinctDimensions > 1) {\n throw new Error(\n `${options.method} requires vectors with equal dimensions, but column ${quoteIdentifier(\n column,\n )} contains ${distinctDimensions} different lengths.`,\n );\n }\n vectorExpression =\n vectorType!.elementType === \"BIGNUM\"\n ? `list_transform(${quotedColumn}, value -> ${castToDouble(\n \"value\",\n \"BIGNUM\",\n )})::DOUBLE[${dimensions}]`\n : `${quotedColumn}::DOUBLE[${dimensions}]`;\n }\n\n await connection.run(\n `CREATE TEMP TABLE ${preparedRelation} AS\n SELECT *, row_number() OVER () - 1 AS ${quoteIdentifier(\n rowIdColumn,\n )}, ${vectorExpression} AS ${quoteIdentifier(vectorColumn)}\n FROM ${source}`,\n );\n\n return {\n relation,\n rowIdColumn,\n vectorColumn,\n dimensions,\n rowCount,\n sourceColumns,\n sourceTemporary,\n cleanup,\n };\n } catch (error) {\n await cleanup();\n throw error;\n }\n}\n\nfunction parseNumericVectorType(\n type: string,\n): { elementType: string; fixedDimensions?: number } | undefined {\n const match = /^(.+)\\[(\\d*)\\]$/.exec(type);\n if (match === null || !isNumericScalarType(match[1])) return undefined;\n const elementType = match[1];\n if (match[2] === \"\") return { elementType };\n const fixedDimensions = Number(match[2]);\n return fixedDimensions > 0 ? { elementType, fixedDimensions } : undefined;\n}\n\nfunction findDuplicate(columns: string[]): string | undefined {\n const seen = new Set<string>();\n for (const column of columns) {\n const folded = foldIdentifier(column);\n if (seen.has(folded)) return column;\n seen.add(folded);\n }\n return undefined;\n}\n\nasync function rejectInvalidScalarRows(\n connection: SimpleTable[\"connection\"],\n source: string,\n columns: string[],\n types: { [column: string]: string },\n method: string,\n validation: { rejectNulls: boolean; rejectNonFinite: boolean },\n) {\n const predicates = columns.map((column) => {\n const value = quoteIdentifier(column);\n const converted = castToDouble(value, types[column], true);\n const checks: string[] = [];\n if (validation.rejectNulls) checks.push(`${value} IS NULL`);\n if (validation.rejectNonFinite) {\n checks.push(\n `(${value} IS NOT NULL AND (${converted} IS NULL OR NOT isfinite(${converted})))`,\n );\n }\n return checks.length === 0 ? \"FALSE\" : `(${checks.join(\" OR \")})`;\n });\n if (predicates.every((predicate) => predicate === \"FALSE\")) return;\n const aliases = columns.map((_, index) => `invalid_${index}`);\n const query = `SELECT\n count(*) FILTER (WHERE ${predicates.join(\" OR \")}) AS invalid_rows,\n ${predicates\n .map((predicate, index) => `count(*) FILTER (WHERE ${predicate}) AS ${aliases[index]}`)\n .join(\", \")}\n FROM ${source}`;\n const row = (await connection.runAndReadAll(query)).getRowsJS()[0];\n const invalidRows = Number(row[0]);\n if (invalidRows === 0) return;\n const affected = columns.flatMap((column, index) => {\n const count = Number(row[index + 1]);\n return count === 0\n ? []\n : [`${quoteIdentifier(column)} (${count} row${count === 1 ? \"\" : \"s\"})`];\n });\n throw new Error(\n `${method} requires finite, non-null numeric features. Found ${invalidRows} invalid row${\n invalidRows === 1 ? \"\" : \"s\"\n }. Affected columns: ${affected.join(\", \")}.`,\n );\n}\n\nasync function rejectInvalidVectorRows(\n connection: SimpleTable[\"connection\"],\n source: string,\n column: string,\n elementType: string,\n method: string,\n validation: { rejectNulls: boolean; rejectNonFinite: boolean },\n) {\n const vector = quoteIdentifier(column);\n const checks: string[] = [];\n if (validation.rejectNulls) {\n checks.push(`${vector} IS NULL`);\n checks.push(`(${vector} IS NOT NULL AND list_count(${vector}) != len(${vector}))`);\n }\n if (validation.rejectNonFinite) {\n checks.push(\n `(${vector} IS NOT NULL AND COALESCE(NOT list_bool_and(list_transform(${vector}, value -> value IS NULL OR COALESCE(isfinite(${castToDouble(\n \"value\",\n elementType,\n true,\n )}), FALSE))), FALSE))`,\n );\n }\n if (checks.length === 0) return;\n const invalidRows = Number(\n (\n await connection.runAndReadAll(`SELECT count(*) FROM ${source} WHERE ${checks.join(\" OR \")}`)\n ).getRowsJS()[0][0],\n );\n if (invalidRows === 0) return;\n throw new Error(\n `${method} requires finite, non-null vector values. Column ${quoteIdentifier(\n column,\n )} has ${invalidRows} invalid row${invalidRows === 1 ? \"\" : \"s\"}.`,\n );\n}\n\n/** BIGNUM's direct DOUBLE conversion can throw even inside DuckDB TRY_CAST. */\nfunction castToDouble(value: string, type: string, tryCast = false): string {\n const convertible = type === \"BIGNUM\" ? `CAST(${value} AS VARCHAR)` : value;\n return `${tryCast ? \"TRY_CAST\" : \"CAST\"}(${convertible} AS DOUBLE)`;\n}\n","// Least-squares fit of 1/(1+a*x^(2*b)) to the reference UMAP target curve.\n// Spread is fixed to one. See umap-learn's find_ab_params (0.5.9.post2).\n// A two-parameter damped Gauss-Newton solve avoids a runtime fitting dependency.\nexport default function fitUmapCurve(minDistance: number): [number, number] {\n if (!Number.isFinite(minDistance) || minDistance < 0 || minDistance > 1) {\n throw new Error(\"minDistance must be between zero and one.\");\n }\n const samples = Array.from({ length: 299 }, (_, i) => {\n const x = ((i + 1) * 3) / 299;\n return {\n logX: Math.log(x),\n target: Math.exp(-Math.max(0, x - minDistance)),\n };\n });\n const loss = (logA: number, logB: number) => {\n let sum = 0;\n for (const { logX, target } of samples) {\n const residual = 1 / (1 + Math.exp(logA + 2 * Math.exp(logB) * logX)) - target;\n sum += residual * residual;\n }\n return sum;\n };\n let logA = 0,\n logB = 0,\n damping = 1e-3;\n let error = loss(logA, logB);\n for (let iteration = 0; iteration < 100; iteration++) {\n let aa = 0,\n ab = 0,\n bb = 0,\n ga = 0,\n gb = 0;\n for (const { logX, target } of samples) {\n const power = Math.exp(logA + 2 * Math.exp(logB) * logX);\n const predicted = 1 / (1 + power);\n const da = -power * predicted * predicted;\n const db = da * 2 * Math.exp(logB) * logX;\n aa += da * da;\n ab += da * db;\n bb += db * db;\n ga += da * (predicted - target);\n gb += db * (predicted - target);\n }\n const aDiagonal = aa + damping * Math.max(aa, 1e-12);\n const bDiagonal = bb + damping * Math.max(bb, 1e-12);\n const determinant = aDiagonal * bDiagonal - ab * ab;\n if (!(determinant > 0)) throw new Error(\"UMAP curve fit became singular.\");\n const stepA = (ab * gb - bDiagonal * ga) / determinant;\n const stepB = (ab * ga - aDiagonal * gb) / determinant;\n const nextA = Math.max(-20, Math.min(20, logA + stepA));\n const nextB = Math.max(-20, Math.min(20, logB + stepB));\n const nextError = loss(nextA, nextB);\n if (nextError < error) {\n const improvement = error - nextError;\n logA = nextA;\n logB = nextB;\n error = nextError;\n damping = Math.max(damping / 3, 1e-12);\n if (improvement < 1e-13) return [Math.exp(logA), Math.exp(logB)];\n } else {\n damping *= 10;\n if (Math.max(Math.abs(ga), Math.abs(gb)) < 1e-7) {\n return [Math.exp(logA), Math.exp(logB)];\n }\n }\n }\n throw new Error(\"UMAP curve fit did not converge.\");\n}\n","import fitUmapCurve from \"./fitUmapCurve.ts\";\n\n// Resolve and validate settings before database work, fitting the curve once.\nexport default function prepareUmapLayoutOptions(\n options: {\n epochs?: number;\n seed?: number;\n minDistance?: number;\n learningRate?: number;\n negativeSamples?: number;\n } = {},\n) {\n const {\n epochs = 200,\n seed = 42,\n minDistance = 0.1,\n learningRate = 1,\n negativeSamples = 5,\n } = options;\n for (const [key, value] of Object.entries({ epochs, negativeSamples })) {\n if (!Number.isSafeInteger(value) || value < 1) {\n throw new Error(`${key} must be a positive safe integer.`);\n }\n }\n if (!Number.isInteger(seed) || seed < 0 || seed > 0xffffffff) {\n throw new Error(\"seed must be an integer between 0 and 4294967295.\");\n }\n if (!Number.isFinite(learningRate) || learningRate <= 0) {\n throw new Error(\"learningRate must be finite and positive.\");\n }\n return {\n epochs,\n seed,\n learningRate,\n negativeSamples,\n curve: fitUmapCurve(minDistance),\n };\n}\n","// Mulberry32: separate initialization and sampling streams, stable per seed.\nexport default function umapRandom(seed: number) {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) | 0;\n let value = Math.imul(state ^ (state >>> 15), 1 | state);\n value ^= value + Math.imul(value ^ (value >>> 7), 61 | value);\n return ((value ^ (value >>> 14)) >>> 0) / 4294967296;\n };\n}\n","import type prepareUmapLayoutOptions from \"./prepareUmapLayoutOptions.ts\";\nimport umapRandom from \"./umapRandom.ts\";\n\n// Internal interface. Graph entries are directed, in a stable order; the fuzzy\n// union graph supplies both orientations. Coordinates are interleaved x,y.\n// Inputs are borrowed read-only. State is O(edges + vertices), never O(n²).\n// Implements reference Euclidean UMAP SGD: scheduled attractive edges, sampled\n// repulsion, clipped gradients, symmetric attractive updates, linear decay.\n// Algorithm: https://umap-learn.readthedocs.io/en/latest/how_umap_works.html\nexport default function optimizeUmapLayout(\n graph: { source: Uint32Array; target: Uint32Array; weight: Float64Array },\n initial: Float64Array,\n options: ReturnType<typeof prepareUmapLayoutOptions>,\n): Float64Array {\n const {\n epochs,\n seed,\n learningRate,\n negativeSamples,\n curve: [a, b],\n } = options;\n const count = initial.length / 2;\n if (!Number.isInteger(count) || count < 3 || count > 0xffffffff) {\n throw new Error(\"Expected interleaved coordinates for at least three vertices.\");\n }\n for (const value of initial) {\n if (!Number.isFinite(value)) {\n throw new Error(\"Initial coordinates must be finite.\");\n }\n }\n const { source, target, weight } = graph;\n if (!weight.length || source.length !== weight.length || target.length !== weight.length)\n throw new Error(\"Invalid graph column lengths.\");\n let maximum = 0;\n for (let edge = 0; edge < weight.length; edge++) {\n if (source[edge] >= count || target[edge] >= count || source[edge] === target[edge])\n throw new Error(\"Graph contains an invalid vertex or self edge.\");\n if (!Number.isFinite(weight[edge]) || weight[edge] < 0 || weight[edge] > 1)\n throw new Error(\"Graph weights must be between zero and one.\");\n maximum = Math.max(maximum, weight[edge]);\n }\n if (!maximum) throw new Error(\"Graph must contain a positive edge.\");\n const period = new Float64Array(weight.length);\n const nextPositive = new Float64Array(weight.length);\n const nextNegative = new Float64Array(weight.length);\n // Reference pruning uses 500 when explicitly requesting at most ten epochs.\n const threshold = maximum / (epochs > 10 ? epochs : 500);\n for (let edge = 0; edge < weight.length; edge++) {\n period[edge] =\n weight[edge] > 0 && weight[edge] >= threshold\n ? epochs / ((weight[edge] / maximum) * epochs)\n : Infinity;\n nextPositive[edge] = period[edge];\n nextNegative[edge] = period[edge] / negativeSamples;\n }\n const coordinates = initial.slice();\n const random = umapRandom(seed ^ 0x7f4a7c15);\n const clip = (gradient: number) => Math.max(-4, Math.min(4, gradient));\n let alpha = learningRate;\n for (let epoch = 0; epoch < epochs; epoch++) {\n for (let edge = 0; edge < weight.length; edge++) {\n if (nextPositive[edge] > epoch) continue;\n const u = source[edge] * 2,\n v = target[edge] * 2;\n let dx = coordinates[u] - coordinates[v],\n dy = coordinates[u + 1] - coordinates[v + 1];\n let squared = dx * dx + dy * dy;\n if (squared > 0) {\n const attraction = (-2 * a * b * Math.pow(squared, b - 1)) / (1 + a * Math.pow(squared, b));\n const gx = clip(attraction * dx) * alpha,\n gy = clip(attraction * dy) * alpha;\n coordinates[u] += gx;\n coordinates[u + 1] += gy;\n coordinates[v] -= gx;\n coordinates[v + 1] -= gy;\n }\n nextPositive[edge] += period[edge];\n const negativePeriod = period[edge] / negativeSamples;\n const draws = Math.floor((epoch - nextNegative[edge]) / negativePeriod);\n for (let draw = 0; draw < draws; draw++) {\n const other = Math.floor(random() * count) * 2;\n dx = coordinates[u] - coordinates[other];\n dy = coordinates[u + 1] - coordinates[other + 1];\n squared = dx * dx + dy * dy;\n // Coincident points get zero repulsive gradient, as in current Python\n // UMAP; this intentionally differs from UMAP-JS's constant +4 fallback.\n if (squared > 0) {\n const repulsion = (2 * b) / ((0.001 + squared) * (1 + a * Math.pow(squared, b)));\n coordinates[u] += clip(repulsion * dx) * alpha;\n coordinates[u + 1] += clip(repulsion * dy) * alpha;\n }\n }\n nextNegative[edge] += draws * negativePeriod;\n }\n alpha = learningRate * (1 - epoch / epochs);\n }\n for (const value of coordinates) {\n if (!Number.isFinite(value)) {\n throw new Error(\"UMAP optimization produced a non-finite coordinate.\");\n }\n }\n return coordinates;\n}\n","import umapRandom from \"./umapRandom.ts\";\n\nexport default function initialUmapCoordinates(count: number, seed: number) {\n const random = umapRandom(seed);\n return Float64Array.from({ length: count * 2 }, () => random() * 20 - 10);\n}\n","import {\n type DuckDBConnection,\n DuckDBDataChunk,\n type DuckDBType,\n type DuckDBValue,\n} from \"@duckdb/node-api\";\n\n// Append to an existing table. Callers retain ownership of type conversion and\n// publication; each column callback supplies only the requested [start, end).\nexport default async function appendColumnBatches(\n connection: DuckDBConnection,\n table: string,\n types: readonly DuckDBType[],\n rowCount: number,\n columnValues: (column: number, start: number, end: number) => readonly DuckDBValue[],\n) {\n const appender = await connection.createAppender(table);\n try {\n // Stay below DuckDB's maximum chunk capacity of 2048 rows.\n for (let start = 0; start < rowCount; start += 2000) {\n const end = Math.min(start + 2000, rowCount);\n const chunk = DuckDBDataChunk.create(types, end - start);\n for (let column = 0; column < types.length; column++) {\n chunk.setColumnValues(column, columnValues(column, start, end));\n }\n appender.appendDataChunk(chunk);\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport buildUmapGraph from \"../helpers/buildUmapGraph.ts\";\nimport prepareNumericFeatures from \"../helpers/prepareNumericFeatures.ts\";\nimport prepareUmapLayoutOptions from \"../helpers/prepareUmapLayoutOptions.ts\";\nimport readScalarNumber from \"../helpers/readScalarNumber.ts\";\nimport optimizeUmapLayout from \"../helpers/optimizeUmapLayout.ts\";\nimport initialUmapCoordinates from \"../helpers/initialUmapCoordinates.ts\";\nimport appendColumnBatches from \"../helpers/appendColumnBatches.ts\";\nimport { DOUBLE, INTEGER } from \"@duckdb/node-api\";\n\ntype Options = NonNullable<Parameters<SimpleTable[\"umap\"]>[1]>;\n\nexport default function umap(\n table: SimpleTable,\n columns: string | string[],\n options: Options = {},\n) {\n const selected = typeof columns === \"string\" ? columns : [...columns];\n const settings = structuredClone(options);\n queueOp(table, {\n kind: \"barrier\",\n method: \"umap()\",\n parameters: { columns: selected, options: settings },\n execute: () => execute(table, selected, settings),\n });\n}\n\nasync function execute(table: SimpleTable, columns: string | string[], options: Options) {\n const { neighbors = 15, metric = \"euclidean\" } = options;\n if (!Number.isSafeInteger(neighbors) || neighbors < 2) {\n throw new Error(\"neighbors must be a safe integer of at least 2.\");\n }\n const layoutOptions = prepareUmapLayoutOptions(options);\n if (![\"euclidean\", \"cosine\"].includes(metric)) {\n throw new Error(\"metric must be euclidean or cosine.\");\n }\n const sourceColumns = await table.getColumns();\n if (sourceColumns.some((c) => [\"umapx\", \"umapy\"].includes(c.toLowerCase()))) {\n throw new Error(\"UMAP output columns umapX and umapY must not already exist.\");\n }\n\n const connection = table.connection!;\n const [sourceOid, sourceTemporary] =\n (\n await connection.runAndReadAll(\n `SELECT table_oid,temporary FROM duckdb_tables()\n WHERE lower(table_name)=lower($1) AND schema_name=current_schema()\n AND database_name IN (current_database(),'temp')\n ORDER BY temporary DESC LIMIT 1`,\n [table.name],\n )\n ).getRowsJS()[0] ?? [];\n if (typeof sourceOid !== \"number\" && typeof sourceOid !== \"bigint\") {\n throw new Error(\"UMAP requires a materialized source table.\");\n }\n const q = quoteIdentifier;\n const count = await readScalarNumber(connection, `SELECT count(*) FROM ${q(table.name)}`);\n if (count < 3 || count > 0x7fffffff) {\n throw new Error(\"UMAP requires between 3 and 2147483647 rows.\");\n }\n const prepared = await prepareNumericFeatures(\n table,\n typeof columns === \"string\"\n ? { kind: \"vector\", column: columns }\n : { kind: \"scalars\", columns },\n { method: \"umap()\" },\n );\n const dimensions = prepared.dimensions;\n const suffix = crypto.randomUUID().replaceAll(\"-\", \"\");\n const name = (part: string) => `__sda_umap_${suffix}_${part}`;\n const ordinal = q(prepared.rowIdColumn);\n const source = q(table.name),\n snapshot = q(prepared.relation);\n const layoutName = name(\"layout\"),\n layout = q(layoutName);\n const names = {\n rows: q(name(\"rows\")),\n knn: q(name(\"knn\")),\n search: q(name(\"search\")),\n hnsw: q(name(\"hnsw\")),\n candidates: q(name(\"candidates\")),\n scales: q(name(\"scales\")),\n directed: q(name(\"directed\")),\n graph: q(name(\"graph\")),\n };\n const scratch = [\n layout,\n ...Object.entries(names)\n .filter(([key]) => key !== \"hnsw\")\n .map(([, value]) => value),\n ];\n try {\n await connection.run(`CREATE TEMP TABLE ${names.rows} AS\n SELECT (row_number() OVER (ORDER BY ${ordinal})-1)::INTEGER AS vertex,\n ${ordinal} AS ordinal, ${q(prepared.vectorColumn)} AS vec FROM ${snapshot}`);\n await connection.run(`ALTER TABLE ${snapshot} DROP COLUMN ${q(prepared.vectorColumn)}`);\n if (\n await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${names.rows}\n WHERE NOT isfinite(array_inner_product(vec,vec)) OR array_inner_product(vec,vec)>1e300\n ${metric === \"cosine\" ? \"OR array_inner_product(vec,vec)=0\" : \"\"}`,\n )\n ) {\n throw new Error(\"Vector norms overflow, or cosine distance received a zero vector.\");\n }\n const graph = await buildUmapGraph(\n connection,\n {\n count,\n dimensions,\n neighbors: Math.min(neighbors, count - 1),\n },\n {\n metric,\n search: count <= 1000 ? \"exact\" : \"hnsw\",\n },\n names,\n );\n // Release index and vector scratch before allocating optimizer state.\n for (const relation of [\n names.search,\n names.candidates,\n names.knn,\n names.directed,\n names.scales,\n names.graph,\n ]) {\n await connection.run(`DROP TABLE IF EXISTS ${relation}`);\n }\n await connection.run(`ALTER TABLE ${names.rows} DROP COLUMN vec`);\n const coordinates = optimizeUmapLayout(\n graph,\n initialUmapCoordinates(count, layoutOptions.seed),\n layoutOptions,\n );\n await connection.run(`CREATE TEMP TABLE ${layout} (vertex INTEGER,x DOUBLE,y DOUBLE)`);\n await appendColumnBatches(\n connection,\n layoutName,\n [INTEGER, DOUBLE, DOUBLE],\n count,\n (column, start, end) =>\n Array.from({ length: end - start }, (_, row) =>\n column === 0 ? start + row : coordinates[2 * (start + row) + column - 1],\n ),\n );\n // Replace the table and recreate existing native indexes, which\n // CREATE OR REPLACE drops.\n const indexes = (\n await connection.runAndReadAll(\"SELECT sql FROM duckdb_indexes() WHERE table_oid=$1\", [\n sourceOid,\n ])\n )\n .getRowsJS()\n .map((row) => {\n if (typeof row[0] !== \"string\") throw new Error(\"Expected index SQL to be a string.\");\n return row[0];\n });\n await queryDB(\n table,\n `CREATE OR REPLACE ${sourceTemporary ? \"TEMP \" : \"\"}TABLE ${source} AS\n SELECT ${prepared.sourceColumns\n .map((c) => `s.${q(c)}`)\n .join(\",\")}, l.x AS \"umapX\", l.y AS \"umapY\"\n FROM ${snapshot} s JOIN ${names.rows} r ON s.${ordinal}=r.ordinal\n JOIN ${layout} l ON r.vertex=l.vertex ORDER BY s.${ordinal}`,\n mergeOptions(table, {\n table: table.name,\n method: \"umap()\",\n parameters: { columns, options },\n noClean: true,\n }),\n );\n for (const sql of indexes) await connection.run(sql);\n } finally {\n for (const relation of scratch) {\n await connection.run(`DROP TABLE IF EXISTS ${relation}`);\n }\n await prepared.cleanup();\n }\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\n\ntype WeightedEdge = { source: number; target: number; distance: number };\n\n/** Select a deterministically ordered MST from a connected sparse candidate graph. */\nexport default async function buildSparseMutualReachabilityMst(\n connection: DuckDBConnection,\n edges: string,\n count: number,\n): Promise<WeightedEdge[]> {\n const parent = new Int32Array(count);\n const size = new Int32Array(count).fill(1);\n for (let vertex = 0; vertex < count; vertex++) parent[vertex] = vertex;\n const find = (start: number): number => {\n let root = start;\n while (parent[root] !== root) root = parent[root];\n let current = start;\n while (parent[current] !== current) {\n const next = parent[current];\n parent[current] = root;\n current = next;\n }\n return root;\n };\n const mst: WeightedEdge[] = [];\n const result = await connection.stream(\n `SELECT source,target,distance FROM ${edges}\n ORDER BY distance,source,target`,\n );\n while (mst.length < count - 1) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const sources = chunk.getColumnVector(0);\n const targets = chunk.getColumnVector(1);\n const distances = chunk.getColumnVector(2);\n for (let row = 0; row < chunk.rowCount && mst.length < count - 1; row++) {\n const source = Number(sources.getItem(row));\n const target = Number(targets.getItem(row));\n const distance = Number(distances.getItem(row));\n let left = find(source),\n right = find(target);\n if (left === right) continue;\n if (size[left] < size[right]) [left, right] = [right, left];\n parent[right] = left;\n size[left] += size[right];\n mst.push({ source, target, distance });\n }\n }\n if (mst.length !== count - 1) {\n throw new Error(\"Approximate HDBSCAN candidate graph has no spanning tree.\");\n }\n return mst;\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\n\n/**\n * Inspect connectivity of an edge relation while transferring ids, not vectors.\n * Isolated vertices count as one-point components. Invalid ids fail closed.\n */\nexport default async function inspectGraphConnectivity(\n connection: DuckDBConnection,\n edges: string,\n vertexCount: number,\n): Promise<{ componentCount: number; sizes: number[] }> {\n if (!Number.isSafeInteger(vertexCount) || vertexCount < 1 || vertexCount > 2147483647) {\n throw new Error(\"Graph vertex count must fit a positive INTEGER vertex count.\");\n }\n const parent = new Int32Array(vertexCount);\n const sizes = new Int32Array(vertexCount).fill(1);\n for (let vertex = 0; vertex < vertexCount; vertex++) parent[vertex] = vertex;\n const root = (vertex: number) => {\n while (parent[vertex] !== vertex) {\n parent[vertex] = parent[parent[vertex]];\n vertex = parent[vertex];\n }\n return vertex;\n };\n const rows = await connection.stream(`SELECT source,target FROM ${edges}`);\n while (true) {\n const chunk = await rows.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const sources = chunk.getColumnVector(0);\n const targets = chunk.getColumnVector(1);\n for (let row = 0; row < chunk.rowCount; row++) {\n const sourceValue = sources.getItem(row);\n const targetValue = targets.getItem(row);\n const source = Number(sourceValue);\n const target = Number(targetValue);\n if (\n sourceValue === null ||\n targetValue === null ||\n !Number.isSafeInteger(source) ||\n source < 0 ||\n source >= vertexCount ||\n !Number.isSafeInteger(target) ||\n target < 0 ||\n target >= vertexCount\n ) {\n throw new Error(\"Graph edge contains an invalid vertex id.\");\n }\n let sourceRoot = root(source),\n targetRoot = root(target);\n if (sourceRoot === targetRoot) continue;\n if (sizes[sourceRoot] < sizes[targetRoot]) {\n [sourceRoot, targetRoot] = [targetRoot, sourceRoot];\n }\n parent[targetRoot] = sourceRoot;\n sizes[sourceRoot] += sizes[targetRoot];\n }\n }\n const componentSizes: number[] = [];\n for (let vertex = 0; vertex < vertexCount; vertex++) {\n if (root(vertex) === vertex) componentSizes.push(sizes[vertex]);\n }\n componentSizes.sort((a, b) => b - a);\n return { componentCount: componentSizes.length, sizes: componentSizes };\n}\n","import { DOUBLE, type DuckDBConnection, INTEGER } from \"@duckdb/node-api\";\nimport appendColumnBatches from \"./appendColumnBatches.ts\";\nimport buildSparseMutualReachabilityMst from \"./buildSparseMutualReachabilityMst.ts\";\nimport buildVectorNeighbors from \"./buildVectorNeighbors.ts\";\nimport inspectGraphConnectivity from \"./inspectGraphConnectivity.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport vectorDistanceExpression from \"./vectorDistanceExpression.ts\";\n\n/**\n * Build an explicitly approximate mutual-reachability MST. HNSW supplies a\n * high-recall k-neighbor candidate graph; disconnected components are repaired\n * with deterministic all-member projection sweeps. Neither step guarantees the\n * complete graph's MST.\n */\nexport default async function buildApproximateMutualReachabilityMst(\n connection: DuckDBConnection,\n input: { count: number; dimensions: number; minSamples: number },\n options: { metric: \"euclidean\" | \"cosine\" },\n names: {\n rows: string;\n neighbors: string;\n search: string;\n hnsw: string;\n candidates: string;\n coreDistances: string;\n edges: string;\n components: string;\n representatives: string;\n componentPairs: string;\n bridgeCandidates: string;\n mst: string;\n },\n): Promise<{ candidateComponents: number; neighborCount: number }> {\n const q = quoteIdentifier;\n const quoted = Object.fromEntries(\n Object.entries(names).map(([key, value]) => [key, q(value)]),\n ) as { [Key in keyof typeof names]: string };\n const neighborCount = Math.min(input.count - 1, Math.max(input.minSamples, 64));\n await buildVectorNeighbors(\n connection,\n {\n count: input.count,\n dimensions: input.dimensions,\n neighborCount,\n },\n {\n metric: options.metric,\n search: \"hnsw\",\n includeSelf: false,\n hnsw: {\n efConstruction: 256,\n efSearch: Math.max(512, neighborCount * 2),\n connectivity: 32,\n candidateCount: Math.min(input.count, neighborCount * 2 + 1),\n singleThreaded: true,\n cosineAsL2: true,\n },\n },\n {\n rows: quoted.rows,\n neighbors: quoted.neighbors,\n search: quoted.search,\n hnsw: quoted.hnsw,\n candidates: quoted.candidates,\n },\n );\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${quoted.coreDistances} AS\n SELECT source AS vertex,distance\n FROM ${quoted.neighbors} WHERE rank=${input.minSamples - 1};\n CREATE OR REPLACE TEMP TABLE ${quoted.edges} AS\n SELECT least(n.source,n.target)::INTEGER AS source,\n greatest(n.source,n.target)::INTEGER AS target,\n min(greatest(cs.distance,ct.distance,n.distance))::DOUBLE AS distance\n FROM ${quoted.neighbors} n\n JOIN ${quoted.coreDistances} cs ON cs.vertex=n.source\n JOIN ${quoted.coreDistances} ct ON ct.vertex=n.target\n GROUP BY least(n.source,n.target),greatest(n.source,n.target)`);\n await connection.run(`DROP TABLE IF EXISTS ${quoted.neighbors};\n DROP TABLE IF EXISTS ${quoted.candidates};\n DROP TABLE IF EXISTS ${quoted.search}`);\n\n const componentCount = await repairApproximateConnectivity(\n connection,\n { count: input.count },\n options,\n {\n rows: names.rows,\n coreDistances: names.coreDistances,\n edges: names.edges,\n components: names.components,\n representatives: names.representatives,\n componentPairs: names.componentPairs,\n bridgeCandidates: names.bridgeCandidates,\n },\n );\n const mst = await buildSparseMutualReachabilityMst(connection, quoted.edges, input.count);\n await connection.run(\n `CREATE OR REPLACE TEMP TABLE ${quoted.mst}\n (source INTEGER,target INTEGER,distance DOUBLE)`,\n );\n await appendColumnBatches(\n connection,\n names.mst,\n [INTEGER, INTEGER, DOUBLE],\n mst.length,\n (column, start, end) =>\n mst\n .slice(start, end)\n .map((edge) => (column === 0 ? edge.source : column === 1 ? edge.target : edge.distance)),\n );\n return { candidateComponents: componentCount, neighborCount };\n}\n\n/** Internal connectivity-repair seam used by focused approximation tests. */\nexport async function repairApproximateConnectivity(\n connection: DuckDBConnection,\n input: { count: number },\n options: { metric: \"euclidean\" | \"cosine\" },\n names: {\n rows: string;\n coreDistances: string;\n edges: string;\n components: string;\n representatives: string;\n componentPairs: string;\n bridgeCandidates: string;\n },\n): Promise<number> {\n const q = quoteIdentifier;\n const quoted = Object.fromEntries(\n Object.entries(names).map(([key, value]) => [key, q(value)]),\n ) as { [Key in keyof typeof names]: string };\n const componentOf = await readComponents(connection, quoted.edges, input.count);\n let maximumComponent = -1;\n for (const component of componentOf) {\n if (component > maximumComponent) maximumComponent = component;\n }\n const componentCount = maximumComponent + 1;\n if (componentCount > 1) {\n await createComponentRows(connection, names.components, componentOf);\n // Each sweep examines every point, rather than a fixed representative\n // sample. Consecutive component runs in the projected order provide a\n // connected backbone, while multiple directions offer alternative edges.\n // We also connect each member of a run to the nearest projected endpoint\n // in both adjacent runs. All weights are recomputed in the actual metric.\n const dimensions = Number(\n (\n await connection.runAndReadAll(`SELECT len(vec) FROM ${quoted.rows} LIMIT 1`)\n ).getRowsJS()[0][0],\n );\n await connection.run(\n `CREATE OR REPLACE TEMP TABLE ${quoted.bridgeCandidates}\n (source INTEGER,target INTEGER,distance DOUBLE)`,\n );\n const rawDistance = vectorDistanceExpression(\"a.vec\", \"b.vec\", options.metric);\n const projectionCount = Math.min(dimensions, 8) + (dimensions > 1 ? 16 : 0);\n for (let projection = 0; projection < projectionCount; projection++) {\n // Coordinate directions handle axis-aligned and one-dimensional data;\n // fixed pseudo-random directions cover rotated component boundaries.\n // Coefficients do not depend on table names, execution order, or RNG state.\n const coefficients = Array.from({ length: dimensions }, (_, dimension) => {\n if (projection < Math.min(dimensions, 8)) {\n return dimension === projection ? 1 : 0;\n }\n let hash = Math.imul(projection + 1, 0x9e3779b1) ^ Math.imul(dimension + 1, 0x85ebca6b);\n hash = Math.imul(hash ^ (hash >>> 16), 0x7feb352d);\n hash = Math.imul(hash ^ (hash >>> 15), 0x846ca68b);\n return (((hash ^ (hash >>> 16)) >>> 0) / 0x100000000) * 2 - 1;\n });\n // Scaling each coordinate by the same global factor prevents overflow\n // in the projection without changing its ordering. Unit directions are\n // the appropriate search geometry for cosine.\n const vector =\n options.metric === \"cosine\"\n ? `list_transform(r.vec,x -> x/sqrt(array_inner_product(r.vec,r.vec)))::DOUBLE[${dimensions}]`\n : `list_transform(r.vec,x -> x/scale.maximum)::DOUBLE[${dimensions}]`;\n await connection.run(\n `CREATE OR REPLACE TEMP TABLE ${quoted.representatives} AS\n WITH projected AS (\n SELECT r.vertex,c.component,\n array_inner_product(${vector},[${coefficients.join(\n \",\",\n )}]::DOUBLE[${dimensions}]) AS position\n FROM ${quoted.rows} r JOIN ${quoted.components} c USING(vertex)\n CROSS JOIN (SELECT greatest(1,max(list_max(list_transform(vec,x -> abs(x))))) AS maximum FROM ${quoted.rows}) scale\n ), ordered AS (\n SELECT *,lag(component) OVER w AS previous_component,\n lead(component) OVER w AS next_component,\n lag(vertex) OVER w AS previous_vertex,\n lead(vertex) OVER w AS next_vertex\n FROM projected WINDOW w AS (ORDER BY position,vertex)\n )\n SELECT vertex,\n last_value(CASE WHEN component != previous_component THEN previous_vertex END IGNORE NULLS)\n OVER (ORDER BY position,vertex ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS left_vertex,\n first_value(CASE WHEN component != next_component THEN next_vertex END IGNORE NULLS)\n OVER (ORDER BY position,vertex ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS right_vertex\n FROM ordered;\n INSERT INTO ${quoted.bridgeCandidates}\n SELECT least(a.vertex,b.vertex)::INTEGER,greatest(a.vertex,b.vertex)::INTEGER,\n greatest(ca.distance,cb.distance,${rawDistance})::DOUBLE\n FROM (SELECT vertex,unnest([left_vertex,right_vertex]) AS target FROM ${quoted.representatives}) p\n JOIN ${quoted.rows} a ON a.vertex=p.vertex\n JOIN ${quoted.rows} b ON b.vertex=p.target\n JOIN ${quoted.coreDistances} ca ON ca.vertex=a.vertex\n JOIN ${quoted.coreDistances} cb ON cb.vertex=b.vertex`,\n );\n }\n const invalidBridgeDistances = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(*) FROM ${quoted.bridgeCandidates}\n WHERE distance IS NULL OR NOT isfinite(distance)`,\n )\n ).getRowsJS()[0][0],\n );\n if (invalidBridgeDistances > 0) {\n throw new Error(\n `Approximate HDBSCAN connectivity repair produced ${invalidBridgeDistances} non-finite candidate distances. Rescale the input features.`,\n );\n }\n await connection.run(`INSERT INTO ${quoted.edges}\n SELECT source,target,min(distance) AS distance\n FROM ${quoted.bridgeCandidates} GROUP BY source,target`);\n }\n const connectivity = await inspectGraphConnectivity(connection, quoted.edges, input.count);\n if (connectivity.componentCount !== 1) {\n throw new Error(\n `Approximate HDBSCAN connectivity repair left ${connectivity.componentCount} graph components.`,\n );\n }\n return componentCount;\n}\n\nasync function readComponents(\n connection: DuckDBConnection,\n edges: string,\n count: number,\n): Promise<Int32Array> {\n const parent = new Int32Array(count);\n const size = new Int32Array(count).fill(1);\n for (let vertex = 0; vertex < count; vertex++) parent[vertex] = vertex;\n const find = (start: number): number => {\n let root = start;\n while (parent[root] !== root) root = parent[root];\n let current = start;\n while (parent[current] !== current) {\n const next = parent[current];\n parent[current] = root;\n current = next;\n }\n return root;\n };\n const union = (left: number, right: number) => {\n let a = find(left),\n b = find(right);\n if (a === b) return;\n if (size[a] < size[b]) [a, b] = [b, a];\n parent[b] = a;\n size[a] += size[b];\n };\n const result = await connection.stream(`SELECT source,target FROM ${edges}`);\n while (true) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const sources = chunk.getColumnVector(0);\n const targets = chunk.getColumnVector(1);\n for (let row = 0; row < chunk.rowCount; row++) {\n union(Number(sources.getItem(row)), Number(targets.getItem(row)));\n }\n }\n const minimum = new Map<number, number>();\n for (let vertex = 0; vertex < count; vertex++) {\n const root = find(vertex);\n minimum.set(root, Math.min(minimum.get(root) ?? vertex, vertex));\n }\n const ids = [...minimum]\n .sort((a, b) => a[1] - b[1])\n .map(([root], component) => [root, component] as const);\n const componentByRoot = new Map(ids);\n const componentOf = new Int32Array(count);\n for (let vertex = 0; vertex < count; vertex++) {\n componentOf[vertex] = componentByRoot.get(find(vertex))!;\n }\n return componentOf;\n}\n\nasync function createComponentRows(\n connection: DuckDBConnection,\n name: string,\n componentOf: Int32Array,\n): Promise<void> {\n await connection.run(\n `CREATE OR REPLACE TEMP TABLE ${quoteIdentifier(name)}\n (vertex INTEGER,component INTEGER)`,\n );\n await appendColumnBatches(\n connection,\n name,\n [INTEGER, INTEGER],\n componentOf.length,\n (column, start, end) =>\n Array.from({ length: end - start }, (_, offset) =>\n column === 0 ? start + offset : componentOf[start + offset],\n ),\n );\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\nimport readScalarNumber from \"./readScalarNumber.ts\";\nimport vectorDistanceExpression from \"./vectorDistanceExpression.ts\";\nimport stabilizeCosineVectors from \"./stabilizeCosineVectors.ts\";\nimport validateVectorRowIds from \"./validateVectorRowIds.ts\";\n\n/** Private, already-quoted relation names owned and cleaned up by the caller. */\nexport type MutualReachabilityTables = {\n rows: string;\n coreDistances: string;\n frontier: string;\n mst: string;\n};\n\n/**\n * Build an exact HDBSCAN mutual-reachability MST with bounded materialization.\n *\n * The prepared rows relation must contain contiguous INTEGER `vertex` ids and\n * fixed-size DOUBLE `vec` values. `minSamples` excludes the point itself. Core\n * distance calculation uses bounded top-k aggregates and retains one scalar per\n * point. Prim's algorithm retains one frontier edge per unvisited point. This\n * costs O(n²d) distance work, O(n) stored algorithm state, and O(n) sequential\n * DuckDB statements; it is intended as the exact correctness baseline.\n * Cosine preparation may rescale the private vec column, preserving direction.\n * All supplied scratch names are already quoted, distinct, and caller-owned;\n * the caller must drop them in finally on both success and failure.\n */\nexport default async function buildExactMutualReachabilityMst(\n connection: DuckDBConnection,\n input: { count: number; minSamples: number },\n options: { metric: \"euclidean\" | \"cosine\" },\n names: MutualReachabilityTables,\n): Promise<void> {\n const { count, minSamples } = input;\n if (count < 2 || !Number.isSafeInteger(count)) {\n throw new Error(\"Exact mutual-reachability MST requires at least two rows.\");\n }\n if (!Number.isSafeInteger(minSamples) || minSamples < 1 || minSamples >= count) {\n throw new Error(`minSamples must be a safe integer between 1 and ${count - 1}.`);\n }\n await validateVectorRowIds(connection, names.rows, count);\n if (options.metric === \"cosine\") {\n await stabilizeCosineVectors(connection, names.rows);\n }\n const distance = vectorDistanceExpression(\"a.vec\", \"b.vec\", options.metric);\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.coreDistances}\n (vertex INTEGER PRIMARY KEY,distance DOUBLE)`);\n for (let offset = 0; offset < count; offset += 32) {\n await connection.run(`INSERT INTO ${names.coreDistances}\n SELECT source,max(item.distance)::DOUBLE AS distance FROM (\n SELECT a.vertex AS source,\n CASE WHEN bool_and(isfinite(${distance})) THEN\n min_by(struct_pack(target := b.vertex,distance := ${distance}),\n struct_pack(distance := ${distance},target := b.vertex),\n ${minSamples}) ELSE error('Distance computation returned a non-finite value.') END AS closest\n FROM ${names.rows} a CROSS JOIN ${names.rows} b\n WHERE a.vertex >= ${offset} AND a.vertex < ${offset + 32}\n AND a.vertex != b.vertex GROUP BY a.vertex\n ),UNNEST(closest) AS t(item) GROUP BY source`);\n }\n if (\n (await readScalarNumber(\n connection,\n `SELECT count(*) FROM ${names.coreDistances}\n WHERE NOT isfinite(distance)`,\n )) ||\n (await readScalarNumber(connection, `SELECT count(*) FROM ${names.coreDistances}`)) !== count\n ) {\n throw new Error(\"Exact core-distance computation returned missing or non-finite values.\");\n }\n\n const root = await readScalarNumber(connection, `SELECT min(vertex) FROM ${names.rows}`);\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.frontier} AS\n SELECT b.vertex,${root}::INTEGER AS parent,\n greatest(ca.distance,cb.distance,${distance})::DOUBLE AS distance\n FROM ${names.rows} a CROSS JOIN ${names.rows} b\n JOIN ${names.coreDistances} ca ON ca.vertex=a.vertex\n JOIN ${names.coreDistances} cb ON cb.vertex=b.vertex\n WHERE a.vertex=${root} AND b.vertex!=${root};\n CREATE OR REPLACE TEMP TABLE ${names.mst}\n (source INTEGER,target INTEGER,distance DOUBLE)`);\n\n for (let edge = 0; edge < count - 1; edge++) {\n const chosen = (\n await connection.runAndReadAll(\n `SELECT vertex,parent,distance FROM ${names.frontier}\n ORDER BY distance,least(parent,vertex),greatest(parent,vertex),parent,vertex\n LIMIT 1`,\n )\n ).getRowsJS()[0];\n if (chosen === undefined) {\n throw new Error(\"Exact mutual-reachability graph became disconnected.\");\n }\n const vertex = Number(chosen[0]);\n const parent = Number(chosen[1]);\n const edgeDistance = Number(chosen[2]);\n if (!Number.isFinite(edgeDistance)) {\n throw new Error(\"Exact mutual-reachability MST returned a non-finite distance.\");\n }\n await connection.run(`INSERT INTO ${names.mst} VALUES\n (${Math.min(vertex, parent)},${Math.max(vertex, parent)},${edgeDistance})`);\n if (edge === count - 2) break;\n const candidateDistance = vectorDistanceExpression(\"added.vec\", \"target.vec\", options.metric);\n await connection.run(`CREATE OR REPLACE TEMP TABLE ${names.frontier} AS\n WITH candidates AS (\n SELECT f.*,greatest(ca.distance,cb.distance,${candidateDistance})::DOUBLE\n AS candidate_distance\n FROM ${names.frontier} f\n JOIN ${names.rows} target ON target.vertex=f.vertex\n CROSS JOIN ${names.rows} added\n JOIN ${names.coreDistances} ca ON ca.vertex=added.vertex\n JOIN ${names.coreDistances} cb ON cb.vertex=target.vertex\n WHERE added.vertex=${vertex} AND f.vertex!=${vertex}\n )\n SELECT vertex,\n CASE WHEN candidate_distance<distance OR\n (candidate_distance=distance AND ${vertex}<parent)\n THEN ${vertex} ELSE parent END::INTEGER AS parent,\n least(distance,candidate_distance)::DOUBLE AS distance\n FROM candidates`);\n }\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\n\ntype Edge = { source: number; target: number; distance: number };\ntype Linkage = { left: number; right: number; distance: number; size: number };\ntype CondensedEdge = {\n parent: number;\n child: number;\n lambda: number;\n childSize: number;\n};\n\n/**\n * Build the condensed hierarchy, select EOM clusters, and calculate point\n * outputs from an HDBSCAN mutual-reachability MST. Only O(n) graph/hierarchy\n * state crosses from DuckDB; source vectors remain native.\n */\nexport default async function clusterHdbscan(\n connection: DuckDBConnection,\n mst: string,\n options: {\n count: number;\n minClusterSize: number;\n allowSingleCluster: boolean;\n },\n): Promise<{\n labels: Int32Array;\n probabilities: Float64Array;\n outlierScores: Float64Array;\n}> {\n // Leaves and internal nodes share the signed Int32 hierarchy namespace.\n if (!Number.isSafeInteger(options.count) || options.count < 2 || options.count > 0x40000000) {\n throw new Error(\n \"HDBSCAN hierarchy requires between 2 and 1073741824 rows so all 2*n-1 node identifiers fit signed INTEGER state.\",\n );\n }\n const edges = await readMst(connection, mst, options.count);\n const linkage = buildSingleLinkage(edges, options.count);\n const tree = condenseTree(linkage, options.count, options.minClusterSize);\n return selectClusters(tree, options.count, options.allowSingleCluster);\n}\n\nasync function readMst(connection: DuckDBConnection, mst: string, count: number): Promise<Edge[]> {\n const edges: Edge[] = [];\n const result = await connection.stream(`SELECT source,target,distance FROM ${mst}`);\n while (true) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const sources = chunk.getColumnVector(0);\n const targets = chunk.getColumnVector(1);\n const distances = chunk.getColumnVector(2);\n for (let row = 0; row < chunk.rowCount; row++) {\n const rawSource = sources.getItem(row);\n const rawTarget = targets.getItem(row);\n const rawDistance = distances.getItem(row);\n if (\n rawSource === null ||\n rawSource === undefined ||\n rawTarget === null ||\n rawTarget === undefined ||\n rawDistance === null ||\n rawDistance === undefined\n ) {\n throw new Error(\"HDBSCAN mutual-reachability MST contains an invalid edge.\");\n }\n const source = Number(rawSource);\n const target = Number(rawTarget);\n const distance = Number(rawDistance);\n if (\n !Number.isSafeInteger(source) ||\n source < 0 ||\n source >= count ||\n !Number.isSafeInteger(target) ||\n target < 0 ||\n target >= count ||\n source === target ||\n !Number.isFinite(distance) ||\n distance < 0\n ) {\n throw new Error(\"HDBSCAN mutual-reachability MST contains an invalid edge.\");\n }\n edges.push({ source, target, distance });\n }\n }\n if (edges.length !== count - 1) {\n throw new Error(\n `HDBSCAN mutual-reachability MST returned ${edges.length} edges; ${count - 1} were required.`,\n );\n }\n return edges;\n}\n\nfunction buildSingleLinkage(edges: Edge[], count: number): Linkage[] {\n edges.sort(\n (a, b) =>\n a.distance - b.distance ||\n Math.min(a.source, a.target) - Math.min(b.source, b.target) ||\n Math.max(a.source, a.target) - Math.max(b.source, b.target),\n );\n const parent = new Int32Array(count);\n const size = new Int32Array(count).fill(1);\n const node = new Int32Array(count);\n for (let vertex = 0; vertex < count; vertex++) {\n parent[vertex] = vertex;\n node[vertex] = vertex;\n }\n const find = (start: number): number => {\n let root = start;\n while (parent[root] !== root) root = parent[root];\n let current = start;\n while (parent[current] !== current) {\n const next = parent[current];\n parent[current] = root;\n current = next;\n }\n return root;\n };\n const linkage: Linkage[] = [];\n for (const edge of edges) {\n let leftRoot = find(edge.source);\n let rightRoot = find(edge.target);\n if (leftRoot === rightRoot) {\n throw new Error(\"HDBSCAN mutual-reachability edges do not form a tree.\");\n }\n const combinedNode = count + linkage.length;\n const combinedSize = size[leftRoot] + size[rightRoot];\n linkage.push({\n left: node[leftRoot],\n right: node[rightRoot],\n distance: edge.distance,\n size: combinedSize,\n });\n if (size[leftRoot] < size[rightRoot]) {\n [leftRoot, rightRoot] = [rightRoot, leftRoot];\n }\n parent[rightRoot] = leftRoot;\n size[leftRoot] = combinedSize;\n node[leftRoot] = combinedNode;\n }\n if (linkage.length !== count - 1 || linkage.at(-1)?.size !== count) {\n throw new Error(\"HDBSCAN mutual-reachability edges do not form one connected tree.\");\n }\n return linkage;\n}\n\nfunction condenseTree(\n hierarchy: Linkage[],\n count: number,\n minClusterSize: number,\n): CondensedEdge[] {\n const root = 2 * count - 2;\n const relabel = new Int32Array(root + 1).fill(-1);\n relabel[root] = count;\n let nextLabel = count + 1;\n const ignored = new Uint8Array(root + 1);\n const result: CondensedEdge[] = [];\n\n for (const current of breadthFirstHierarchy(hierarchy, count, root)) {\n if (ignored[current] || current < count) continue;\n const split = hierarchy[current - count];\n const lambda = split.distance > 0 ? 1 / split.distance : Infinity;\n const leftSize = split.left >= count ? hierarchy[split.left - count].size : 1;\n const rightSize = split.right >= count ? hierarchy[split.right - count].size : 1;\n if (leftSize >= minClusterSize && rightSize >= minClusterSize) {\n relabel[split.left] = nextLabel++;\n result.push({\n parent: relabel[current],\n child: relabel[split.left],\n lambda,\n childSize: leftSize,\n });\n relabel[split.right] = nextLabel++;\n result.push({\n parent: relabel[current],\n child: relabel[split.right],\n lambda,\n childSize: rightSize,\n });\n } else if (leftSize < minClusterSize && rightSize < minClusterSize) {\n appendRunt(hierarchy, count, split.left, relabel[current], lambda, ignored, result);\n appendRunt(hierarchy, count, split.right, relabel[current], lambda, ignored, result);\n } else if (leftSize < minClusterSize) {\n relabel[split.right] = relabel[current];\n appendRunt(hierarchy, count, split.left, relabel[current], lambda, ignored, result);\n } else {\n relabel[split.left] = relabel[current];\n appendRunt(hierarchy, count, split.right, relabel[current], lambda, ignored, result);\n }\n }\n if (result.length === 0) {\n throw new Error(\"HDBSCAN condensed hierarchy is empty.\");\n }\n return result;\n}\n\nfunction appendRunt(\n hierarchy: Linkage[],\n count: number,\n root: number,\n parent: number,\n lambda: number,\n ignored: Uint8Array,\n result: CondensedEdge[],\n): void {\n for (const node of breadthFirstHierarchy(hierarchy, count, root)) {\n if (node < count) {\n result.push({ parent, child: node, lambda, childSize: 1 });\n }\n ignored[node] = 1;\n }\n}\n\nfunction breadthFirstHierarchy(hierarchy: Linkage[], count: number, root: number): number[] {\n const result: number[] = [];\n let level = [root];\n while (level.length > 0) {\n for (const node of level) result.push(node);\n const next: number[] = [];\n for (const node of level) {\n if (node < count) continue;\n const split = hierarchy[node - count];\n next.push(split.left, split.right);\n }\n level = next;\n }\n return result;\n}\n\nfunction selectClusters(\n tree: CondensedEdge[],\n count: number,\n allowSingleCluster: boolean,\n): {\n labels: Int32Array;\n probabilities: Float64Array;\n outlierScores: Float64Array;\n} {\n let root = Number.MAX_SAFE_INTEGER;\n let maximumParent = -1;\n for (const edge of tree) {\n if (edge.parent < root) root = edge.parent;\n if (edge.parent > maximumParent) maximumParent = edge.parent;\n }\n if (root !== count) {\n throw new Error(\"HDBSCAN condensed hierarchy has an invalid root.\");\n }\n const births = new Float64Array(maximumParent + 1).fill(NaN);\n for (const edge of tree) {\n if (Number.isNaN(births[edge.child])) births[edge.child] = edge.lambda;\n else births[edge.child] = Math.min(births[edge.child], edge.lambda);\n }\n births[root] = 0;\n const stability = new Map<number, number>();\n for (let cluster = root; cluster <= maximumParent; cluster++) {\n stability.set(cluster, 0);\n }\n for (const edge of tree) {\n stability.set(\n edge.parent,\n stability.get(edge.parent)! + (edge.lambda - births[edge.parent]) * edge.childSize,\n );\n }\n\n const clusterEdges = tree.filter(({ childSize }) => childSize > 1);\n const nodeList = [...stability.keys()].sort((a, b) => b - a);\n if (!allowSingleCluster) nodeList.pop();\n const preferred = new Map<number, boolean>();\n const children = new Map<number, number[]>();\n for (const edge of clusterEdges) {\n const values = children.get(edge.parent) ?? [];\n values.push(edge.child);\n children.set(edge.parent, values);\n }\n for (const cluster of nodeList) {\n const childClusters = children.get(cluster) ?? [];\n // hdbscan 0.8.44 stores this otherwise-double reduction in a C float.\n const subtreeStability = accumulateFloat32(childClusters.map((child) => stability.get(child)!));\n if (subtreeStability > stability.get(cluster)!) {\n stability.set(cluster, subtreeStability);\n preferred.set(cluster, false);\n } else {\n preferred.set(cluster, true);\n }\n }\n const clusters: number[] = [];\n const pending = [root];\n while (pending.length > 0) {\n const cluster = pending.pop()!;\n if ((cluster !== root || allowSingleCluster) && preferred.get(cluster)) {\n clusters.push(cluster);\n continue;\n }\n const childClusters = children.get(cluster) ?? [];\n for (let index = childClusters.length - 1; index >= 0; index--) {\n pending.push(childClusters[index]);\n }\n }\n clusters.sort((a, b) => a - b);\n const labelsByCluster = new Map(clusters.map((cluster, label) => [cluster, label]));\n const pointEdges: CondensedEdge[] = [];\n pointEdges.length = count;\n const parentByCluster = new Map<number, number>();\n for (const edge of tree) {\n if (edge.child < count) pointEdges[edge.child] = edge;\n else parentByCluster.set(edge.child, edge.parent);\n }\n for (let point = 0; point < count; point++) {\n if (pointEdges[point] === undefined) {\n throw new Error(\"HDBSCAN condensed hierarchy omitted an input row.\");\n }\n }\n\n const labels = new Int32Array(count).fill(-1);\n const selectedAncestor = new Int32Array(maximumParent + 1).fill(-1);\n for (let cluster = root; cluster <= maximumParent; cluster++) {\n if (labelsByCluster.has(cluster)) {\n selectedAncestor[cluster] = cluster;\n continue;\n }\n const parent = parentByCluster.get(cluster);\n if (parent !== undefined) {\n selectedAncestor[cluster] = selectedAncestor[parent];\n }\n }\n let rootExit = 0;\n for (const edge of tree) {\n if (edge.parent === root && edge.lambda > rootExit) rootExit = edge.lambda;\n }\n for (let point = 0; point < count; point++) {\n const pointEdge = pointEdges[point];\n const cluster = selectedAncestor[pointEdge.parent];\n if (cluster < 0) continue;\n if (\n cluster === root &&\n !(clusters.length === 1 && allowSingleCluster && pointEdge.lambda >= rootExit)\n )\n continue;\n labels[point] = labelsByCluster.get(cluster)!;\n }\n\n const deaths = directMaximumLambdas(tree, maximumParent);\n const probabilities = new Float64Array(count);\n for (let point = 0; point < count; point++) {\n const label = labels[point];\n if (label < 0) continue;\n const cluster = clusters[label];\n const maximum = deaths[cluster];\n const lambda = pointEdges[point].lambda;\n probabilities[point] =\n maximum === 0 || !Number.isFinite(lambda) ? 1 : Math.min(lambda, maximum) / maximum;\n }\n\n // hdbscan 0.8.44 propagates maximum density through the condensed tree in\n // reverse edge order, so each parent sees maxima already resolved below it.\n for (let index = tree.length - 1; index >= 0; index--) {\n const edge = tree[index];\n if (deaths[edge.child] > deaths[edge.parent]) {\n deaths[edge.parent] = deaths[edge.child];\n }\n }\n const outlierScores = new Float64Array(count);\n for (let point = 0; point < count; point++) {\n const edge = pointEdges[point];\n const maximum = deaths[edge.parent];\n if (maximum === 0 || !Number.isFinite(edge.lambda)) {\n outlierScores[point] = 0;\n } else if (!Number.isFinite(maximum)) {\n // hdbscan 0.8.44 returns NaN for (Infinity - finite) / Infinity.\n // Use the finite perturbation limit so public outputs remain finite.\n outlierScores[point] = 1;\n } else {\n outlierScores[point] = (maximum - edge.lambda) / maximum;\n }\n }\n if (\n probabilities.some((value) => !Number.isFinite(value)) ||\n outlierScores.some((value) => !Number.isFinite(value))\n ) {\n throw new Error(\"HDBSCAN produced non-finite point scores.\");\n }\n return { labels, probabilities, outlierScores };\n}\n\n/** Match a C float accumulator, including rounding after every addition. */\nexport function accumulateFloat32(values: number[]): number {\n let total = 0;\n for (const value of values) total = Math.fround(total + value);\n return total;\n}\n\nfunction directMaximumLambdas(tree: CondensedEdge[], maximumParent: number): Float64Array {\n const deaths = new Float64Array(maximumParent + 1);\n for (const edge of tree) {\n deaths[edge.parent] = Math.max(deaths[edge.parent], edge.lambda);\n }\n return deaths;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { PreparedNumericFeatures } from \"./prepareNumericFeatures.ts\";\nimport foldIdentifier from \"./foldIdentifier.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\ntype PublicationOutput = {\n /** Raw output-column name. */\n name: string;\n /** Trusted internal SQL evaluated with the prepared relation aliased as p. */\n expression: string;\n /** Raw source-column name to replace in its original position. */\n replace?: string;\n};\n\ntype PublicationResult = {\n /** Raw relation name joined to the prepared rows. */\n relation: string;\n /** Raw row-identity column in the result relation. */\n rowIdColumn: string;\n};\n\n/**\n * Publishes validated algorithm outputs from a prepared numeric\n * feature snapshot. New outputs are appended, while replacements retain the\n * source column's position. Existing native DuckDB indexes are recreated after\n * table replacement because CREATE OR REPLACE drops them.\n *\n * Output expressions are trusted internal SQL. They may reference `p`, the\n * prepared relation alias, and `r` when a result relation is supplied. The\n * consumer must fully compute and validate one result row per prepared row\n * before calling this helper, and remains responsible for scratch cleanup.\n */\nexport default async function publishPreparedColumns(\n table: SimpleTable,\n prepared: Pick<\n PreparedNumericFeatures,\n \"relation\" | \"rowIdColumn\" | \"sourceColumns\" | \"sourceTemporary\"\n >,\n options: {\n method: string;\n parameters: { [key: string]: unknown } | null;\n outputs: PublicationOutput[];\n result?: PublicationResult;\n },\n): Promise<void> {\n validateOutputs(prepared.sourceColumns, options.outputs);\n\n const connection = table.connection!;\n const q = quoteIdentifier;\n const source = q(table.name);\n const tableDetails = (\n await connection.runAndReadAll(\n `SELECT table_oid FROM duckdb_tables()\n WHERE translate(table_name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = $1\n AND schema_name = current_schema()\n AND database_name IN (current_database(), 'temp')\n AND temporary = $2\n LIMIT 1`,\n [foldIdentifier(table.name), prepared.sourceTemporary],\n )\n ).getRowsJS()[0];\n if (tableDetails === undefined) {\n throw new Error(`${options.method} requires a materialized source table.`);\n }\n const tableOid = tableDetails[0];\n if (typeof tableOid !== \"number\" && typeof tableOid !== \"bigint\") {\n throw new Error(`${options.method} could not identify the source table.`);\n }\n\n const indexes = (\n await connection.runAndReadAll(\n \"SELECT sql FROM duckdb_indexes() WHERE table_oid = $1 ORDER BY index_name\",\n [tableOid],\n )\n )\n .getRowsJS()\n .map((row) => {\n if (typeof row[0] !== \"string\") throw new Error(\"Expected index SQL to be a string.\");\n return row[0];\n });\n const replacements = new Map(\n options.outputs\n .filter((output) => output.replace !== undefined)\n .map((output) => [foldIdentifier(output.replace!), output]),\n );\n const select = prepared.sourceColumns.map((column) => {\n const replacement = replacements.get(foldIdentifier(column));\n return replacement === undefined\n ? `p.${q(column)}`\n : `${replacement.expression} AS ${q(column)}`;\n });\n for (const output of options.outputs) {\n if (output.replace === undefined) {\n select.push(`${output.expression} AS ${q(output.name)}`);\n }\n }\n const resultJoin =\n options.result === undefined\n ? \"\"\n : ` JOIN ${q(options.result.relation)} r\n ON p.${q(prepared.rowIdColumn)} = r.${q(options.result.rowIdColumn)}`;\n\n await queryDB(\n table,\n `CREATE OR REPLACE ${prepared.sourceTemporary ? \"TEMP \" : \"\"}TABLE ${source} AS\n SELECT ${select.join(\", \")}\n FROM ${q(prepared.relation)} p${resultJoin}\n ORDER BY p.${q(prepared.rowIdColumn)}`,\n mergeOptions(table, {\n table: table.name,\n method: options.method,\n parameters: options.parameters,\n noClean: true,\n }),\n );\n for (const sql of indexes) {\n try {\n await connection.run(sql);\n } catch (error) {\n const detail = error instanceof Error ? ` ${error.message}` : \"\";\n throw new Error(\n `${options.method} could not restore an existing DuckDB index while publishing its output. Remove or rebuild indexes that do not support the output column types.${detail}`,\n { cause: error },\n );\n }\n }\n}\n\nfunction validateOutputs(sourceColumns: string[], outputs: PublicationOutput[]): void {\n const outputNames = new Set<string>();\n const replacements = new Set<string>();\n for (const output of outputs) {\n const outputName = foldIdentifier(output.name);\n if (outputNames.has(outputName)) {\n throw new Error(\n `Internal publication received duplicate output column ${quoteIdentifier(output.name)}.`,\n );\n }\n outputNames.add(outputName);\n if (output.replace === undefined) {\n if (sourceColumns.some((column) => foldIdentifier(column) === outputName)) {\n throw new Error(\n `Internal publication cannot append existing column ${quoteIdentifier(output.name)}.`,\n );\n }\n continue;\n }\n const replacement = foldIdentifier(output.replace);\n if (outputName !== replacement) {\n throw new Error(\n `Internal publication output ${quoteIdentifier(\n output.name,\n )} must match its replacement column ${quoteIdentifier(output.replace)}.`,\n );\n }\n if (!sourceColumns.some((column) => foldIdentifier(column) === replacement)) {\n throw new Error(\n `Internal publication cannot replace missing column ${quoteIdentifier(output.replace)}.`,\n );\n }\n if (replacements.has(replacement)) {\n throw new Error(\n `Internal publication received duplicate replacement column ${quoteIdentifier(\n output.replace,\n )}.`,\n );\n }\n replacements.add(replacement);\n }\n}\n","import { DOUBLE, INTEGER, VARCHAR } from \"@duckdb/node-api\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport appendColumnBatches from \"../helpers/appendColumnBatches.ts\";\nimport buildApproximateMutualReachabilityMst from \"../helpers/buildApproximateMutualReachabilityMst.ts\";\nimport buildExactMutualReachabilityMst from \"../helpers/buildExactMutualReachabilityMst.ts\";\nimport clusterHdbscan from \"../helpers/clusterHdbscan.ts\";\nimport foldIdentifier from \"../helpers/foldIdentifier.ts\";\nimport prepareNumericFeatures from \"../helpers/prepareNumericFeatures.ts\";\nimport publishPreparedColumns from \"../helpers/publishPreparedColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype Options = NonNullable<Parameters<SimpleTable[\"hdbscan\"]>[2]>;\n\nexport default function hdbscan(\n table: SimpleTable,\n columns: string | string[],\n newColumn: string,\n options: Options = {},\n): void {\n const selected = typeof columns === \"string\" ? columns : [...columns];\n const settings = structuredClone(options);\n queueOp(table, {\n kind: \"barrier\",\n method: \"hdbscan()\",\n parameters: { columns: selected, newColumn, options: settings },\n execute: () => execute(table, selected, newColumn, settings),\n });\n}\n\nasync function execute(\n table: SimpleTable,\n columns: string | string[],\n newColumn: string,\n options: Options,\n): Promise<void> {\n const {\n minClusterSize = 5,\n metric = \"euclidean\",\n allowSingleCluster = false,\n approximate = false,\n membershipScoreColumn,\n outlierScoreColumn,\n } = options;\n const minSamples = options.minSamples ?? minClusterSize;\n if (typeof newColumn !== \"string\") {\n throw new Error(\"hdbscan() newColumn must be a string.\");\n }\n if (!Number.isSafeInteger(minClusterSize) || minClusterSize < 2) {\n throw new Error(\"hdbscan() minClusterSize must be a safe integer of at least 2.\");\n }\n if (!Number.isSafeInteger(minSamples) || minSamples < 1) {\n throw new Error(\"hdbscan() minSamples must be a safe integer of at least 1.\");\n }\n if (!([\"euclidean\", \"cosine\"] as unknown[]).includes(metric)) {\n throw new Error('hdbscan() metric must be \"euclidean\" or \"cosine\".');\n }\n if (typeof allowSingleCluster !== \"boolean\") {\n throw new Error(\"hdbscan() allowSingleCluster must be a boolean.\");\n }\n if (typeof approximate !== \"boolean\") {\n throw new Error(\"hdbscan() approximate must be a boolean.\");\n }\n if (membershipScoreColumn !== undefined && typeof membershipScoreColumn !== \"string\") {\n throw new Error(\"hdbscan() membershipScoreColumn must be a string.\");\n }\n if (outlierScoreColumn !== undefined && typeof outlierScoreColumn !== \"string\") {\n throw new Error(\"hdbscan() outlierScoreColumn must be a string.\");\n }\n\n const sourceColumns = Object.keys(await table.getTypes());\n const outputNames = [newColumn, membershipScoreColumn, outlierScoreColumn].filter(\n (name): name is string => name !== undefined,\n );\n validateOutputNames(sourceColumns, outputNames);\n\n const prepared = await prepareNumericFeatures(\n table,\n typeof columns === \"string\"\n ? { kind: \"vector\", column: columns }\n : { kind: \"scalars\", columns },\n { method: \"hdbscan()\" },\n );\n const connection = table.connection!;\n const suffix = crypto.randomUUID().replaceAll(\"-\", \"\");\n const name = (part: string) => `__sda_hdbscan_${suffix}_${part}`;\n const names = {\n rows: name(\"rows\"),\n neighbors: name(\"neighbors\"),\n search: name(\"search\"),\n hnsw: name(\"hnsw\"),\n candidates: name(\"candidates\"),\n coreDistances: name(\"core_distances\"),\n frontier: name(\"frontier\"),\n edges: name(\"edges\"),\n components: name(\"components\"),\n representatives: name(\"representatives\"),\n componentPairs: name(\"component_pairs\"),\n bridgeCandidates: name(\"bridge_candidates\"),\n mst: name(\"mst\"),\n result: name(\"result\"),\n };\n try {\n if (prepared.rowCount < 2) {\n throw new Error(\n `hdbscan() requires at least 2 rows, but the input has ${prepared.rowCount}.`,\n );\n }\n if (prepared.rowCount > 0x40000000) {\n throw new Error(\n \"hdbscan() supports at most 1073741824 rows because its 2*n-1 hierarchy nodes use signed INTEGER identifiers.\",\n );\n }\n if (minSamples >= prepared.rowCount) {\n const defaulted = options.minSamples === undefined ? \" (defaulted from minClusterSize)\" : \"\";\n throw new Error(\n `hdbscan() minSamples is ${minSamples}${defaulted}, but ${prepared.rowCount} rows provide at most ${\n prepared.rowCount - 1\n } other point${prepared.rowCount === 2 ? \"\" : \"s\"}. Set minSamples between 1 and ${\n prepared.rowCount - 1\n }, or provide at least ${minSamples + 1} rows.`,\n );\n }\n if (minClusterSize > prepared.rowCount) {\n throw new Error(\n `hdbscan() minClusterSize is ${minClusterSize}, but the input has ${prepared.rowCount} rows. Set minClusterSize between 2 and ${prepared.rowCount}, or provide more rows.`,\n );\n }\n const q = quoteIdentifier;\n await connection.run(\n `CREATE TEMP TABLE ${q(names.rows)} AS\n SELECT ${q(prepared.rowIdColumn)}::INTEGER AS vertex,\n ${q(prepared.vectorColumn)} AS vec\n FROM ${q(prepared.relation)}\n ORDER BY ${q(prepared.rowIdColumn)}`,\n );\n if (approximate) {\n await buildApproximateMutualReachabilityMst(\n connection,\n {\n count: prepared.rowCount,\n dimensions: prepared.dimensions,\n minSamples,\n },\n { metric },\n {\n rows: names.rows,\n neighbors: names.neighbors,\n search: names.search,\n hnsw: names.hnsw,\n candidates: names.candidates,\n coreDistances: names.coreDistances,\n edges: names.edges,\n components: names.components,\n representatives: names.representatives,\n componentPairs: names.componentPairs,\n bridgeCandidates: names.bridgeCandidates,\n mst: names.mst,\n },\n );\n } else {\n await buildExactMutualReachabilityMst(\n connection,\n { count: prepared.rowCount, minSamples },\n { metric },\n {\n rows: q(names.rows),\n coreDistances: q(names.coreDistances),\n frontier: q(names.frontier),\n mst: q(names.mst),\n },\n );\n }\n const result = await clusterHdbscan(connection, q(names.mst), {\n count: prepared.rowCount,\n minClusterSize,\n allowSingleCluster,\n });\n const labelColumn = \"label\";\n const membershipColumn = \"membership\";\n const gloshColumn = \"glosh\";\n const resultColumns = [\n \"row_id INTEGER\",\n `${labelColumn} VARCHAR`,\n membershipScoreColumn === undefined ? undefined : `${membershipColumn} DOUBLE`,\n outlierScoreColumn === undefined ? undefined : `${gloshColumn} DOUBLE`,\n ].filter((definition): definition is string => definition !== undefined);\n await connection.run(`CREATE TEMP TABLE ${q(names.result)} (${resultColumns.join(\",\")})`);\n const outputTypes = [\n INTEGER,\n VARCHAR,\n ...(membershipScoreColumn === undefined ? [] : [DOUBLE]),\n ...(outlierScoreColumn === undefined ? [] : [DOUBLE]),\n ];\n await appendColumnBatches(\n connection,\n names.result,\n outputTypes,\n prepared.rowCount,\n (column, start, end) => {\n if (column === 0) {\n return Array.from({ length: end - start }, (_, offset) => start + offset);\n }\n if (column === 1) {\n return Array.from(result.labels.subarray(start, end), (label) =>\n label < 0 ? \"noise\" : `cluster-${label}`,\n );\n }\n const membershipIndex = membershipScoreColumn === undefined ? -1 : 2;\n return Array.from(\n column === membershipIndex\n ? result.probabilities.subarray(start, end)\n : result.outlierScores.subarray(start, end),\n );\n },\n );\n const publicationOutputs = [\n {\n name: newColumn,\n expression: `r.${q(labelColumn)}`,\n },\n ];\n if (membershipScoreColumn !== undefined) {\n publicationOutputs.push({\n name: membershipScoreColumn,\n expression: `r.${q(membershipColumn)}`,\n });\n }\n if (outlierScoreColumn !== undefined) {\n publicationOutputs.push({\n name: outlierScoreColumn,\n expression: `r.${q(gloshColumn)}`,\n });\n }\n await publishPreparedColumns(table, prepared, {\n method: \"hdbscan()\",\n parameters: { columns, newColumn, options },\n result: { relation: names.result, rowIdColumn: \"row_id\" },\n outputs: publicationOutputs,\n });\n } finally {\n for (const relation of Object.entries(names)\n .reverse()\n .flatMap(([key, value]) => (key === \"hnsw\" ? [] : [value]))) {\n await connection.run(`DROP TABLE IF EXISTS ${quoteIdentifier(relation)}`);\n }\n await prepared.cleanup();\n }\n}\n\nfunction validateOutputNames(sourceColumns: string[], outputNames: string[]): void {\n const seen = new Map<string, string>();\n for (const name of outputNames) {\n if (name.length === 0 || name.includes(\"\\0\")) {\n throw new Error(\n \"hdbscan() output column names must be non-empty strings without null characters.\",\n );\n }\n const folded = foldIdentifier(name);\n const source = sourceColumns.find((column) => foldIdentifier(column) === folded);\n if (source !== undefined) {\n throw new Error(\n `hdbscan() cannot create ${quoteIdentifier(\n name,\n )} because that source column already exists. Remove it first or choose different output names.`,\n );\n }\n const duplicate = seen.get(folded);\n if (duplicate !== undefined) {\n throw new Error(\n `hdbscan() output columns ${quoteIdentifier(duplicate)} and ${quoteIdentifier(\n name,\n )} refer to the same column. Choose distinct output names.`,\n );\n }\n seen.set(folded, name);\n }\n}\n","const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\n// Keep combining characters attached to their base without normalizing text.\n// Grapheme counts are not terminal display widths for wide characters or emoji.\nexport default function splitGraphemes(text: string): string[] {\n return Array.from(segmenter.segment(text), ({ segment }) => segment);\n}\n","import splitGraphemes from \"./splitGraphemes.ts\";\n\n/**\n * Wraps a string to a specified maximum width, attempting to break at word\n * boundaries when possible. If a single word exceeds the maximum width, it\n * will be broken at a grapheme boundary, keeping combining accents with their\n * letters. This function is primarily used for preparing text to be displayed\n * in console tables. Widths count graphemes, not terminal columns for wide\n * characters or emoji.\n *\n * @example\n * ```typescript\n * const text = \"This is a very long sentence that needs to be wrapped\";\n * const wrapped = wrapString(text, 20);\n * console.log(wrapped);\n * // Output:\n * // This is a very long\n * // sentence that needs\n * // to be wrapped\n * ```\n *\n * @example\n * ```typescript\n * // Character-based wrapping (no word boundaries)\n * const text = \"Thisisaverylongword\";\n * const wrapped = wrapString(text, 10, false);\n * // Output: Thisisaver\n * // ylongword\n * ```\n *\n * @param str - The string to wrap.\n *\n * @param maxWidth - The maximum number of graphemes in each line.\n *\n * @param wordWrap - If true, attempts to break at word boundaries. If false,\n * breaks at grapheme boundaries. Defaults to `true`.\n *\n * @returns The wrapped string with newline characters inserted at appropriate\n * positions.\n */\nexport default function wrapString(str: string, maxWidth: number, wordWrap = true): string {\n const graphemes = splitGraphemes(str);\n if (graphemes.length <= maxWidth) {\n return str;\n }\n\n if (!wordWrap) {\n // Simple grapheme-based wrapping\n const lines: string[] = [];\n for (let i = 0; i < graphemes.length; i += maxWidth) {\n lines.push(graphemes.slice(i, i + maxWidth).join(\"\"));\n }\n return lines.join(\"\\n\");\n }\n\n // Word-aware wrapping\n const lines: string[] = [];\n let currentLine = \"\";\n let currentWidth = 0;\n\n const words = str.split(/(\\s+)/); // Split but keep whitespace\n\n for (const word of words) {\n const wordGraphemes = splitGraphemes(word);\n const wordWidth = wordGraphemes.length;\n // If adding this word would exceed maxWidth\n if (currentWidth + wordWidth > maxWidth) {\n // If current line is not empty, save it\n if (currentLine.length > 0) {\n lines.push(currentLine.trimEnd());\n currentLine = \"\";\n currentWidth = 0;\n }\n\n // If the word itself is longer than maxWidth, break it\n if (wordWidth > maxWidth) {\n for (let i = 0; i < wordWidth; i += maxWidth) {\n const chunk = wordGraphemes.slice(i, i + maxWidth).join(\"\");\n if (i + maxWidth < wordWidth) {\n lines.push(chunk);\n } else {\n currentLine = chunk;\n currentWidth = wordWidth - i;\n }\n }\n } else {\n currentLine = word;\n currentWidth = wordWidth;\n }\n } else {\n currentLine += word;\n currentWidth += wordWidth;\n }\n }\n\n // Add any remaining text\n if (currentLine.length > 0) {\n lines.push(currentLine.trimEnd());\n }\n\n return lines.join(\"\\n\");\n}\n","import LogValue from \"./LogValue.ts\";\nimport splitGraphemes from \"./splitGraphemes.ts\";\nimport wrapString from \"./wrapString.ts\";\n\n/**\n * Prints a formatted table to the console with support for word wrapping\n * within headers and cells. Unlike `console.table()`, this function properly\n * handles multi-line content, making it ideal for displaying data with long\n * column names and text values.\n * Widths count graphemes, keeping combining accents with their letters. Wide\n * characters and emoji are not measured by their terminal display width.\n *\n * @example\n * ```typescript\n * const data = [\n * { name: \"Alice\", description: \"A software engineer with expertise in TypeScript\" },\n * { name: \"Bob\", description: \"A product manager\" }\n * ];\n * printTable(data, { maxColumnWidth: 30 });\n * // Outputs a nicely formatted table with word-wrapped description column\n * ```\n *\n * @example\n * ```typescript\n * // With types row\n * const types = { name: \"VARCHAR/string\", age: \"INTEGER/number\" };\n * const data = [\n * { name: \"Alice\", age: 30 },\n * { name: \"Bob\", age: 25 }\n * ];\n * printTable([types, ...data], { typesRowIndex: 0 });\n * ```\n *\n * @param data - An array of objects representing the rows of the table. Each\n * object should have string keys.\n *\n * @param options - Optional configuration for table rendering.\n *\n * @param options.maxColumnWidth - The maximum width for any column (default:\n * `75`). Headers and values exceeding this width will be wrapped at word\n * boundaries.\n *\n * @param options.minColumnWidth - The minimum width for any column (default:\n * `3`).\n *\n * @param options.typesRowIndex - The index of a row that contains type\n * annotations (e.g. `\"VARCHAR/string\"`). This row will be rendered in grey.\n * If omitted, no row is treated as a types row.\n *\n * @returns void - The table is printed directly to the console.\n */\nexport default function printTable(\n data: { [key: string]: unknown }[],\n options?: {\n maxColumnWidth?: number;\n minColumnWidth?: number;\n typesRowIndex?: number;\n },\n): void {\n if (!data || data.length === 0) {\n console.log(\"(empty table)\");\n return;\n }\n\n const maxColumnWidth = options?.maxColumnWidth ?? 75;\n const minColumnWidth = options?.minColumnWidth ?? 3;\n\n // Helper function to format values for display\n const formatValue = (value: unknown): string => {\n if (value instanceof LogValue) return value.text;\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? \"Invalid Date\" : value.toISOString();\n }\n return String(value);\n };\n\n // Get all column names\n const columns = Object.keys(data[0]);\n\n if (columns.length === 0) {\n console.log(\"(empty table)\");\n return;\n }\n\n // Single pass: calculate column widths and prepare wrapped data.\n // First, seed widths from header names.\n const columnWidths: { [key: string]: number } = {};\n for (const col of columns) {\n columnWidths[col] = Math.max(...col.split(\"\\n\").map((line) => splitGraphemes(line).length));\n }\n\n // Format every cell, track the longest raw line per column, and\n // store the formatted strings for the wrapping step that follows.\n const formattedData: string[][] = [];\n for (const row of data) {\n const formattedRow: string[] = [];\n for (let c = 0; c < columns.length; c++) {\n const col = columns[c];\n const value = formatValue(row[col]);\n formattedRow.push(value);\n\n // Track longest line (handles embedded newlines)\n const lines = value.split(\"\\n\");\n let longestLine = 0;\n for (const line of lines) {\n const length = splitGraphemes(line).length;\n if (length > longestLine) longestLine = length;\n }\n if (longestLine > columnWidths[col]) {\n columnWidths[col] = longestLine;\n }\n }\n formattedData.push(formattedRow);\n }\n\n // Apply min/max constraints\n for (const col of columns) {\n columnWidths[col] = Math.min(Math.max(columnWidths[col], minColumnWidth), maxColumnWidth);\n }\n\n // Use the same newline and word wrapping rules for headers and cells.\n const wrapCell = (value: string, width: number): string[] => {\n const lines = value\n .split(\"\\n\")\n .flatMap((line) =>\n splitGraphemes(line).length <= width ? [line] : wrapString(line, width).split(\"\\n\"),\n );\n return lines.length > 0 ? lines : [\"\"];\n };\n const wrappedHeaders = columns.map((col) => wrapCell(col, columnWidths[col]));\n const wrappedData = formattedData.map((row) =>\n Object.fromEntries(columns.map((col, c) => [col, wrapCell(row[c], columnWidths[col])])),\n );\n\n // ANSI console color codes\n const colors = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n grey: \"\\x1b[90m\",\n string: \"\\x1b[32m\", // green\n number: \"\\x1b[33m\", // yellow\n boolean: \"\\x1b[95m\", // bright magenta/pink\n date: \"\\x1b[36m\", // cyan\n null: \"\\x1b[90m\", // grey\n };\n\n // Helper function to get color for a value based on its actual JavaScript type\n const getColorForValue = (value: unknown, isTypeRow: boolean): string => {\n if (isTypeRow) return colors.grey;\n if (value instanceof LogValue) return colors[value.category];\n if (value === null || value === undefined) return colors.null;\n if (value instanceof Date) return colors.date;\n if (typeof value === \"boolean\") return colors.boolean;\n if (typeof value === \"number\") return colors.number;\n return colors.string;\n };\n\n // Helper function to create a horizontal border line with column junctions\n const createBorderLine = (left: string, middle: string, right: string) => {\n const segments = columns.map((col) => \"─\".repeat(columnWidths[col] + 2));\n return colors.grey + left + segments.join(middle) + right + colors.reset;\n };\n\n // Helper function to create a separator line\n const createSeparator = () => createBorderLine(\"├\", \"┼\", \"┤\");\n\n // Helper function to create the top border\n const createTopBorder = () => createBorderLine(\"┌\", \"┬\", \"┐\");\n\n // Helper function to create the bottom border\n const createBottomBorder = () => createBorderLine(\"└\", \"┴\", \"┘\");\n\n // Helper function to pad a string to a specific width\n const pad = (str: string, width: number) => {\n return str + \" \".repeat(Math.max(0, width - splitGraphemes(str).length));\n };\n\n // Print top border\n console.log(createTopBorder());\n\n // Print each header line in bold, padding shorter headers to the same height.\n const headerHeight = Math.max(...wrappedHeaders.map((lines) => lines.length));\n for (let lineIdx = 0; lineIdx < headerHeight; lineIdx++) {\n const headerParts = columns.map(\n (col, c) =>\n ` ${colors.bold}${pad(\n wrappedHeaders[c][lineIdx] ?? \"\",\n columnWidths[col],\n )}${colors.reset} `,\n );\n console.log(\n colors.grey +\n \"│\" +\n colors.reset +\n headerParts.join(colors.grey + \"│\" + colors.reset) +\n colors.grey +\n \"│\" +\n colors.reset,\n );\n }\n\n // Detect if any row has word wrapping (spans multiple lines)\n let hasWordWrapping = false;\n for (const wrappedRow of wrappedData) {\n for (const col of columns) {\n if (wrappedRow[col].length > 1) {\n hasWordWrapping = true;\n break;\n }\n }\n if (hasWordWrapping) break;\n }\n\n // Print separator after header (unless the first row is the types row,\n // in which case the separator is printed after the types row instead)\n if (options?.typesRowIndex !== 0) {\n console.log(createSeparator());\n }\n\n // Print data rows\n for (let i = 0; i < wrappedData.length; i++) {\n const wrappedRow = wrappedData[i];\n const originalRow = data[i];\n const isTypeRow = i === options?.typesRowIndex;\n\n // Find the maximum number of lines in this row\n let maxLines = 1;\n for (const col of columns) {\n if (wrappedRow[col].length > maxLines) {\n maxLines = wrappedRow[col].length;\n }\n }\n\n // Print each line of this row\n for (let lineIdx = 0; lineIdx < maxLines; lineIdx++) {\n const lineParts = columns.map((col) => {\n const lines = wrappedRow[col];\n const lineValue = lineIdx < lines.length ? lines[lineIdx] : \"\";\n const color = getColorForValue(originalRow[col], isTypeRow);\n return ` ${color}${pad(lineValue, columnWidths[col])}${colors.reset} `;\n });\n console.log(\n colors.grey +\n \"│\" +\n colors.reset +\n lineParts.join(colors.grey + \"│\" + colors.reset) +\n colors.grey +\n \"│\" +\n colors.reset,\n );\n }\n\n // Print separator after types row\n if (isTypeRow) {\n console.log(createSeparator());\n } // Print separator between rows when word wrapping is present (except after last row)\n else if (hasWordWrapping && i < wrappedData.length - 1) {\n console.log(createSeparator());\n }\n }\n\n // Print bottom border\n console.log(createBottomBorder());\n}\n","import LogValue from \"./LogValue.ts\";\nimport printTable from \"./printTable.ts\";\n\nexport default function logData(\n types: { [key: string]: string } | null,\n data: { [key: string]: unknown }[] | null,\n charsToLog?: number,\n) {\n if (data === null) {\n console.log(\"Data is null\");\n return;\n }\n if (data.length === 0) {\n console.log(data);\n return;\n }\n const formatted = data.map((row) =>\n Object.fromEntries(\n Object.entries(row).map(([key, value]) => {\n const nested =\n value !== null &&\n typeof value === \"object\" &&\n !(value instanceof Date) &&\n !(value instanceof LogValue);\n let text = value instanceof LogValue ? value.text : nested ? JSON.stringify(value) : value;\n const truncatable = !(value instanceof LogValue) || value.category === \"string\";\n if (\n truncatable &&\n typeof text === \"string\" &&\n typeof charsToLog === \"number\" &&\n text.length > charsToLog\n ) {\n const limit = Math.max(0, Math.floor(charsToLog));\n text = text.slice(0, Math.max(0, limit - 3)) + \"...\".slice(0, limit);\n }\n return [\n key,\n value instanceof LogValue\n ? new LogValue(\n typeof text === \"string\" ? text : value.text,\n value.jsType,\n value.category,\n )\n : text,\n ];\n }),\n ),\n );\n const hasTypes = types !== null && Object.keys(types).length > 0;\n if (hasTypes) {\n formatted.unshift(\n Object.fromEntries(\n Object.entries(types).map(([key, sqlType]) => {\n const representations = new Set(\n data.flatMap((row) => {\n const value = row[key];\n if (value instanceof LogValue) {\n return value.category === \"null\" ? [] : [value.jsType];\n }\n return value === null || value === undefined ? [] : [typeof value];\n }),\n );\n const first = data[0][key];\n const representation =\n representations.size > 0\n ? [...representations].join(\"|\")\n : first instanceof LogValue\n ? first.jsType\n : \"null\";\n return [key, `${sqlType}/${representation}`];\n }),\n ),\n );\n }\n printTable(formatted, hasTypes ? { typesRowIndex: 0 } : undefined);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getBottom(\n simpleTable: SimpleTable,\n count: number,\n options: {\n originalOrder?: boolean;\n conditions?: string;\n } = {},\n method: \"getBottom()\" | \"logBottom()\" = \"getBottom()\",\n) {\n const queryResult = await queryDB(\n simpleTable,\n `WITH \"numberedRowsForGetBottom\" AS (\n SELECT *, row_number() OVER () as \"rowNumberForGetBottom\" FROM ${quoteIdentifier(\n simpleTable.name,\n )}${options.conditions ? ` WHERE ${options.conditions}` : \"\"}\n )\n SELECT * FROM \"numberedRowsForGetBottom\" ORDER BY \"rowNumberForGetBottom\" DESC LIMIT ${count};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method,\n parameters: { count, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const rowsRaw = queryResult.map((d) => {\n delete d.rowNumberForGetBottom;\n return d;\n });\n const rows = options.originalOrder ? rowsRaw.reverse() : rowsRaw;\n\n return rows;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport logData from \"../helpers/logData.ts\";\nimport getBottom from \"./getBottom.ts\";\n\nexport default async function logBottom(\n simpleTable: SimpleTable,\n count?: number,\n options: { originalOrder?: boolean } = {},\n) {\n const rows = count ?? simpleTable.rowsToLog;\n console.log(`\\nTable ${simpleTable.name} (${rows} bottom rows):`);\n const data = await getBottom(simpleTable, rows, options, \"logBottom()\");\n logData(null, data, simpleTable.charsToLog);\n return;\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/**\n * Quotes a SQL identifier together with the relation that owns it.\n *\n * Qualifying column references prevents DuckDB from resolving a relation name\n * as its row struct when a missing column has the same name as the relation.\n *\n * @example\n * ```ts\n * quoteQualifiedIdentifier(\"people\", \"full name\");\n * // '\"people\".\"full name\"'\n * ```\n *\n * @param relation - The table or relation containing the identifier.\n *\n * @param identifier - The identifier to qualify.\n *\n * @returns The separately quoted relation and identifier joined by a period.\n */\nexport default function quoteQualifiedIdentifier(relation: string, identifier: string): string {\n return `${quoteIdentifier(relation)}.${quoteIdentifier(identifier)}`;\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getData(\n simpleTable: SimpleTable,\n options: {\n columns?: string | string[];\n conditions?: string;\n limit?: number;\n } = {},\n method: \"getData()\" | \"log()\" = \"getData()\",\n) {\n if (options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 0)) {\n throw new Error(\"getData() limit must be an integer greater than or equal to 0.\");\n }\n const columns = options.columns\n ? typeof options.columns === \"string\"\n ? [options.columns]\n : options.columns\n : undefined;\n return (await queryDB(\n simpleTable,\n `SELECT ${\n columns\n ? columns.map((column) => quoteQualifiedIdentifier(simpleTable.name, column)).join(\", \")\n : \"*\"\n } from ${quoteIdentifier(simpleTable.name)}${\n options.conditions ? ` WHERE ${options.conditions}` : \"\"\n }${options.limit === undefined ? \"\" : ` LIMIT ${options.limit}`}`,\n mergeOptions(simpleTable, {\n returnData: true,\n table: simpleTable.name,\n method,\n parameters: { options },\n }),\n )) as {\n [key: string]: unknown;\n }[];\n}\n","/**\n * Rounds a number based on specified criteria: a fixed number of decimal places or to a specific number of significant digits.\n *\n * @example\n * ```ts\n * // Round to one decimal place.\n * const result = round(1234.567, { decimals: 1 });\n * console.log(result); // 1234.6\n * ```\n *\n * @example\n * ```ts\n * // Round to 3 significant digits.\n * const result = round(0.004622, { significantDigits: 3 });\n * console.log(result); // 0.00462\n * ```\n *\n * @param number - The number to be rounded.\n *\n * @param options - An object containing options for rounding.\n *\n * @param options.decimals - The number of decimal places to keep when rounding.\n *\n * @param options.significantDigits - The number of significant digits to retain.\n *\n * @returns The rounded number.\n *\n * @throws {Error} If more than one rounding option is provided.\n */\nfunction round(\n number: number,\n options: {\n decimals?: number;\n significantDigits?: number;\n } = {},\n): number {\n if (typeof options.decimals === \"number\" && typeof options.significantDigits === \"number\") {\n throw new Error(\"You can't use options decimals and significantDigits together. Pick one.\");\n }\n\n if (typeof options.decimals === \"number\") {\n return parseFloat(number.toFixed(options.decimals));\n } else if (typeof options.significantDigits === \"number\") {\n return parseFloat(number.toPrecision(options.significantDigits));\n } else {\n return Math.round(number);\n }\n}\n\n/**\n * Formats a number with thousands separators, decimals, abbreviations, and more.\n *\n * @example\n * ```ts\n * // Basic usage: Format a number with thousands separator.\n * const num1 = formatNumber(1234567.89);\n * console.log(num1); // \"1,234,567.89\"\n * ```\n *\n * @example\n * ```ts\n * // With significant digits and suffix.\n * const num2 = formatNumber(66.666, { significantDigits: 3, suffix: \"%\" });\n * console.log(num2); // \"66.7%\"\n * ```\n *\n * @example\n * ```ts\n * // Abbreviation.\n * const num3 = formatNumber(12000, { abbreviation: true });\n * console.log(num3); // \"12K\"\n * ```\n *\n * @example\n * ```ts\n * // With decimal places.\n * const num4 = formatNumber(123.456, { decimals: 1 });\n * console.log(num4); // \"123.5\"\n * ```\n *\n * @param number - The number to be formatted.\n *\n * @param options - An object containing various formatting options.\n *\n * @param options.decimals - The number of decimal places to round to.\n *\n * @param options.significantDigits - The number of significant digits to round to.\n *\n * @param options.abbreviation - If `true`, the number will be abbreviated (e.g., 1,200,000 becomes \"1.2M\").\n *\n * @param options.prefix - A string to prepend before the formatted number.\n *\n * @param options.suffix - A string to append after the formatted number.\n *\n * @returns The formatted number as a string.\n */\nexport default function formatNumber(\n number: number,\n options: {\n decimals?: number;\n significantDigits?: number;\n abbreviation?: boolean;\n prefix?: string;\n suffix?: string;\n } = {},\n): string {\n if (typeof number !== \"number\") {\n throw new Error(\"Not a number\");\n }\n\n const mergedOptions: {\n decimals?: number;\n significantDigits?: number;\n abbreviation?: boolean;\n prefix: string;\n suffix: string;\n } = {\n prefix: \"\",\n suffix: \"\",\n ...options,\n };\n\n // Handle abbreviation (K/M/B/T)\n let abbreviation = \"\";\n if (mergedOptions.abbreviation && number !== 0) {\n const abbreviations = [\"\", \"K\", \"M\", \"B\", \"T\"];\n const index = Math.floor(Math.log10(Math.abs(number)) / 3);\n abbreviation = abbreviations[index] ?? \"\";\n number = number / Math.pow(10, index * 3);\n }\n\n // Round if needed\n if (\n typeof mergedOptions.decimals === \"number\" ||\n typeof mergedOptions.significantDigits === \"number\"\n ) {\n number = round(number, {\n decimals: mergedOptions.decimals,\n significantDigits: mergedOptions.significantDigits,\n });\n }\n\n // Format with thousands separator\n const regex = /\\B(?=(\\d{3})+(?!\\d))/g;\n const [integers, decimals] = number.toString().split(\".\");\n\n const formattedIntegers = integers.replace(regex, \",\");\n const formattedNumber = decimals ? `${formattedIntegers}.${decimals}` : formattedIntegers;\n\n // Handle dollar sign prefix placement (after minus sign for negative numbers)\n if (mergedOptions.prefix === \"$\") {\n if (formattedNumber.startsWith(\"-\")) {\n return `-${mergedOptions.prefix}${formattedNumber.slice(\n 1,\n )}${abbreviation}${mergedOptions.suffix}`;\n } else if (formattedNumber.startsWith(\"+\")) {\n return `+${mergedOptions.prefix}${formattedNumber.slice(\n 1,\n )}${abbreviation}${mergedOptions.suffix}`;\n } else {\n return `${mergedOptions.prefix}${formattedNumber}${abbreviation}${mergedOptions.suffix}`;\n }\n }\n\n return `${mergedOptions.prefix}${formattedNumber}${abbreviation}${mergedOptions.suffix}`;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport logData from \"../helpers/logData.ts\";\nimport getData from \"./getData.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport formatNumber from \"../helpers/formatNumber.ts\";\n\nexport default async function log(\n simpleTable: SimpleTable,\n options:\n | \"all\"\n | number\n | {\n count?: number | \"all\";\n types?: boolean;\n conditions?: string;\n } = {},\n) {\n if (simpleTable.connection === undefined) {\n await simpleTable.sdb.start();\n simpleTable.db = simpleTable.sdb.db;\n simpleTable.connection = simpleTable.sdb.connection;\n }\n if (simpleTable.connection === undefined) {\n throw new Error(\"simpleTable.connection is undefined\");\n }\n\n let count: number;\n if (typeof options === \"number\") {\n count = options;\n } else if (options === \"all\") {\n count = await simpleTable.getRowCount();\n } else if (typeof options === \"object\") {\n if (options.count === \"all\") {\n count = await simpleTable.getRowCount();\n } else if (typeof options.count === \"number\") {\n count = options.count;\n } else {\n count = simpleTable.rowsToLog;\n }\n } else {\n count = simpleTable.rowsToLog;\n }\n const types =\n typeof options === \"object\"\n ? (options.types ?? simpleTable.typesToLog)\n : simpleTable.typesToLog;\n const conditions = typeof options === \"object\" ? (options.conditions ?? undefined) : undefined;\n\n if (simpleTable.connection === undefined || !(await simpleTable.sdb.hasTable(simpleTable.name))) {\n console.log(`\\nTable ${simpleTable.name}: no data`);\n } else {\n console.log(`\\nTable ${simpleTable.name}:`);\n if (conditions) {\n console.log(`Conditions: ${conditions}`);\n }\n const data = await getData(simpleTable, { limit: count, conditions }, \"log()\");\n logData(types ? await simpleTable.getTypes() : null, data, simpleTable.charsToLog);\n const rowCount = conditions\n ? parseInt(\n (\n (await simpleTable.sdb.customQuery(\n `select count(*) as count from ${quoteIdentifier(\n simpleTable.name,\n )} where ${conditions}`,\n { returnData: true },\n )) as { count: string }[]\n )[0].count,\n )\n : await simpleTable.getRowCount();\n const displayedRows = data.length;\n const showing =\n displayedRows < rowCount ? ` / showing ${formatNumber(displayedRows)} rows` : \"\";\n console.log(`${formatNumber(rowCount)} rows in total${showing}`);\n }\n return;\n}\n","import stringifyUnknown from \"./stringifyUnknown.ts\";\n/*\n * Formatting subset of d3-dsv 3.0.1: https://github.com/d3/d3-dsv\n * Copyright 2013-2021 Mike Bostock\n *\n * Permission to use, copy, modify, and/or distribute this software for any purpose\n * with or without fee is hereby granted, provided that the above copyright notice\n * and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\n * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n * THIS SOFTWARE.\n */\n\nfunction pad(value: number, width: number): string {\n return String(value).padStart(width, \"0\");\n}\n\nfunction formatDate(date: Date): string {\n if (Number.isNaN(date.getTime())) return \"Invalid Date\";\n const year = date.getUTCFullYear();\n const formattedYear =\n year < 0 ? `-${pad(-year, 6)}` : year > 9999 ? `+${pad(year, 6)}` : pad(year, 4);\n const hours = date.getUTCHours();\n const minutes = date.getUTCMinutes();\n const seconds = date.getUTCSeconds();\n const milliseconds = date.getUTCMilliseconds();\n const day = `${formattedYear}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}`;\n const time = `${pad(hours, 2)}:${pad(minutes, 2)}`;\n return (\n day +\n (milliseconds\n ? `T${time}:${pad(seconds, 2)}.${pad(milliseconds, 3)}Z`\n : seconds\n ? `T${time}:${pad(seconds, 2)}Z`\n : minutes || hours\n ? `T${time}Z`\n : \"\")\n );\n}\n\nfunction formatValue(value: unknown): string {\n if (value == null) return \"\";\n if (value instanceof Date) return formatDate(value);\n const text = stringifyUnknown(value, \"default\");\n return /[\",\\n\\r]/.test(text) ? `\"${text.replaceAll('\"', '\"\"')}\"` : text;\n}\n\nexport default function csvFormat(\n rows: Record<string, unknown>[],\n columns?: string[] | null,\n): string {\n if (columns == null) {\n const seen = new Set<string>();\n columns = [];\n for (const row of rows) {\n for (const column in row) {\n if (!seen.has(column)) {\n seen.add(column);\n columns.push(column);\n }\n }\n }\n }\n const fields = columns;\n return [\n fields.map(formatValue).join(\",\"),\n ...rows.map((row) => fields.map((column) => formatValue(row[column])).join(\",\")),\n ].join(\"\\n\");\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getDescription(simpleTable: SimpleTable) {\n const types = await simpleTable.getTypes();\n const columns = await simpleTable.getColumns();\n const summaryForGetDescription = simpleTable.summarize({\n columns: columns,\n stats: [\"count\", \"countDistinct\", \"countNull\"],\n datesToMs: true,\n outputTable: \"summaryForGetDescription\",\n });\n const summaryData = await summaryForGetDescription.getData();\n\n await summaryForGetDescription.removeTable();\n\n // summarize adds the `column` output column only when it summarizes more than one\n // column; for a single-column table the column name is already known.\n const description = summaryData.map((d) => {\n const column = columns.length > 1 ? (d.column as string) : columns[0];\n return {\n column,\n type: types[column],\n count: d[\"count\"] as number,\n unique: d[\"countDistinct\"] as number,\n null: d[\"countNull\"] as number,\n };\n });\n\n return description;\n}\n","/**\n * Normalizes a string or array of strings to a new array.\n * Existing arrays are copied so callers can change the result independently.\n *\n * @example\n * ```ts\n * import { stringToArray } from \"@nshiab/simple-data-analysis-core/helpers\";\n * console.log(stringToArray(\"name\")); // [\"name\"]\n * console.log(stringToArray([\"name\", \"age\"])); // [\"name\", \"age\"]\n * ```\n *\n * @param argument - One string or an array of strings.\n *\n * @returns A new array containing the supplied strings.\n */\nexport default function stringToArray(argument: string | string[]): string[] {\n if (Array.isArray(argument)) {\n return [...argument];\n } else if (typeof argument === \"string\") {\n return [argument];\n } else {\n throw new Error(`argument should be a string or an array of strings.`);\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport type { DuckDBValue } from \"@duckdb/node-api\";\n\nexport default function removeMissing(\n simpleTable: SimpleTable,\n options: {\n columns?: string | string[];\n missingValues?: (string | number)[];\n invert?: boolean;\n } = {},\n) {\n options = structuredClone(options);\n const missingValues = options.missingValues ?? [\"undefined\", \"NaN\", \"null\", \"NULL\", \"\"];\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"removeMissing()\",\n parameters: { options },\n needsSchema: true,\n preservesSchema: true,\n values: (types) => {\n const columns = getRemoveMissingColumns(types, options.columns);\n return getRemoveMissingValues(types, columns, missingValues);\n },\n buildSelect: (input, types) => {\n const allColumns = Object.keys(types);\n return removeMissingSelect(\n input,\n allColumns,\n types,\n getRemoveMissingColumns(types, options.columns),\n { missingValues, invert: options.invert },\n );\n },\n });\n}\n\nfunction getRemoveMissingColumns(\n types: TableSchema,\n selectedColumns?: string | string[],\n): string[] {\n const columns = stringToArray(selectedColumns ?? []);\n return columns.length === 0 ? Object.keys(types) : columns;\n}\n\nfunction getRemoveMissingValues(\n types: TableSchema,\n columns: string[],\n missingValues: (string | number)[],\n): DuckDBValue[] {\n return columns.flatMap((column) =>\n missingValues.filter((missingValue) =>\n typeof missingValue === \"string\"\n ? types[column] === \"VARCHAR\"\n : [\"BIGINT\", \"DOUBLE\"].includes(types[column]),\n ),\n );\n}\n\nfunction removeMissingSelect(\n input: string,\n allColumns: string[],\n types: TableSchema,\n columns: string[],\n options: {\n missingValues?: (string | number)[];\n invert?: boolean;\n } = {},\n) {\n let query = `SELECT ${allColumns.map((d) => `${quoteIdentifier(d)}`).join(\", \")} FROM ${input}\n WHERE`;\n\n if (options.invert) {\n for (let i = 0; i < columns.length; i++) {\n query += `\\n${quoteIdentifier(columns[i])} IS NULL OR`;\n if (options.missingValues) {\n for (const otherMissingValue of options.missingValues) {\n if (typeof otherMissingValue === \"string\" && types[columns[i]] === \"VARCHAR\") {\n query += `\\n${quoteIdentifier(columns[i])} = ? OR`;\n } else if (\n typeof otherMissingValue === \"number\" &&\n [\"BIGINT\", \"DOUBLE\"].includes(types[columns[i]])\n ) {\n query += `\\n${quoteIdentifier(columns[i])} = ? OR`;\n }\n }\n }\n }\n } else {\n for (let i = 0; i < columns.length; i++) {\n query += `\\n${quoteIdentifier(columns[i])} IS NOT NULL AND`;\n if (options.missingValues) {\n for (const otherMissingValue of options.missingValues) {\n if (typeof otherMissingValue === \"string\" && types[columns[i]] === \"VARCHAR\") {\n query += `\\n${quoteIdentifier(columns[i])} != ? AND`;\n } else if (\n typeof otherMissingValue === \"number\" &&\n [\"BIGINT\", \"DOUBLE\"].includes(types[columns[i]])\n ) {\n query += `\\n${quoteIdentifier(columns[i])} != ? AND`;\n }\n }\n }\n }\n }\n\n return options.invert ? query.slice(0, query.length - 3) : query.slice(0, query.length - 4);\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default async function getColumns(simpleTable: SimpleTable) {\n const queryResult = await queryDB(\n simpleTable,\n `DESCRIBE ${quoteIdentifier(simpleTable.name)}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getColumns()\",\n parameters: {},\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const columns = queryResult.map((d) => d.column_name) as string[];\n\n return columns;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getRow(\n simpleTable: SimpleTable,\n conditions: string,\n options: { strict?: boolean } = {},\n): Promise<{ [key: string]: unknown }> {\n const data = await simpleTable.getData({ conditions, limit: 2 });\n if (data.length === 0) {\n throw new Error(`No row found with condition \\`${conditions}\\`.`);\n }\n if (options.strict !== false && data.length > 1) {\n throw new Error(`More than one row found with condition \\`${conditions}\\`.`);\n }\n return data[0];\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getRowCount(\n SimpleTable: SimpleTable,\n options: { conditions?: string } = {},\n) {\n const queryResult = await queryDB(\n SimpleTable,\n `SELECT CAST(COUNT(*) AS INTEGER) AS count FROM ${quoteIdentifier(\n SimpleTable.name,\n )}${options.conditions ? ` WHERE ${options.conditions}` : \"\"}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getRowCount()\",\n parameters: { options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n const length = queryResult[0].count as number;\n\n return length;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getCharacterCount(SimpleTable: SimpleTable, column: string) {\n const queryResult = await queryDB(\n SimpleTable,\n `SELECT CAST(SUM(LENGTH(${quoteQualifiedIdentifier(\n SimpleTable.name,\n column,\n )})) AS BIGINT) AS total_chars FROM ${quoteIdentifier(SimpleTable.name)}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getCharacterCount()\",\n parameters: { column },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = Number(queryResult[0].total_chars);\n\n return result;\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\n\n/**\n * Throws if any of the target columns already exists in the schema, matching\n * the behavior of the v1 methods that added columns with `ALTER TABLE ADD`\n * (which errored on a duplicate). Without this guard, a `SELECT *, expr AS\n * col` that collides with an existing column is silently renamed to `col_1`\n * by DuckDB, so the operation would appear to succeed while leaving the\n * original column untouched.\n *\n * @param schema - The schema of the operation's input.\n * @param newColumns - The names of the columns the operation adds.\n * @param method - The method name, for the error message (e.g. \"cloneColumn()\").\n * @param allowInPlace - Columns whose name may already exist because the\n * operation overwrites them in place rather than adding a new column.\n */\nexport default function assertNewColumns(\n schema: TableSchema,\n newColumns: string[],\n method: string,\n allowInPlace: string[] = [],\n): void {\n for (const column of newColumns) {\n if (schema[column] !== undefined && !allowInPlace.includes(column)) {\n throw new Error(\n `${method} the column ${quoteIdentifier(\n column,\n )} already exists. Remove it first or choose a different name for the new column.`,\n );\n }\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default function addCharacterCount(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addCharacterCount()\",\n parameters: { column, newColumn },\n needsSchema: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addCharacterCount()\");\n return `SELECT *, LENGTH(${quoteIdentifier(column)}) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default function addWordCount(simpleTable: SimpleTable, column: string, newColumn: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addWordCount()\",\n parameters: { column, newColumn },\n needsSchema: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addWordCount()\");\n return `SELECT *, ARRAY_LENGTH(REGEXP_EXTRACT_ALL(${quoteIdentifier(\n column,\n )}, '[^[:space:]]+')) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport extractTypes from \"../helpers/extractTypes.ts\";\n\nexport default async function getTypes(simpleTable: SimpleTable) {\n const types = await queryDB(\n simpleTable,\n `DESCRIBE ${quoteIdentifier(simpleTable.name)}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getTypes()\",\n parameters: {},\n }),\n );\n\n const typesObj = extractTypes(types);\n\n return typesObj;\n}\n","import crypto from \"node:crypto\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getTypes from \"./getTypes.ts\";\n\nexport default async function getHash(simpleTable: SimpleTable) {\n const types = await getTypes(simpleTable);\n const result = await queryDB(\n simpleTable,\n `WITH numbered AS (\n SELECT\n ROW_NUMBER() OVER () AS __sda_position,\n source AS __sda_row\n FROM ${quoteIdentifier(simpleTable.name)} AS source\n )\n SELECT\n CAST(COUNT(*) AS VARCHAR) AS row_count,\n CAST(\n COALESCE(BIT_XOR(MD5_NUMBER(numbered::VARCHAR)), 0)\n AS VARCHAR\n ) AS checksum\n FROM numbered`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getHash()\",\n parameters: {},\n }),\n );\n\n if (result === null || result.length !== 1) {\n throw new Error(\"getHash() could not compute the table hash.\");\n }\n const { row_count, checksum } = result[0];\n if (typeof row_count !== \"string\" || typeof checksum !== \"string\") {\n throw new Error(\"getHash() received an unexpected result from DuckDB.\");\n }\n\n return crypto\n .createHash(\"sha256\")\n .update(JSON.stringify([\"sda-table-hash-v1\", Object.entries(types), row_count, checksum]))\n .digest(\"hex\");\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getValues(simpleTable: SimpleTable, column: string) {\n const queryResult = await queryDB(\n simpleTable,\n `SELECT ${quoteQualifiedIdentifier(simpleTable.name, column)} FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getValues()\",\n parameters: { column },\n }),\n );\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const values = queryResult.map((d) => d[column]);\n\n return values;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getUniques(simpleTable: SimpleTable, column: string) {\n const qualifiedColumn = quoteQualifiedIdentifier(simpleTable.name, column);\n const queryResult = await queryDB(\n simpleTable,\n `SELECT DISTINCT ${qualifiedColumn} FROM ${quoteIdentifier(\n simpleTable.name,\n )} ORDER BY ${qualifiedColumn} ASC`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getUniques()\",\n parameters: { column },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const uniques = queryResult.map((d) => d[column]);\n\n return uniques;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getFirstRow(\n simpleTable: SimpleTable,\n options: {\n conditions?: string;\n } = {},\n) {\n const queryResult = await queryDB(\n simpleTable,\n `SELECT * FROM ${quoteIdentifier(simpleTable.name)}${\n options.conditions ? ` WHERE ${options.conditions}` : \"\"\n } LIMIT 1`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getFirstRow()\",\n parameters: { options },\n }),\n );\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0];\n\n return result ?? null;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getLastRow(\n simpleTable: SimpleTable,\n options: {\n conditions?: string;\n } = {},\n) {\n const queryResult = await queryDB(\n simpleTable,\n `WITH \"numberedRowsForGetLastRow\" AS (\n SELECT *, row_number() OVER () as \"rowNumberForGetLastRow\" FROM ${quoteIdentifier(\n simpleTable.name,\n )}${options.conditions ? ` WHERE ${options.conditions}` : \"\"}\n )\n SELECT * FROM \"numberedRowsForGetLastRow\" ORDER BY \"rowNumberForGetLastRow\" DESC LIMIT 1;`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getLastRow()\",\n parameters: { options },\n }),\n );\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n const result = queryResult[0];\n if (result === undefined) {\n return null;\n }\n delete result.rowNumberForGetLastRow;\n\n return result;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getTop(\n simpleTable: SimpleTable,\n count: number,\n options: {\n conditions?: string;\n } = {},\n) {\n const rows = await queryDB(\n simpleTable,\n `SELECT * FROM ${quoteIdentifier(simpleTable.name)}${\n options.conditions ? ` WHERE ${options.conditions}` : \"\"\n } LIMIT ${count}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getTop()\",\n parameters: { count, options },\n }),\n );\n\n if (!rows) {\n throw new Error(\"no rows\");\n }\n\n return rows;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getMin(simpleTable: SimpleTable, column: string) {\n const qualifiedColumn = quoteQualifiedIdentifier(simpleTable.name, column);\n const queryResult = await queryDB(\n simpleTable,\n `SELECT MIN(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getMin()\",\n parameters: { column },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n const result = queryResult[0][column];\n\n return result;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getMax(simpleTable: SimpleTable, column: string) {\n const qualifiedColumn = quoteQualifiedIdentifier(simpleTable.name, column);\n const queryResult = await queryDB(\n simpleTable,\n `SELECT MAX(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getMax()\",\n parameters: { column },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n\n return result;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getMean(\n simpleTable: SimpleTable,\n column: string,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(simpleTable.name, column);\n const queryResult = await queryDB(\n simpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(AVG(${qualifiedColumn}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(simpleTable.name)}`\n : `SELECT AVG(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n returnData: true,\n method: \"getMean()\",\n parameters: { column, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getMedian(\n SimpleTable: SimpleTable,\n column: string,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(MEDIAN(${qualifiedColumn}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`\n : `SELECT MEDIAN(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n SimpleTable.name,\n )}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getMedian()\",\n parameters: { column, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n const result = queryResult[0][column];\n\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getSum(SimpleTable: SimpleTable, column: string) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n `SELECT SUM(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n SimpleTable.name,\n )}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getSum()\",\n parameters: { column },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getSkew(\n SimpleTable: SimpleTable,\n column: string,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(SKEWNESS(${qualifiedColumn}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`\n : `SELECT SKEWNESS(${qualifiedColumn}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getSkew()\",\n parameters: { column, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getStdDev(\n SimpleTable: SimpleTable,\n column: string,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(STDDEV(${qualifiedColumn}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`\n : `SELECT STDDEV(${qualifiedColumn}) AS ${quoteIdentifier(column)} FROM ${quoteIdentifier(\n SimpleTable.name,\n )}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getStdDev()\",\n parameters: { column, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getVariance(\n SimpleTable: SimpleTable,\n column: string,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(VARIANCE(${qualifiedColumn}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`\n : `SELECT VARIANCE(${qualifiedColumn}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getVariance()\",\n parameters: { column, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteQualifiedIdentifier from \"../helpers/quoteQualifiedIdentifier.ts\";\n\nexport default async function getQuantile(\n SimpleTable: SimpleTable,\n column: string,\n quantile: number,\n options: {\n decimals?: number;\n } = {},\n) {\n const qualifiedColumn = quoteQualifiedIdentifier(SimpleTable.name, column);\n const queryResult = await queryDB(\n SimpleTable,\n typeof options.decimals === \"number\"\n ? `SELECT ROUND(QUANTILE_CONT(${qualifiedColumn}, ${quantile}), ${options.decimals}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`\n : `SELECT QUANTILE_CONT(${qualifiedColumn}, ${quantile}) AS ${quoteIdentifier(\n column,\n )} FROM ${quoteIdentifier(SimpleTable.name)}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n returnData: true,\n method: \"getQuantile()\",\n parameters: { column, quantile, options },\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const result = queryResult[0][column];\n return result as number;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function cloneColumn(simpleTable: SimpleTable, column: string, newColumn: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"cloneColumn()\",\n parameters: { column, newColumn },\n needsSchema: true,\n buildSelect: (input, types) => {\n if (!types[column]) {\n throw new Error(`Can't find type of ${column}`);\n }\n assertNewColumns(types, [newColumn], \"cloneColumn()\");\n return `SELECT *, ${quoteIdentifier(column)} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","/*\n * Spherical area and containment subset of d3-geo 3.1.1, with the\n * compensated Adder from d3-array 3.2.4 (Copyright 2010-2023 Mike Bostock).\n * https://github.com/d3/d3-geo and https://github.com/d3/d3-array\n * Rewinding adapted from @nshiab/journalism-dataviz 1.0.10 (MIT).\n *\n * Copyright 2010-2024 Mike Bostock\n *\n * Permission to use, copy, modify, and/or distribute this software for any purpose\n * with or without fee is hereby granted, provided that the above copyright notice\n * and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\n * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n * THIS SOFTWARE.\n *\n * This license applies to GeographicLib, versions 1.12 and later.\n *\n * Copyright 2008-2012 Charles Karney\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this software and associated documentation files (the \"Software\"), to deal in\n * the Software without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n * the Software, and to permit persons to whom the Software is furnished to do so,\n * subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\ntype Position = number[];\ntype Vector = [number, number, number];\nexport type GeoGeometry =\n | { type: \"Point\"; coordinates: Position }\n | { type: \"MultiPoint\" | \"LineString\"; coordinates: Position[] }\n | { type: \"MultiLineString\" | \"Polygon\"; coordinates: Position[][] }\n | { type: \"MultiPolygon\"; coordinates: Position[][][] }\n | { type: \"GeometryCollection\"; geometries: GeoGeometry[] };\ntype Feature = { type: \"Feature\"; geometry: GeoGeometry | null; properties?: unknown };\nexport type GeoObject = GeoGeometry | Feature | { type: \"FeatureCollection\"; features: Feature[] };\n\nconst pi = Math.PI;\nconst tau = 2 * pi;\nconst halfPi = pi / 2;\nconst quarterPi = pi / 4;\nconst radians = pi / 180;\nconst epsilon = 1e-6;\nconst epsilon2 = 1e-12;\n\n// Preserve D3's compensated summation: rounding at the hemisphere boundary\n// determines whether a polygon must be reversed.\nclass Adder {\n private readonly partials = new Float64Array(32);\n private count = 0;\n\n add(x: number): void {\n const p = this.partials;\n let i = 0;\n for (let j = 0; j < this.count && j < 32; j++) {\n const y = p[j];\n const hi = x + y;\n const lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);\n if (lo) p[i++] = lo;\n x = hi;\n }\n p[i] = x;\n this.count = i + 1;\n }\n\n valueOf(): number {\n const p = this.partials;\n let n = this.count;\n let hi = 0;\n let lo = 0;\n if (n > 0) {\n hi = p[--n];\n while (n > 0) {\n const x = hi;\n const y = p[--n];\n hi = x + y;\n lo = y - (hi - x);\n if (lo) break;\n }\n if (n > 0 && ((lo < 0 && p[n - 1] < 0) || (lo > 0 && p[n - 1] > 0))) {\n const y = lo * 2;\n const x = hi + y;\n if (y === x - hi) hi = x;\n }\n }\n return hi;\n }\n}\n\nfunction ringArea(ring: Position[]): number {\n const sum = new Adder();\n let lambda0 = ring[0][0] * radians;\n const phi0 = (ring[0][1] * radians) / 2 + quarterPi;\n let cosPhi0 = Math.cos(phi0);\n let sinPhi0 = Math.sin(phi0);\n // A closed ring is streamed without its last point, then closed explicitly.\n for (let i = 1; i < ring.length; i++) {\n const point = i === ring.length - 1 ? ring[0] : ring[i];\n const lambda = point[0] * radians;\n const phi = (point[1] * radians) / 2 + quarterPi;\n const delta = lambda - lambda0;\n const sign = delta >= 0 ? 1 : -1;\n const absDelta = sign * delta;\n const cosPhi = Math.cos(phi);\n const sinPhi = Math.sin(phi);\n const k = sinPhi0 * sinPhi;\n sum.add(Math.atan2(k * sign * Math.sin(absDelta), cosPhi0 * cosPhi + k * Math.cos(absDelta)));\n lambda0 = lambda;\n cosPhi0 = cosPhi;\n sinPhi0 = sinPhi;\n }\n const area = sum.valueOf();\n return (area < 0 ? tau + area : area) * 2;\n}\n\nfunction longitude(point: Position): number {\n return Math.abs(point[0]) <= pi\n ? point[0]\n : Math.sign(point[0]) * (((Math.abs(point[0]) + pi) % tau) - pi);\n}\n\nfunction cartesian(point: Position): Vector {\n const cosPhi = Math.cos(point[1]);\n return [cosPhi * Math.cos(point[0]), cosPhi * Math.sin(point[0]), Math.sin(point[1])];\n}\n\nfunction cross(a: Vector, b: Vector): Vector {\n return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];\n}\n\nfunction normalize(vector: Vector): void {\n const length = Math.sqrt(vector[0] ** 2 + vector[1] ** 2 + vector[2] ** 2);\n vector[0] /= length;\n vector[1] /= length;\n vector[2] /= length;\n}\n\nfunction ringContains(closedRing: Position[], point: Position): boolean {\n const ring = closedRing.slice(0, -1).map(([x, y]) => [x * radians, y * radians]);\n const lambda = longitude([point[0] * radians, point[1] * radians]);\n let phi = point[1] * radians;\n const sinPhi = Math.sin(phi);\n const normal: Vector = [Math.sin(lambda), -Math.cos(lambda), 0];\n let angle = 0;\n let winding = 0;\n const sum = new Adder();\n if (sinPhi === 1) phi = halfPi + epsilon;\n else if (sinPhi === -1) phi = -halfPi - epsilon;\n if (ring.length > 0) {\n let point0 = ring[ring.length - 1];\n let lambda0 = longitude(point0);\n const phi0 = point0[1] / 2 + quarterPi;\n let sinPhi0 = Math.sin(phi0);\n let cosPhi0 = Math.cos(phi0);\n for (const point1 of ring) {\n const lambda1 = longitude(point1);\n const phi1 = point1[1] / 2 + quarterPi;\n const sinPhi1 = Math.sin(phi1);\n const cosPhi1 = Math.cos(phi1);\n const delta = lambda1 - lambda0;\n const sign = delta >= 0 ? 1 : -1;\n const absDelta = sign * delta;\n const antimeridian = absDelta > pi;\n const k = sinPhi0 * sinPhi1;\n sum.add(\n Math.atan2(k * sign * Math.sin(absDelta), cosPhi0 * cosPhi1 + k * Math.cos(absDelta)),\n );\n angle += antimeridian ? delta + sign * tau : delta;\n if (Number(antimeridian) ^ Number(lambda0 >= lambda) ^ Number(lambda1 >= lambda)) {\n const arc = cross(cartesian(point0), cartesian(point1));\n normalize(arc);\n const intersection = cross(normal, arc);\n normalize(intersection);\n const z = intersection[2];\n const asin = z > 1 ? halfPi : z < -1 ? -halfPi : Math.asin(z);\n const direction = antimeridian !== delta >= 0;\n const phiArc = (direction ? -1 : 1) * asin;\n if (phi > phiArc || (phi === phiArc && (arc[0] || arc[1]))) {\n winding += direction ? 1 : -1;\n }\n }\n point0 = point1;\n lambda0 = lambda1;\n sinPhi0 = sinPhi1;\n cosPhi0 = cosPhi1;\n }\n }\n return Boolean(\n Number(angle < -epsilon || (angle < epsilon && sum.valueOf() < -epsilon2)) ^ (winding & 1),\n );\n}\n\nfunction rewindPolygon(coordinates: Position[][]): Position[][] {\n const polygon = coordinates.map((ring) => ring.slice(0, -1).map(([x, y]) => [x, y]));\n for (const [index, ring] of polygon.entries()) {\n ring.push([...ring[0]]);\n const reverse = index\n ? !ringContains(ring, polygon[0][0])\n : polygon[1]\n ? !ringContains(ring, polygon[1][0])\n : ringArea(ring) > 2 * pi;\n if (reverse) ring.reverse();\n ring.pop();\n }\n return polygon.map((ring) => [...ring, [...ring[0]]]);\n}\n\nfunction rewindGeometry(geometry: GeoGeometry): GeoGeometry {\n switch (geometry.type) {\n case \"GeometryCollection\":\n return { ...geometry, geometries: geometry.geometries.map(rewindGeometry) };\n case \"Polygon\":\n return { ...geometry, coordinates: rewindPolygon(geometry.coordinates) };\n case \"MultiPolygon\":\n return { ...geometry, coordinates: geometry.coordinates.map(rewindPolygon) };\n default:\n return geometry;\n }\n}\n\nexport default function rewind<T extends GeoObject>(geojson: T): T;\nexport default function rewind(geojson: unknown): GeoObject | null;\nexport default function rewind(geojson: unknown): GeoObject | null {\n if (geojson == null) return null;\n if (!isGeoObject(geojson)) throw new Error(\"Invalid GeoJSON object.\");\n if (geojson.type === \"FeatureCollection\") {\n return {\n ...geojson,\n features: geojson.features.map((feature) => ({\n ...feature,\n geometry: feature.geometry ? rewindGeometry(feature.geometry) : null,\n })),\n };\n }\n if (geojson.type === \"Feature\") {\n return { ...geojson, geometry: geojson.geometry ? rewindGeometry(geojson.geometry) : null };\n }\n return rewindGeometry(geojson);\n}\n\nfunction isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nfunction isPosition(value: unknown): value is number[] {\n return isArray(value) && value.every((coordinate) => typeof coordinate === \"number\");\n}\n\nfunction isLine(value: unknown): value is number[][] {\n return isArray(value) && value.every(isPosition);\n}\n\nfunction isPolygon(value: unknown): value is number[][][] {\n return isArray(value) && value.every(isLine);\n}\n\nexport function isGeometry(value: unknown): value is GeoGeometry {\n if (value === null || typeof value !== \"object\" || !(\"type\" in value)) return false;\n if (value.type === \"GeometryCollection\") {\n return \"geometries\" in value && isArray(value.geometries) && value.geometries.every(isGeometry);\n }\n if (!(\"coordinates\" in value)) return false;\n switch (value.type) {\n case \"Point\":\n return isPosition(value.coordinates);\n case \"MultiPoint\":\n case \"LineString\":\n return isLine(value.coordinates);\n case \"MultiLineString\":\n case \"Polygon\":\n return isPolygon(value.coordinates);\n case \"MultiPolygon\":\n return isArray(value.coordinates) && value.coordinates.every(isPolygon);\n default:\n return false;\n }\n}\n\nexport function isGeoObject(value: unknown): value is GeoObject {\n if (value === null || typeof value !== \"object\" || !(\"type\" in value)) return false;\n if (value.type === \"Feature\") {\n return \"geometry\" in value && (value.geometry === null || isGeometry(value.geometry));\n }\n if (value.type === \"FeatureCollection\") {\n return (\n \"features\" in value &&\n isArray(value.features) &&\n value.features.every(\n (feature) =>\n feature !== null &&\n typeof feature === \"object\" &&\n \"type\" in feature &&\n feature.type === \"Feature\" &&\n \"geometry\" in feature &&\n (feature.geometry === null || isGeometry(feature.geometry)),\n )\n );\n }\n return isGeometry(value);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport rewind, { isGeometry, type GeoGeometry } from \"../helpers/rewind.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nexport default async function getGeoData(\n SimpleTable: SimpleTable,\n column: string,\n options: { rewind?: boolean } = {},\n) {\n const quotedColumn = quoteIdentifier(column);\n const query = `SELECT * EXCLUDE ${quotedColumn}, ST_AsGeoJSON(${quotedColumn}) AS ${quoteIdentifier(\n \"geoJsonFragment\",\n )} FROM ${quoteIdentifier(SimpleTable.name)};`;\n\n const queryResult = await queryDB(\n SimpleTable,\n query,\n mergeOptions(SimpleTable, {\n table: null,\n method: \"getGeoData()\",\n parameters: { column },\n returnData: true,\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const features = queryResult.map((d) => {\n const { geoJsonFragment, ...properties } = d;\n if (typeof geoJsonFragment !== \"string\" && geoJsonFragment !== null) {\n throw new Error(\"Expected a GeoJSON geometry string from DuckDB.\");\n }\n const geometry: unknown = geoJsonFragment === null ? null : JSON.parse(geoJsonFragment);\n if (geometry !== null && !isGeometry(geometry)) {\n throw new Error(\"DuckDB returned an invalid GeoJSON geometry.\");\n }\n\n const feature: {\n type: \"Feature\";\n geometry: GeoGeometry | null;\n properties: Record<string, unknown>;\n } = {\n type: \"Feature\",\n geometry,\n properties,\n };\n\n return feature;\n });\n\n const geoJSON: { type: \"FeatureCollection\"; features: typeof features } = {\n type: \"FeatureCollection\",\n features,\n };\n\n return options.rewind ? rewind(geoJSON) : geoJSON;\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\n\n/**\n * Creates missing directories in an output path, including parent directories.\n * Non-hidden path segments containing a dot are treated as filenames and omitted.\n *\n * @example\n * ```ts\n * import { createDirectory } from \"@nshiab/simple-data-analysis-core/helpers\";\n * createDirectory(\"output/tables/results.csv\"); // Creates output/tables.\n * ```\n *\n * @param path - An output file path or a directory path without dotted segments.\n *\n * @returns Nothing. Existing directories are left unchanged.\n */\nexport default function createDirectory(path: string): void {\n path = path\n .split(\"/\")\n .filter((d) => (d.startsWith(\".\") ? true : !d.includes(\".\")))\n .join(\"/\");\n\n if (path !== \"\" && !existsSync(path)) {\n mkdirSync(path, { recursive: true });\n }\n}\n","export default function getExtension(path: string) {\n const extensionSplit = path.replace(\".gz\", \"\").replace(\".zstd\", \"\").split(\".\");\n const extension = extensionSplit[extensionSplit.length - 1].toLocaleLowerCase();\n\n return extension;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Returns `true` if the table has one or more columns of type geometry.\n *\n * Uses `getTypes()` to inspect column types and checks for any column\n * whose type normalizes to `\"geometry\"`.\n *\n * @example\n * ```ts\n * const hasGeo = await hasGeometryColumn(table);\n * if (hasGeo) {\n * console.log(\"This table contains geometry columns\");\n * }\n * ```\n *\n * @param table - The SimpleTable instance to inspect.\n *\n * @returns `true` if at least one geometry column exists, `false` otherwise.\n */\nexport default async function hasGeometryColumn(table: SimpleTable): Promise<boolean> {\n const types = await table.getTypes();\n return Object.values(types).some((t) => t.toLowerCase().includes(\"geometry\"));\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function stringifyDates(\n simpleTable: SimpleTable,\n types: { [key: string]: string },\n) {\n const typesKeys = Object.keys(types);\n const typesValues = Object.values(types);\n const toConvert: { [key: string]: \"string\" } = {};\n for (let i = 0; i < typesKeys.length; i++) {\n if (typesValues[i] === \"TIMESTAMP\" || typesValues[i] === \"DATE\") {\n toConvert[typesKeys[i]] = \"string\";\n }\n }\n if (Object.keys(toConvert).length > 0) {\n simpleTable.convert(toConvert, { datetimeFormat: \"%xT%T.%g%z\" });\n simpleTable.replace(Object.keys(toConvert), { \"+00\": \"Z\" });\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function stringifyDatesInvert(\n simpleTable: SimpleTable,\n types: { [key: string]: string },\n) {\n const typesKeys = Object.keys(types);\n const typesValues = Object.values(types);\n const toConvertBack: { [key: string]: \"timestamp\" | \"date\" } = {};\n for (let i = 0; i < typesKeys.length; i++) {\n if (typesValues[i] === \"TIMESTAMP\" || typesValues[i] === \"DATE\") {\n toConvertBack[typesKeys[i]] = typesValues[i].toLowerCase() as \"timestamp\" | \"date\";\n }\n }\n if (Object.keys(toConvertBack).length > 0) {\n simpleTable.replace(Object.keys(toConvertBack), { Z: \"+00\" });\n simpleTable.convert(toConvertBack);\n }\n}\n","export default function cleanPath(file: string) {\n return file.replaceAll(\"'\", \"''\");\n}\n","import { createReadStream } from \"node:fs\";\nimport { type FileHandle, open, rm, stat } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { Transform, type TransformCallback, Writable, type WritableOptions } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport * as zlib from \"node:zlib\";\nimport { constants, createDeflateRaw } from \"node:zlib\";\n\nconst maximumZip32Value = 0xffff_fffe;\nconst maximumZip32Entries = 0xfffe;\nconst utf8WithDataDescriptor = 0x0808;\nconst crc32Table = createCrc32Table();\n\ntype ZipInput = {\n file: string;\n name?: string;\n};\n\ntype ZipEntry = {\n name: Uint8Array;\n crc32: number;\n compressedSize: number;\n uncompressedSize: number;\n localHeaderOffset: number;\n modificationTime: number;\n modificationDate: number;\n};\n\nclass ChecksumTransform extends Transform {\n #crc32 = 0;\n size = 0;\n\n get crc32(): number {\n return this.#crc32;\n }\n\n override _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: TransformCallback,\n ): void {\n this.#crc32 = updateCrc32(chunk, this.#crc32);\n this.size += chunk.byteLength;\n callback(null, chunk);\n }\n}\n\nclass FileHandleWritable extends Writable {\n bytesWritten = 0;\n readonly #fileHandle: FileHandle;\n\n constructor(fileHandle: FileHandle, options?: WritableOptions) {\n super(options);\n this.#fileHandle = fileHandle;\n }\n\n override _write(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: (error?: Error | null) => void,\n ): void {\n writeAll(this.#fileHandle, chunk)\n .then(() => {\n this.bytesWritten += chunk.byteLength;\n callback();\n })\n .catch((error: unknown) => {\n callback(error instanceof Error ? error : new Error(String(error)));\n });\n }\n}\n\n/**\n * Writes files to a ZIP archive using streaming DEFLATE compression.\n *\n * The implementation intentionally supports ZIP32 archives only. Shapefile\n * components are conventionally limited to 2 GB, but the combined archive can\n * still exceed ZIP32 limits; those cases fail explicitly instead of producing\n * a corrupt archive.\n */\nexport default async function writeZip(archive: string, inputs: ZipInput[]): Promise<void> {\n if (inputs.length > maximumZip32Entries) {\n throw new Error(`ZIP archives support at most ${maximumZip32Entries} files.`);\n }\n\n const fileHandle = await open(archive, \"w\");\n const entries: ZipEntry[] = [];\n let offset = 0;\n let operationError: unknown;\n\n try {\n for (const input of inputs) {\n const fileStats = await stat(input.file);\n if (!fileStats.isFile()) {\n throw new Error(`ZIP input is not a file: ${JSON.stringify(input.file)}`);\n }\n assertZip32Value(fileStats.size, \"uncompressed file size\");\n\n const name = encodeZipName(input.name ?? basename(input.file));\n const { modificationTime, modificationDate } = encodeDosDateTime(fileStats.mtime);\n const localHeaderOffset = offset;\n const localHeader = createLocalHeader(name, modificationTime, modificationDate);\n await writeAll(fileHandle, localHeader);\n offset += localHeader.byteLength;\n\n const checksum = new ChecksumTransform();\n const output = new FileHandleWritable(fileHandle);\n await pipeline(\n createReadStream(input.file),\n checksum,\n createDeflateRaw({ level: constants.Z_BEST_SPEED }),\n output,\n );\n\n assertZip32Value(output.bytesWritten, \"compressed file size\");\n const descriptor = createDataDescriptor(checksum.crc32, output.bytesWritten, checksum.size);\n await writeAll(fileHandle, descriptor);\n offset += output.bytesWritten + descriptor.byteLength;\n\n entries.push({\n name,\n crc32: checksum.crc32,\n compressedSize: output.bytesWritten,\n uncompressedSize: checksum.size,\n localHeaderOffset,\n modificationTime,\n modificationDate,\n });\n }\n\n const centralDirectoryOffset = offset;\n for (const entry of entries) {\n assertZip32Value(entry.localHeaderOffset, \"local header offset\");\n const centralHeader = createCentralDirectoryHeader(entry);\n await writeAll(fileHandle, centralHeader);\n offset += centralHeader.byteLength;\n }\n\n const centralDirectorySize = offset - centralDirectoryOffset;\n assertZip32Value(centralDirectoryOffset, \"central directory offset\");\n assertZip32Value(centralDirectorySize, \"central directory size\");\n await writeAll(\n fileHandle,\n createEndOfCentralDirectory(entries.length, centralDirectorySize, centralDirectoryOffset),\n );\n } catch (error) {\n operationError = error;\n }\n\n try {\n await fileHandle.close();\n } catch (closeError) {\n if (operationError !== undefined) {\n operationError = new AggregateError(\n [operationError, closeError],\n \"Writing and closing the ZIP archive both failed.\",\n { cause: operationError },\n );\n } else {\n operationError = closeError;\n }\n }\n\n if (operationError !== undefined) {\n try {\n await rm(archive, { force: true });\n } catch (cleanupError) {\n throw new AggregateError(\n [operationError, cleanupError],\n \"Writing and cleaning up the ZIP archive both failed.\",\n { cause: operationError },\n );\n }\n throw operationError;\n }\n}\n\nfunction createCrc32Table(): Uint32Array {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index++) {\n let value = index;\n for (let bit = 0; bit < 8; bit++) {\n value = (value & 1) === 1 ? 0xedb8_8320 ^ (value >>> 1) : value >>> 1;\n }\n table[index] = value >>> 0;\n }\n return table;\n}\n\nfunction updateCrc32(data: Uint8Array, previous: number): number {\n if (typeof zlib.crc32 === \"function\") {\n return zlib.crc32(data, previous);\n }\n\n let value = (previous ^ 0xffff_ffff) >>> 0;\n for (const byte of data) {\n value = crc32Table[(value ^ byte) & 0xff] ^ (value >>> 8);\n }\n return (value ^ 0xffff_ffff) >>> 0;\n}\n\nfunction encodeZipName(name: string): Uint8Array {\n const normalizedName = name.replaceAll(\"\\\\\", \"/\");\n if (\n normalizedName === \"\" ||\n normalizedName.startsWith(\"/\") ||\n normalizedName.split(\"/\").includes(\"..\")\n ) {\n throw new Error(`Invalid ZIP entry name: ${JSON.stringify(name)}`);\n }\n const encoded = new TextEncoder().encode(normalizedName);\n if (encoded.byteLength > 0xffff) {\n throw new Error(`ZIP entry name is too long: ${JSON.stringify(name)}`);\n }\n return encoded;\n}\n\nfunction encodeDosDateTime(date: Date): {\n modificationTime: number;\n modificationDate: number;\n} {\n const year = Math.min(2107, Math.max(1980, date.getFullYear()));\n return {\n modificationTime:\n (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2),\n modificationDate: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(),\n };\n}\n\nfunction createLocalHeader(\n name: Uint8Array,\n modificationTime: number,\n modificationDate: number,\n): Uint8Array {\n const header = new Uint8Array(30 + name.byteLength);\n const view = new DataView(header.buffer);\n view.setUint32(0, 0x0403_4b50, true);\n view.setUint16(4, 20, true);\n view.setUint16(6, utf8WithDataDescriptor, true);\n view.setUint16(8, 8, true);\n view.setUint16(10, modificationTime, true);\n view.setUint16(12, modificationDate, true);\n view.setUint16(26, name.byteLength, true);\n header.set(name, 30);\n return header;\n}\n\nfunction createDataDescriptor(\n crc32: number,\n compressedSize: number,\n uncompressedSize: number,\n): Uint8Array {\n const descriptor = new Uint8Array(16);\n const view = new DataView(descriptor.buffer);\n view.setUint32(0, 0x0807_4b50, true);\n view.setUint32(4, crc32, true);\n view.setUint32(8, compressedSize, true);\n view.setUint32(12, uncompressedSize, true);\n return descriptor;\n}\n\nfunction createCentralDirectoryHeader(entry: ZipEntry): Uint8Array {\n const header = new Uint8Array(46 + entry.name.byteLength);\n const view = new DataView(header.buffer);\n view.setUint32(0, 0x0201_4b50, true);\n view.setUint16(4, 20, true);\n view.setUint16(6, 20, true);\n view.setUint16(8, utf8WithDataDescriptor, true);\n view.setUint16(10, 8, true);\n view.setUint16(12, entry.modificationTime, true);\n view.setUint16(14, entry.modificationDate, true);\n view.setUint32(16, entry.crc32, true);\n view.setUint32(20, entry.compressedSize, true);\n view.setUint32(24, entry.uncompressedSize, true);\n view.setUint16(28, entry.name.byteLength, true);\n view.setUint32(42, entry.localHeaderOffset, true);\n header.set(entry.name, 46);\n return header;\n}\n\nfunction createEndOfCentralDirectory(\n entryCount: number,\n centralDirectorySize: number,\n centralDirectoryOffset: number,\n): Uint8Array {\n const end = new Uint8Array(22);\n const view = new DataView(end.buffer);\n view.setUint32(0, 0x0605_4b50, true);\n view.setUint16(8, entryCount, true);\n view.setUint16(10, entryCount, true);\n view.setUint32(12, centralDirectorySize, true);\n view.setUint32(16, centralDirectoryOffset, true);\n return end;\n}\n\nfunction assertZip32Value(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value < 0 || value > maximumZip32Value) {\n throw new Error(`Cannot create ZIP archive: ${label} exceeds the 4 GB ZIP32 limit.`);\n }\n}\n\nasync function writeAll(fileHandle: FileHandle, data: Uint8Array): Promise<void> {\n let offset = 0;\n while (offset < data.byteLength) {\n const { bytesWritten } = await fileHandle.write(data.subarray(offset));\n if (bytesWritten === 0) {\n throw new Error(\"Could not write to ZIP archive.\");\n }\n offset += bytesWritten;\n }\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport { mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport createDirectory from \"./createDirectory.ts\";\nimport getExtension from \"./getExtension.ts\";\nimport hasGeometryColumn from \"./hasGeometryColumn.ts\";\nimport queryDB from \"./queryDB.ts\";\n\nimport mergeOptions from \"./mergeOptions.ts\";\nimport rewind, { isGeoObject } from \"./rewind.ts\";\nimport flushAllTables from \"./flushAllTables.ts\";\nimport stringifyDates from \"./stringifyDates.ts\";\nimport stringifyDatesInvert from \"./stringifyDatesInvert.ts\";\nimport cleanPath from \"./cleanPath.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport writeZip from \"./writeZip.ts\";\n\nexport default async function writeGeoData(\n table: SimpleTable,\n file: string,\n options: {\n precision?: number;\n compression?: boolean;\n rewind?: boolean;\n metadata?: unknown;\n formatDates?: boolean;\n } = {},\n): Promise<void> {\n const compressedShapefileExtension = file.toLowerCase().endsWith(\".shp.zip\");\n const fileExtension = compressedShapefileExtension ? \"shp\" : getExtension(file);\n assertWriteGeoDataOptions(fileExtension, options);\n\n if (!(await hasGeometryColumn(table))) {\n throw new Error(\"Table contains no geometry columns. Use writeData() instead.\");\n }\n createDirectory(file);\n if (fileExtension === \"geojson\" || fileExtension === \"json\") {\n let types;\n let datesConverted = false;\n if (options.formatDates === true) {\n types = await table.getTypes();\n if (Object.values(types).includes(\"DATE\") || Object.values(types).includes(\"TIMESTAMP\")) {\n await stringifyDates(table, types);\n datesConverted = true;\n }\n }\n\n try {\n await queryDB(\n table,\n writeGeoDataQuery(table.name, file, fileExtension, options),\n mergeOptions(table, {\n table: table.name,\n method: \"writeGeoData()\",\n parameters: { file, options },\n }),\n );\n\n if (options.metadata) {\n const fileData: unknown = JSON.parse(readFileSync(file, \"utf-8\"));\n if (!isGeoObject(fileData)) throw new Error(\"Invalid GeoJSON output from DuckDB.\");\n writeFileSync(file, JSON.stringify({ ...fileData, metadata: options.metadata }));\n }\n if (options.rewind) {\n const fileData: unknown = JSON.parse(readFileSync(file, \"utf-8\"));\n if (!isGeoObject(fileData)) throw new Error(\"Invalid GeoJSON output from DuckDB.\");\n const fileRewinded = rewind(fileData);\n writeFileSync(file, JSON.stringify(fileRewinded));\n }\n } finally {\n if (datesConverted && types) {\n await stringifyDatesInvert(table, types);\n // stringifyDatesInvert queues sync builder operations restoring the\n // date columns. writeGeoData is an observer, so it must leave no\n // queued work behind.\n await flushAllTables(table.sdb);\n }\n }\n } else if (fileExtension === \"shp\") {\n if (compressedShapefileExtension) {\n const shapefile = file.slice(0, -\".zip\".length);\n await writeCompressedShapefile(table, shapefile, file, file, options);\n } else {\n await writeShapefile(table, file, file, options);\n }\n } else if (fileExtension === \"geoparquet\") {\n await queryDB(\n table,\n `COPY ${quoteIdentifier(table.name)} TO '${cleanPath(file)}' WITH (FORMAT PARQUET${\n options.compression === true ? \", COMPRESSION 'zstd'\" : \"\"\n });`,\n mergeOptions(table, {\n table: table.name,\n method: \"writeGeoData()\",\n parameters: { file, options },\n }),\n );\n }\n}\n\nfunction assertWriteGeoDataOptions(\n fileExtension: string,\n options: {\n precision?: number;\n compression?: boolean;\n rewind?: boolean;\n metadata?: unknown;\n formatDates?: boolean;\n },\n): void {\n if (![\"geojson\", \"json\", \"shp\", \"geoparquet\"].includes(fileExtension)) {\n throw new Error(\n `writeGeoData() does not support the extension ${JSON.stringify(\n fileExtension,\n )}. Use .geojson, .json, .shp, .shp.zip, or .geoparquet.`,\n );\n }\n if (\n (fileExtension === \"geojson\" || fileExtension === \"json\") &&\n typeof options.compression === \"boolean\"\n ) {\n throw new Error(\"writeGeoData() compression is not supported for GeoJSON files.\");\n }\n if (fileExtension === \"shp\" && typeof options.compression === \"boolean\") {\n throw new Error(\n \"writeGeoData() compression is not supported for Shapefiles. Use a .shp.zip file extension instead.\",\n );\n }\n if (\n fileExtension === \"shp\" &&\n (typeof options.precision === \"number\" ||\n typeof options.rewind === \"boolean\" ||\n options.metadata !== undefined ||\n options.formatDates === true)\n ) {\n throw new Error(\n \"writeGeoData() precision, rewind, metadata, and formatDates are not supported for Shapefiles.\",\n );\n }\n if (fileExtension === \"geoparquet\" && typeof options.precision === \"number\") {\n throw new Error(\n \"writeGeoData() precision is not supported for GeoParquet files. Use reducePrecision() first.\",\n );\n }\n if (fileExtension === \"geoparquet\" && typeof options.rewind === \"boolean\") {\n throw new Error(\"writeGeoData() rewind is not supported for GeoParquet files.\");\n }\n}\n\nasync function writeCompressedShapefile(\n table: SimpleTable,\n shapefile: string,\n archive: string,\n requestedFile: string,\n options: { compression?: boolean },\n): Promise<void> {\n const temporaryDirectory = mkdtempSync(join(dirname(archive), `.${basename(shapefile)}-`));\n const temporaryShapefile = join(temporaryDirectory, basename(shapefile));\n const temporaryArchive = `${temporaryShapefile}.zip`;\n let outcome: { success: true } | { success: false; error: unknown };\n\n try {\n await writeShapefile(table, temporaryShapefile, requestedFile, options);\n const inputs = readdirSync(temporaryDirectory, { withFileTypes: true })\n .filter((entry) => entry.isFile())\n .sort((first, second) => first.name.localeCompare(second.name))\n .map((entry) => ({\n file: join(temporaryDirectory, entry.name),\n name: entry.name,\n }));\n await writeZip(temporaryArchive, inputs);\n renameSync(temporaryArchive, archive);\n outcome = { success: true };\n } catch (error) {\n outcome = { success: false, error };\n }\n\n try {\n rmSync(temporaryDirectory, { recursive: true, force: true });\n } catch (cleanupError) {\n if (!outcome.success) {\n throw new AggregateError(\n [outcome.error, cleanupError],\n \"Writing and cleaning up the compressed Shapefile both failed.\",\n { cause: outcome.error },\n );\n }\n throw cleanupError;\n }\n\n if (!outcome.success) {\n throw outcome.error;\n }\n}\n\nasync function writeShapefile(\n table: SimpleTable,\n outputFile: string,\n requestedFile: string,\n options: { compression?: boolean },\n): Promise<void> {\n await queryDB(\n table,\n writeGeoDataQuery(table.name, outputFile, \"shp\"),\n mergeOptions(table, {\n table: table.name,\n method: \"writeGeoData()\",\n parameters: { file: requestedFile, options },\n }),\n );\n}\n\nfunction writeGeoDataQuery(\n table: string,\n file: string,\n fileExtension: string,\n options: { precision?: number } = {},\n) {\n if (fileExtension === \"geojson\" || fileExtension === \"json\") {\n const layerOptions = [];\n if (typeof options.precision === \"number\") {\n layerOptions.push(`COORDINATE_PRECISION=${options.precision}`);\n }\n layerOptions.push(`RFC7946=YES`);\n\n return `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; COPY ${quoteIdentifier(\n table,\n )} to '${cleanPath(file)}' WITH (FORMAT GDAL, DRIVER 'GeoJSON'${\n layerOptions.length > 0\n ? `, LAYER_CREATION_OPTIONS ('WRITE_NAME=NO', ${layerOptions\n .map((d) => `'${d}'`)\n .join(\", \")})`\n : \"\"\n })`;\n } else if (fileExtension === \"shp\") {\n // DuckDB only finalizes the main file when a GDAL driver creates a\n // multi-file dataset, leaving Shapefile sidecars under the tmp_ prefix.\n // Remove USE_TMP_FILE false once the upstream fix is released:\n // https://github.com/duckdb/duckdb-spatial/issues/859\n return `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; COPY ${quoteIdentifier(\n table,\n )} TO '${cleanPath(\n file,\n )}' WITH (FORMAT GDAL, DRIVER 'ESRI Shapefile', LAYER_CREATION_OPTIONS 'ENCODING=UTF-8', USE_TMP_FILE false)`;\n } else {\n throw new Error(`Unknown extension ${fileExtension}`);\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function splitSpread(\n simpleTable: SimpleTable,\n column: string,\n separator: string,\n newColumns: string[],\n options: {\n strict?: boolean;\n } = {},\n) {\n newColumns = [...newColumns];\n if (newColumns.length === 0) {\n throw new Error(\"splitSpread() newColumns must contain at least one column.\");\n }\n options = structuredClone(options);\n // The pre-validation queries the data, so splitSpread can't be expressed\n // as a single SELECT over its input: it executes as a barrier.\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"splitSpread()\",\n parameters: { column, separator, newColumns, options },\n execute: () => executeSplitSpread(simpleTable, column, separator, newColumns, options),\n });\n}\n\nasync function executeSplitSpread(\n simpleTable: SimpleTable,\n column: string,\n separator: string,\n newColumns: string[],\n options: {\n strict?: boolean;\n },\n): Promise<void> {\n const partCount = newColumns.length;\n const strict = options.strict !== false;\n\n // A SELECT *, expr AS col colliding with an existing column would be\n // silently renamed by DuckDB (col -> col_1) instead of erroring, unlike\n // the ALTER TABLE ADD this used to run.\n assertNewColumns(await simpleTable.getTypes(), newColumns, \"splitSpread()\");\n\n if (strict) {\n // Both bounds come from the same scan instead of one query each.\n const partsResult = await queryDB(\n simpleTable,\n `SELECT\n MAX(ARRAY_LENGTH(STRING_SPLIT(${quoteIdentifier(column)}, ?))) AS max_parts,\n MIN(ARRAY_LENGTH(STRING_SPLIT(${quoteIdentifier(column)}, ?))) AS min_parts\n FROM ${quoteIdentifier(simpleTable.name)}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"splitSpread()\",\n parameters: { column, separator, newColumns },\n returnData: true,\n values: [separator, separator],\n }),\n );\n\n if (partsResult && partsResult.length > 0) {\n const maxParts = partsResult[0].max_parts as number;\n const minParts = partsResult[0].min_parts as number;\n\n if (maxParts > partCount) {\n // Get the first 5 rows with more parts than expected\n const problematicRows = await queryDB(\n simpleTable,\n `SELECT ${quoteIdentifier(column)}\n FROM ${quoteIdentifier(simpleTable.name)}\n WHERE ARRAY_LENGTH(STRING_SPLIT(${quoteIdentifier(column)}, ?)) > ${partCount}\n LIMIT 5`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"splitSpread()\",\n parameters: { column, separator, newColumns },\n returnData: true,\n values: [separator],\n }),\n );\n\n const exampleRows = problematicRows\n ? problematicRows.map((row) => row[column]).join(\"\\n - \")\n : \"\";\n\n throw new Error(\n `Some rows contain more values after splitting (${maxParts}) than the number of new columns specified (${partCount}).\nWhen splitting by '${separator}', each row must produce at most ${partCount} value(s) to fit in the columns: ${newColumns.join(\n \", \",\n )}.\n\nFirst 5 rows with too many values:\\n - ${exampleRows}`,\n );\n }\n\n if (minParts < partCount) {\n console.warn(\n `splitSpread() warning: Some rows contain fewer values after splitting (${minParts}) than the number of new columns (${partCount}). Empty strings will be used for missing values.`,\n );\n }\n }\n }\n\n const split = splitSpreadQuery(simpleTable.name, column, separator, newColumns);\n await queryDB(\n simpleTable,\n split.query,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"splitSpread()\",\n parameters: { column, separator, newColumns },\n values: split.values,\n }),\n );\n}\n\nfunction splitSpreadQuery(\n table: string,\n column: string,\n separator: string,\n newColumns: string[],\n): { query: string; values: string[] } {\n // All columns are added in a single rewrite, so the table is scanned once\n // instead of once per ALTER + once per UPDATE.\n const splitColumns = newColumns\n .map(\n (col, i) => `SPLIT_PART(${quoteIdentifier(column)}, ?, ${i + 1}) AS ${quoteIdentifier(col)}`,\n )\n .join(\", \");\n\n const query = `CREATE OR REPLACE TABLE ${quoteIdentifier(\n table,\n )} AS SELECT *, ${splitColumns} FROM ${quoteIdentifier(table)}`;\n return { query, values: newColumns.map(() => separator) };\n}\n","export type Stat =\n | \"count\"\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\";\n\nexport const allStats: readonly Stat[] = [\n \"count\",\n \"countDistinct\",\n \"countNull\",\n \"min\",\n \"max\",\n \"mean\",\n \"median\",\n \"sum\",\n \"skew\",\n \"stdDev\",\n \"variance\",\n];\n\nconst aggregateFunctions: Partial<Record<Stat, string>> = {\n min: \"MIN\",\n max: \"MAX\",\n mean: \"AVG\",\n median: \"MEDIAN\",\n sum: \"SUM\",\n skew: \"SKEWNESS\",\n stdDev: \"STDDEV\",\n variance: \"VARIANCE\",\n};\n\nconst temporalStatTypes: readonly string[] = [\n \"DATE\",\n \"TIME\",\n \"TIMESTAMP\",\n \"TIMESTAMP_MS\",\n \"TIMESTAMP WITH TIME ZONE\",\n];\n\n/** Returns whether a DuckDB type is temporal for statistic compatibility. */\nexport function isTemporalStatType(type: string | undefined): boolean {\n return typeof type === \"string\" && temporalStatTypes.includes(type);\n}\n\n/**\n * Returns the aggregate expression for one statistic of one column, or `null`\n * when the statistic is not supported for the column type.\n */\nexport default function getStatExpression(\n stat: Stat,\n type: string | undefined,\n reference: string,\n decimals: number | undefined,\n): string | null {\n if (typeof type === \"string\" && type.toLowerCase().includes(\"geometry\")) {\n return null;\n }\n if (stat === \"count\") {\n return `CAST(COUNT(*) AS INTEGER)`;\n }\n if (stat === \"countDistinct\") {\n return `CAST(COUNT(DISTINCT ${reference}) AS INTEGER)`;\n }\n if (stat === \"countNull\") {\n return `CAST(COUNT(CASE WHEN ${reference} IS NULL THEN 1 END) AS INTEGER)`;\n }\n if (type === \"VARCHAR\") {\n return null;\n }\n if (isTemporalStatType(type) && [\"mean\", \"sum\", \"skew\", \"stdDev\", \"variance\"].includes(stat)) {\n return null;\n }\n const aggregateFunction = aggregateFunctions[stat];\n if (aggregateFunction === undefined) {\n return null;\n }\n const aggregate = `${aggregateFunction}(${reference})`;\n return typeof decimals === \"number\" &&\n typeof type === \"string\" &&\n ![\"VARCHAR\", \"DATE\", \"TIME\", \"TIMESTAMP\", \"TIMESTAMP WITH TIME ZONE\"].includes(type)\n ? `ROUND(${aggregate}, ${decimals})`\n : aggregate;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Resolves `outputTable: true` into an auto-generated table name\n * (\"table0\", \"table1\", ...), incrementing the database's shared counter so\n * concurrent auto-named tables never collide. A string, `false`, or\n * `undefined` value passes through unchanged.\n */\nexport default function resolveOutputTable(\n simpleTable: SimpleTable,\n outputTable: string | boolean | undefined,\n): string | boolean | undefined {\n if (outputTable === true) {\n const name = `table${simpleTable.sdb.tableIncrement}`;\n simpleTable.sdb.tableIncrement += 1;\n return name;\n }\n return outputTable;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getStatExpression, {\n allStats,\n isTemporalStatType,\n type Stat,\n} from \"../helpers/getStatExpression.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\n\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\n\ntype SummarizeOptions = {\n outputTable?: string | boolean;\n columns?: string | string[];\n by?: string | string[];\n stats?: Stat | Stat[] | { [key: string]: Stat };\n decimals?: number;\n datesToMs?: boolean;\n};\n\nexport default function summarize(\n simpleTable: SimpleTable,\n options: SummarizeOptions = {},\n): SimpleTable {\n options = structuredClone(options);\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n const columns = getSummarizeColumns(options);\n const boundColumns = columns.length > 1 ? columns : [];\n\n if (typeof options.outputTable === \"string\") {\n // The output table instance is created at call time so it can be\n // returned synchronously and chained on right away.\n const outputTable = simpleTable.sdb.newTable(options.outputTable);\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"summarize()\",\n parameters: { options },\n execute: async () => {\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable.name)} AS ${summarizeSelect(\n `${quoteIdentifier(simpleTable.name)}`,\n await simpleTable.getTypes(),\n options,\n )}`,\n mergeOptions(simpleTable, {\n table: outputTable.name,\n method: \"summarize()\",\n parameters: { options },\n values: boundColumns,\n }),\n );\n },\n });\n return outputTable;\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"summarize()\",\n parameters: { options },\n needsSchema: true,\n values: boundColumns,\n buildSelect: (input, types) => summarizeSelect(input, types, options),\n });\n return simpleTable;\n}\n\nfunction getSummarizeColumns(options: SummarizeOptions): string[] {\n const by = options.by ? stringToArray(options.by) : [];\n return [\n ...new Set(\n (options.columns ? stringToArray(options.columns) : []).filter(\n (column) => !by.includes(column),\n ),\n ),\n ];\n}\n\nfunction summarizeSelect(input: string, types: TableSchema, options: SummarizeOptions): string {\n const by = options.by ? stringToArray(options.by) : [];\n // Duplicated columns would duplicate rows now that the branches are combined\n // with UNION ALL instead of a deduplicating UNION.\n const columns = getSummarizeColumns(options);\n\n let stats: Stat[];\n let outputColumns: string[] | undefined;\n if (options.stats === undefined) {\n stats = columns.length === 0 ? [\"count\"] : [...allStats];\n } else if (typeof options.stats === \"string\") {\n stats = [options.stats];\n } else if (Array.isArray(options.stats)) {\n stats = options.stats.length === 0 ? [...allStats] : options.stats;\n } else {\n const entries = Object.entries(options.stats);\n outputColumns = entries.map((d) => d[0]);\n stats = entries.map((d) => d[1]);\n }\n\n // The `column` output column is a row key that distinguishes rows for\n // different input columns, so it appears only when there is more than one.\n const columnColumn = columns.length > 1;\n\n // With datesToMs, dates are converted to milliseconds inside the aggregate\n // expressions (same conversions as convert()), so the input table is left\n // untouched instead of being rewritten.\n const references: { [column: string]: string } = {};\n const effectiveTypes: TableSchema = {};\n for (const column of columns) {\n const type = types[column];\n if (\n options.datesToMs === true &&\n typeof type === \"string\" &&\n (type.includes(\"TIME\") || type.includes(\"DATE\"))\n ) {\n references[column] = type.includes(\"TIME\")\n ? `(date_part('epoch', ${quoteIdentifier(column)}) * 1000)`\n : `(epoch(${quoteIdentifier(column)}) * 1000)`;\n effectiveTypes[column] = \"BIGINT\";\n } else {\n references[column] = `${quoteIdentifier(column)}`;\n effectiveTypes[column] = type;\n }\n }\n\n const columnTypes = columns.map((d) => effectiveTypes[d]);\n const doubleAndDate = columnTypes.includes(\"DOUBLE\") && columnTypes.some(isTemporalStatType);\n if (doubleAndDate) {\n throw new Error(\n \"You are trying to summarize numbers and timestamps/dates/times. You can specify columns in the options (just numbers or just timestamps/dates/times) or convert your timestamps/dates/times to the number of ms since 1970-01-01 00:00:00 by passing the option { datesToMs: true }.\",\n );\n }\n\n const bySelect = by.map((d) => `${quoteIdentifier(d)}`).join(\", \");\n const groupBy = by.length > 0 ? `\\nGROUP BY ${bySelect}` : \"\";\n\n // With no columns, the only meaningful statistic is the row count, which\n // doesn't need an input-column label (or any temporary column) at all.\n if (columns.length === 0) {\n const statColumns = stats.map((stat, i) => {\n const name = outputColumns ? outputColumns[i] : stat;\n return stat === \"count\"\n ? `CAST(COUNT(*) AS INTEGER) AS ${quoteIdentifier(name)}`\n : `NULL AS ${quoteIdentifier(name)}`;\n });\n const orderBy =\n by.length > 0 ? `\\nORDER BY ${by.map((d) => `${quoteIdentifier(d)} ASC`).join(\", \")}` : \"\";\n return `SELECT ${[...by.map((d) => `${quoteIdentifier(d)}`), ...statColumns].join(\n \", \",\n )}\\nFROM ${input}${groupBy}${orderBy}`;\n }\n\n // One UNION ALL branch per input column. DuckDB runs the branches as\n // concurrent pipelines, which parallelizes the expensive aggregates\n // (medians, distinct counts) better than computing them all in one scan.\n const branches: string[] = [];\n for (const column of columns) {\n let hasAggregate = false;\n const projections = stats.map((stat, j) => {\n const name = outputColumns ? outputColumns[j] : stat;\n const expression = getStatExpression(\n stat,\n effectiveTypes[column],\n references[column],\n options.decimals,\n );\n if (expression === null) {\n return `NULL AS ${quoteIdentifier(name)}`;\n }\n hasAggregate = true;\n return `${expression} AS ${quoteIdentifier(name)}`;\n });\n const select = `SELECT ${\n columnColumn ? `? AS ${quoteIdentifier(\"column\")}, ` : \"\"\n }${bySelect === \"\" ? \"\" : `${bySelect}, `}${projections.join(\", \")}`;\n if (by.length === 0 && !hasAggregate) {\n // Every statistic is NULL and there is nothing to group by: the branch\n // is a single constant row, so the input is not even scanned.\n branches.push(select);\n } else {\n branches.push(`${select}\\nFROM ${input}${groupBy}`);\n }\n }\n\n const orderByColumns = columnColumn ? [\"column\", ...by] : by;\n const orderBy =\n orderByColumns.length > 0\n ? `\\nORDER BY ${orderByColumns.map((d) => `${quoteIdentifier(d)} ASC`).join(\", \")}`\n : \"\";\n\n return `${branches.join(\"\\nUNION ALL\\n\")}${orderBy}`;\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\n\n/**\n * Throws if any of the named columns is absent from the schema. The mirror of\n * `assertNewColumns`: where that guard rejects a column that unexpectedly\n * already exists, this one rejects a column that should exist but doesn't.\n *\n * It backs methods whose SQL silently tolerates a missing column instead of\n * erroring — notably `SELECT * RENAME (...)`, which drops a rename whose\n * source column is absent rather than failing, so a typo would pass unnoticed.\n *\n * @param schema - The schema of the operation's input.\n * @param columns - The names of the columns the operation reads.\n * @param method - The method name, for the error message (e.g. \"renameColumns()\").\n */\nexport default function assertColumnsExist(\n schema: TableSchema,\n columns: string[],\n method: string,\n): void {\n const missing = columns.filter((column) => schema[column] === undefined);\n if (missing.length > 0) {\n const plural = missing.length > 1;\n throw new Error(\n `${method} the column${plural ? \"s\" : \"\"} ${missing\n .map((column) => `${quoteIdentifier(column)}`)\n .join(\", \")} ${plural ? \"do\" : \"does\"} not exist. Check for typos, or load the data first.`,\n );\n }\n}\n","export default function keepNumericalColumns(types: { [key: string]: string }) {\n const columns: string[] = [];\n for (const col of Object.keys(types)) {\n const type = types[col];\n if (\n [\"FLOAT\", \"DOUBLE\", \"REAL\"].includes(type) ||\n type.startsWith(\"DECIMAL\") ||\n type.includes(\"INT\")\n ) {\n columns.push(col);\n }\n }\n return columns;\n}\n","import assertColumnsExist from \"../helpers/assertColumnsExist.ts\";\nimport getStatExpression, { allStats, type Stat } from \"../helpers/getStatExpression.ts\";\nimport keepNumericalColumns from \"../helpers/keepNumericalColumns.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\ntype StatRowOperation = Exclude<Stat, \"count\">;\ntype StatRow = StatRowOperation | { stat: StatRowOperation; label?: string };\ntype NormalizedStatRow = { stat: StatRowOperation; label: string };\ntype AddSummaryRowsOptions = {\n stats?: StatRow | StatRow[];\n position?: \"top\" | \"bottom\";\n};\n\nconst allStatRowOperations = allStats.filter((stat): stat is StatRowOperation => stat !== \"count\");\n\nexport default function addSummaryRows(\n simpleTable: SimpleTable,\n columns: string | string[],\n labelColumn: string,\n options: AddSummaryRowsOptions = {},\n) {\n options = structuredClone(options);\n if (\n options.position !== undefined &&\n options.position !== \"top\" &&\n options.position !== \"bottom\"\n ) {\n throw new Error(\n `addSummaryRows() options.position must be \"top\" or \"bottom\". Received ${JSON.stringify(\n options.position,\n )}.`,\n );\n }\n const selectedColumns = columns === \"all\" ? \"all\" : stringToArray(columns);\n if (selectedColumns !== \"all\" && selectedColumns.length === 0) {\n throw new Error('addSummaryRows() requires at least one column or \"all\".');\n }\n if (selectedColumns !== \"all\") {\n const duplicates = selectedColumns.filter(\n (column, index) => selectedColumns.indexOf(column) !== index,\n );\n if (duplicates.length > 0) {\n throw new Error(\n `addSummaryRows() received duplicate column${\n new Set(duplicates).size === 1 ? \"\" : \"s\"\n } ${[...new Set(duplicates)].map(quoteIdentifier).join(\", \")}.`,\n );\n }\n if (selectedColumns.includes(labelColumn)) {\n throw new Error(\n `addSummaryRows() label column ${quoteIdentifier(labelColumn)} cannot also be summarized.`,\n );\n }\n }\n\n const statRows = normalizeStatRows(options.stats);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addSummaryRows()\",\n parameters: { columns, labelColumn, options },\n needsSchema: true,\n values: statRows.map((row) => row.label),\n buildSelect: (input, schema) =>\n addSummaryRowsSelect(\n input,\n schema,\n selectedColumns,\n labelColumn,\n statRows,\n options.position ?? \"bottom\",\n ),\n });\n}\n\nfunction normalizeStatRows(stats?: StatRow | StatRow[]): NormalizedStatRow[] {\n const rows =\n stats === undefined ? [...allStatRowOperations] : Array.isArray(stats) ? stats : [stats];\n if (rows.length === 0) {\n throw new Error(\n \"addSummaryRows() stats cannot be an empty array. Omit stats to add every supported stat.\",\n );\n }\n\n return rows.map((row) => {\n if (typeof row === \"string\") {\n assertStat(row);\n return { stat: row, label: row };\n }\n if (row === null || typeof row !== \"object\") {\n throw new Error(\n \"addSummaryRows() stats must contain stat names or objects with a stat property.\",\n );\n }\n assertStat(row.stat);\n if (row.label !== undefined && typeof row.label !== \"string\") {\n throw new Error(\"addSummaryRows() stat labels must be strings.\");\n }\n return { stat: row.stat, label: row.label ?? row.stat };\n });\n}\n\nfunction assertStat(stat: string): asserts stat is StatRowOperation {\n if (!(allStatRowOperations as readonly string[]).includes(stat)) {\n throw new Error(\n `addSummaryRows() stat ${JSON.stringify(stat)} is not supported. Use ${allStatRowOperations\n .map((value) => JSON.stringify(value))\n .join(\", \")}.`,\n );\n }\n}\n\nfunction addSummaryRowsSelect(\n input: string,\n schema: TableSchema,\n columns: \"all\" | string[],\n labelColumn: string,\n statRows: NormalizedStatRow[],\n position: \"top\" | \"bottom\",\n): string {\n const method = \"addSummaryRows()\";\n const tableColumns = Object.keys(schema);\n assertColumnsExist(schema, [labelColumn], method);\n if (schema[labelColumn] !== \"VARCHAR\") {\n throw new Error(\n `${method} label column ${quoteIdentifier(\n labelColumn,\n )} must have type VARCHAR, but has type ${schema[labelColumn]}.`,\n );\n }\n\n const numericalColumns = keepNumericalColumns(schema);\n const selectedColumns = columns === \"all\" ? numericalColumns : columns;\n if (selectedColumns.length === 0) {\n throw new Error(\n `${method} could not find any numeric columns. Select numeric columns explicitly or convert columns to numeric types first.`,\n );\n }\n if (columns !== \"all\") {\n assertColumnsExist(schema, selectedColumns, method);\n const numericalColumnSet = new Set(numericalColumns);\n const nonNumericalColumns = selectedColumns.filter((column) => !numericalColumnSet.has(column));\n if (nonNumericalColumns.length > 0) {\n throw new Error(\n `${method} requires numeric columns, but ${nonNumericalColumns\n .map((column) => `${quoteIdentifier(column)} has type ${schema[column]}`)\n .join(\", \")}. Convert ${\n nonNumericalColumns.length === 1 ? \"it\" : \"them\"\n } to a numeric type first.`,\n );\n }\n }\n\n const selectedColumnSet = new Set(selectedColumns);\n const kindColumn = unusedColumn(schema, \"_sda_stat_kind\");\n const orderColumn = unusedColumn({ ...schema, [kindColumn]: \"INTEGER\" }, \"_sda_stat_order\");\n const projectedColumns = tableColumns.map(quoteIdentifier).join(\", \");\n const dataKind = position === \"top\" ? 1 : 0;\n const statKind = position === \"top\" ? 0 : 1;\n const branches = [\n `SELECT ${projectedColumns}, ${dataKind} AS ${quoteIdentifier(\n kindColumn,\n )}, ROW_NUMBER() OVER () AS ${quoteIdentifier(orderColumn)} FROM ${input}`,\n ...statRows.map((row, index) => {\n const projections = tableColumns.map((column) => {\n if (column === labelColumn) {\n return `CAST(? AS VARCHAR) AS ${quoteIdentifier(column)}`;\n }\n if (!selectedColumnSet.has(column)) {\n return `NULL AS ${quoteIdentifier(column)}`;\n }\n const expression = getStatExpression(\n row.stat,\n schema[column],\n quoteIdentifier(column),\n undefined,\n );\n if (expression === null) {\n throw new Error(\n `${method} stat ${JSON.stringify(\n row.stat,\n )} cannot be computed for column ${quoteIdentifier(\n column,\n )} with type ${schema[column]}.`,\n );\n }\n return `${expression} AS ${quoteIdentifier(column)}`;\n });\n return `SELECT ${projections.join(\", \")}, ${statKind} AS ${quoteIdentifier(\n kindColumn,\n )}, ${index} AS ${quoteIdentifier(orderColumn)} FROM ${input}`;\n }),\n ];\n\n return `SELECT ${projectedColumns}\nFROM (${branches.join(\"\\nUNION ALL\\n\")}) AS ${quoteIdentifier(\"stats\")}\nORDER BY ${quoteIdentifier(kindColumn)}, ${quoteIdentifier(orderColumn)}`;\n}\n\nfunction unusedColumn(schema: TableSchema, base: string): string {\n let column = base;\n while (schema[column] !== undefined) {\n column += \"_\";\n }\n return column;\n}\n","// from https://github.com/simple-statistics/simple-statistics/blob/main/src/combinations.js\n\nfunction getCombinations<T>(x: T[], k: 2): [T, T][];\nfunction getCombinations<T>(x: T[], k: number): T[][];\nfunction getCombinations<T>(x: T[], k: number): T[][] {\n let i;\n let subI;\n const combinationList: T[][] = [];\n let subsetCombinations;\n let next;\n\n for (i = 0; i < x.length; i++) {\n if (k === 1) {\n combinationList.push([x[i]]);\n } else {\n subsetCombinations = getCombinations(x.slice(i + 1, x.length), k - 1);\n for (subI = 0; subI < subsetCombinations.length; subI++) {\n next = subsetCombinations[subI];\n next.unshift(x[i]);\n combinationList.push(next);\n }\n }\n }\n return combinationList;\n}\n\nexport default getCombinations;\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport keepNumericalColumns from \"./keepNumericalColumns.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\n\n/**\n * Validates the column options shared by numerical pair analyses.\n *\n * @example\n * ```ts\n * const columns = validateNumericalAnalysis(\n * { x: \"DOUBLE\", y: \"BIGINT\" },\n * { x: \"x\" },\n * \"correlations()\",\n * \"measurements\",\n * );\n * ```\n *\n * @param types - The schema of the table being analyzed.\n *\n * @param options - The optional x and y columns selected by the caller.\n *\n * @param method - The SDA method performing the analysis.\n *\n * @param tableName - The name of the table being analyzed.\n *\n * @returns All numeric columns in the table schema.\n */\nexport default function validateNumericalAnalysis(\n types: TableSchema,\n options: { x?: string; y?: string },\n method: string,\n tableName: string,\n): string[] {\n if (options.x === undefined && options.y !== undefined) {\n throw new Error(\n `${method} options.y cannot be used without options.x. Provide options.x, or omit options.y to analyze every numeric column pair.`,\n );\n }\n\n const numericalColumns = keepNumericalColumns(types);\n const requestedColumns = [options.x, options.y].filter(\n (column): column is string => column !== undefined,\n );\n for (const column of requestedColumns) {\n const type = types[column];\n if (type === undefined) {\n const availableColumns = Object.keys(types).sort();\n throw new Error(\n `${method} could not find column ${quoteIdentifier(column)} in table ${quoteIdentifier(\n tableName,\n )}. Available columns: ${availableColumns.map(quoteIdentifier).join(\", \")}.`,\n );\n }\n if (!numericalColumns.includes(column)) {\n throw new Error(\n `${method} requires numeric columns, but column ${quoteIdentifier(\n column,\n )} in table ${quoteIdentifier(tableName)} has type ${type}. Convert ${quoteIdentifier(\n column,\n )} to a numeric type first.`,\n );\n }\n }\n\n if (options.y === undefined && numericalColumns.length < 2) {\n const found =\n numericalColumns.length === 0 ? \"\" : `: ${numericalColumns.map(quoteIdentifier).join(\", \")}`;\n const missingCount = 2 - numericalColumns.length;\n const columnsToConvert =\n numericalColumns.length === 0\n ? `${missingCount} columns`\n : `${missingCount} more column${missingCount === 1 ? \"\" : \"s\"}`;\n throw new Error(\n `${method} requires at least 2 numeric columns in table ${quoteIdentifier(\n tableName,\n )}, but found ${numericalColumns.length}${found}. Convert at least ${columnsToConvert} to ${\n missingCount === 1 ? \"a numeric type\" : \"numeric types\"\n } first.`,\n );\n }\n\n return numericalColumns;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getCombinations from \"../helpers/getCombinations.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport validateNumericalAnalysis from \"../helpers/validateNumericalAnalysis.ts\";\n\nexport default function correlations(\n simpleTable: SimpleTable,\n options: {\n x?: string;\n y?: string;\n by?: string | string[];\n decimals?: number;\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n options = structuredClone(options);\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n\n if (typeof options.outputTable === \"string\") {\n // The output table instance is created at call time so it can be\n // returned synchronously and chained on right away.\n const outputTable = simpleTable.sdb.newTable(options.outputTable);\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"correlations()\",\n parameters: { options },\n execute: async () => {\n const combinations = getCorrelationsCombinations(\n await simpleTable.getTypes(),\n options,\n simpleTable.name,\n );\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable.name)} AS ${correlationsSelect(\n `${quoteIdentifier(simpleTable.name)}`,\n combinations,\n options,\n )}`,\n mergeOptions(simpleTable, {\n table: outputTable.name,\n method: \"correlations()\",\n parameters: {\n options,\n \"combinations (computed)\": combinations,\n },\n values: correlationsValues(combinations),\n }),\n );\n },\n });\n return outputTable;\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"correlations()\",\n parameters: { options },\n needsSchema: true,\n values: (types) =>\n correlationsValues(getCorrelationsCombinations(types, options, simpleTable.name)),\n buildSelect: (input, types) =>\n correlationsSelect(\n input,\n getCorrelationsCombinations(types, options, simpleTable.name),\n options,\n ),\n });\n return simpleTable;\n}\n\nfunction correlationsValues(combinations: [string, string][]): string[] {\n return combinations.flatMap(([x, y]) => [x, y]);\n}\n\nfunction getCorrelationsCombinations(\n types: TableSchema,\n options: { x?: string; y?: string },\n tableName: string,\n): [string, string][] {\n const columns = validateNumericalAnalysis(types, options, \"correlations()\", tableName);\n let combinations: [string, string][] = [];\n if (options.x === undefined) {\n combinations = getCombinations(columns, 2);\n } else if (options.y === undefined) {\n combinations = [];\n for (const col of columns) {\n if (col !== options.x) {\n combinations.push([options.x, col]);\n }\n }\n } else {\n combinations = [[options.x, options.y]];\n }\n return combinations;\n}\n\nfunction correlationsSelect(\n input: string,\n combinations: [string, string][],\n options: {\n by?: string | string[];\n decimals?: number;\n },\n) {\n const by = options.by ? stringToArray(options.by) : [];\n\n const groupBy =\n by.length === 0 ? \"\" : ` GROUP BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")}`;\n\n const catSelect = by.length > 0 ? `${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")}, ` : \"\";\n\n // One UNION ALL branch per pair (each with a distinct pair of literals, so\n // deduplication would never remove anything). DuckDB runs the branches as\n // concurrent pipelines, which parallelizes the aggregates better than\n // computing them all in one scan.\n const branches = combinations.map((comb) => {\n const expression =\n typeof options.decimals === \"number\"\n ? `ROUND(corr(${quoteIdentifier(comb[0])}, ${quoteIdentifier(\n comb[1],\n )}), ${options.decimals})`\n : `corr(${quoteIdentifier(comb[0])}, ${quoteIdentifier(comb[1])})`;\n return `SELECT ${catSelect}? AS ${quoteIdentifier(\"x\")}, ? AS ${quoteIdentifier(\n \"y\",\n )}, ${expression} AS ${quoteIdentifier(\"corr\")} FROM ${input}${groupBy}`;\n });\n\n return branches.join(\"\\nUNION ALL\\n\");\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getCombinations from \"../helpers/getCombinations.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport validateNumericalAnalysis from \"../helpers/validateNumericalAnalysis.ts\";\n\nexport default function linearRegressions(\n simpleTable: SimpleTable,\n options: {\n x?: string;\n y?: string;\n by?: string | string[];\n decimals?: number;\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n options = structuredClone(options);\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n\n if (typeof options.outputTable === \"string\") {\n // The output table instance is created at call time so it can be\n // returned synchronously and chained on right away.\n const outputTable = simpleTable.sdb.newTable(options.outputTable);\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"linearRegressions()\",\n parameters: { options },\n execute: async () => {\n const permutations = getLinearRegressionsPermutations(\n await simpleTable.getTypes(),\n options,\n simpleTable.name,\n );\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable.name)} AS ${linearRegressionsSelect(\n `${quoteIdentifier(simpleTable.name)}`,\n permutations,\n options,\n )}`,\n mergeOptions(simpleTable, {\n table: outputTable.name,\n method: \"linearRegressions()\",\n parameters: {\n options,\n \"permutations (computed)\": permutations,\n },\n values: linearRegressionsValues(permutations),\n }),\n );\n },\n });\n return outputTable;\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"linearRegressions()\",\n parameters: { options },\n needsSchema: true,\n values: (types) =>\n linearRegressionsValues(getLinearRegressionsPermutations(types, options, simpleTable.name)),\n buildSelect: (input, types) =>\n linearRegressionsSelect(\n input,\n getLinearRegressionsPermutations(types, options, simpleTable.name),\n options,\n ),\n });\n return simpleTable;\n}\n\nfunction linearRegressionsValues(permutations: [string, string][]): string[] {\n return permutations.flatMap(([x, y]) => [x, y]);\n}\n\nfunction getLinearRegressionsPermutations(\n types: TableSchema,\n options: { x?: string; y?: string },\n tableName: string,\n): [string, string][] {\n const columns = validateNumericalAnalysis(types, options, \"linearRegressions()\", tableName);\n const permutations: [string, string][] = [];\n if (options.x === undefined) {\n const combinations = getCombinations(columns, 2);\n for (const c of combinations) {\n permutations.push(c);\n permutations.push([c[1], c[0]]);\n }\n } else if (options.y === undefined) {\n for (const col of columns) {\n if (col !== options.x) {\n permutations.push([options.x, col]);\n }\n }\n } else {\n permutations.push([options.x, options.y]);\n }\n return permutations;\n}\n\nfunction linearRegressionsSelect(\n input: string,\n permutations: [string, string][],\n options: {\n by?: string | string[];\n decimals?: number;\n },\n) {\n const by = options.by ? stringToArray(options.by) : [];\n\n const groupBy =\n by.length === 0 ? \"\" : ` GROUP BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")}`;\n\n const catSelect = by.length > 0 ? `${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")}, ` : \"\";\n\n // One UNION ALL branch per permutation (each with a distinct pair of\n // literals, so deduplication would never remove anything). DuckDB runs the\n // branches as concurrent pipelines, which parallelizes the aggregates\n // better than computing them all in one scan.\n const branches = permutations.map((perm) => {\n const expressions = [\n [\"slope\", \"REGR_SLOPE\"],\n [\"yIntercept\", \"REGR_INTERCEPT\"],\n [\"r2\", \"REGR_R2\"],\n ].map(([alias, fn]) => {\n const expression =\n typeof options.decimals === \"number\"\n ? `ROUND(${fn}(${quoteIdentifier(perm[1])}, ${quoteIdentifier(\n perm[0],\n )}), ${options.decimals})`\n : `${fn}(${quoteIdentifier(perm[1])}, ${quoteIdentifier(perm[0])})`;\n return `${expression} AS ${quoteIdentifier(alias)}`;\n });\n return `SELECT ${catSelect}? AS ${quoteIdentifier(\"x\")}, ? AS ${quoteIdentifier(\n \"y\",\n )}, ${expressions.join(\", \")}\n FROM ${input}${groupBy}`;\n });\n\n return branches.join(\"\\nUNION ALL\\n\");\n}\n","/**\n * Capitalizes the first letter of a given string.\n *\n * @example\n * ```ts\n * // Basic usage\n * const capitalized = capitalize(\"hello world\");\n * console.log(capitalized); // \"Hello world\"\n * ```\n *\n * @example\n * ```ts\n * // With an already capitalized string\n * const alreadyCapitalized = capitalize(\"Journalism\");\n * console.log(alreadyCapitalized); // \"Journalism\"\n * ```\n *\n * @example\n * ```ts\n * // With a single character\n * const singleChar = capitalize(\"a\");\n * console.log(singleChar); // \"A\"\n * ```\n *\n * @param string - The string to be capitalized.\n *\n * @returns A new string with the first letter in uppercase.\n */\nexport default function capitalize(string: string): string {\n if (string.length === 0) {\n return string;\n }\n const first = string[0];\n return first.toUpperCase() + string.slice(1);\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\n\n/**\n * Returns the only geometry column in a table schema.\n *\n * @example\n * ```ts\n * const column = findGeoColumnFromSchema(\n * { geom: \"GEOMETRY('EPSG:4326')\" },\n * \"area()\",\n * \"places\",\n * );\n * ```\n *\n * @param types - The table schema to inspect.\n *\n * @param method - The SDA method requesting a geometry column.\n *\n * @param tableName - The name of the table represented by the schema.\n *\n * @returns The name of the only geometry column.\n */\nexport default function findGeoColumnFromSchema(\n types: TableSchema,\n method: string,\n tableName: string,\n): string {\n const geometryColumns = Object.keys(types)\n .filter((column) => types[column].toLowerCase().includes(\"geometry\"))\n .sort();\n if (geometryColumns.length === 0) {\n throw new Error(\n `${method} could not find a geometry column in table ${quoteIdentifier(\n tableName,\n )}. Specify a geometry column explicitly, or add one to the table first.`,\n );\n } else if (geometryColumns.length > 1) {\n throw new Error(\n `${method} found ${geometryColumns.length} geometry columns in table ${quoteIdentifier(\n tableName,\n )}: ${geometryColumns.map(quoteIdentifier).join(\", \")}. Specify one explicitly.`,\n );\n }\n return geometryColumns[0];\n}\n","export default function getIdenticalColumns(table1Columns: string[], table2Columns: string[]) {\n return table1Columns.filter((column) => table2Columns.includes(column));\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Throws when a method receives a table owned by another database connection.\n *\n * @param simpleDB - The database on which the method will execute.\n * @param tables - The tables that must belong to `simpleDB`.\n * @param method - The SDA method name used in the error message.\n */\nexport default function assertSameDatabase(\n simpleDB: SimpleDB,\n tables: SimpleTable[],\n method: string,\n): void {\n const foreignTables = tables.filter((table) => table.sdb !== simpleDB);\n if (foreignTables.length > 0) {\n throw new Error(\n `${method} all tables must belong to the same SimpleDB instance. The following table${\n foreignTables.length === 1 ? \" belongs\" : \"s belong\"\n } to another database: ${foreignTables\n .map((table) => JSON.stringify(table.name))\n .join(\", \")}.`,\n );\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport capitalize from \"../helpers/capitalize.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport getIdenticalColumns from \"../helpers/getIdenticalColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\n\nexport default function joinGeo(\n leftTable: SimpleTable,\n method: \"intersect\" | \"inside\" | \"withinDistance\",\n rightTable: SimpleTable,\n options: {\n leftColumn?: string;\n rightColumn?: string;\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n distance?: number;\n distanceMethod?: \"srs\" | \"haversine\" | \"spheroid\";\n excludeLeftGeometry?: boolean;\n excludeRightGeometry?: boolean;\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n assertSameDatabase(leftTable.sdb, [rightTable], \"joinGeo()\");\n options = structuredClone(options);\n validateJoinGeoOptions(method, options);\n // The output table instance is created at call time so it can be returned\n // synchronously and chained on right away.\n const outputTable =\n typeof options.outputTable === \"string\"\n ? leftTable.sdb.newTable(options.outputTable)\n : leftTable;\n\n queueOp(outputTable, {\n kind: \"source\",\n rawSQL: [quoteIdentifier(leftTable.name), quoteIdentifier(rightTable.name)],\n needsSpatial: true,\n method: \"joinGeo()\",\n parameters: { method, rightTable: rightTable.name, options },\n buildSelect: () => buildJoinGeoSelect(leftTable, method, rightTable, options),\n });\n\n return outputTable;\n}\n\nfunction validateJoinGeoOptions(\n method: \"intersect\" | \"inside\" | \"withinDistance\",\n options: {\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n distance?: number;\n distanceMethod?: \"srs\" | \"haversine\" | \"spheroid\";\n },\n): void {\n if (![\"intersect\", \"inside\", \"withinDistance\"].includes(method)) {\n throw new Error(\n `joinGeo() method must be \"intersect\", \"inside\", or \"withinDistance\". Received ${formatReceivedValue(\n method,\n )}.`,\n );\n }\n if (options.type !== undefined && ![\"inner\", \"left\", \"right\", \"full\"].includes(options.type)) {\n throw new Error(\n `joinGeo() options.type must be \"inner\", \"left\", \"right\", or \"full\". Received ${formatReceivedValue(\n options.type,\n )}.`,\n );\n }\n if (\n options.distanceMethod !== undefined &&\n ![\"srs\", \"haversine\", \"spheroid\"].includes(options.distanceMethod)\n ) {\n throw new Error(\n `joinGeo() options.distanceMethod must be \"srs\", \"haversine\", or \"spheroid\". Received ${formatReceivedValue(\n options.distanceMethod,\n )}.`,\n );\n }\n if (\n method === \"withinDistance\" &&\n (typeof options.distance !== \"number\" || !Number.isFinite(options.distance))\n ) {\n throw new Error(\n `joinGeo() options.distance must be a finite number when method is \"withinDistance\". Received ${formatReceivedValue(\n options.distance,\n )}.`,\n );\n }\n}\n\nfunction formatReceivedValue(value: unknown): string {\n return JSON.stringify(value) ?? String(value);\n}\n\nasync function buildJoinGeoSelect(\n leftTable: SimpleTable,\n method: \"intersect\" | \"inside\" | \"withinDistance\",\n rightTable: SimpleTable,\n options: {\n leftColumn?: string;\n rightColumn?: string;\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n distance?: number;\n distanceMethod?: \"srs\" | \"haversine\" | \"spheroid\";\n excludeLeftGeometry?: boolean;\n excludeRightGeometry?: boolean;\n },\n): Promise<string> {\n const leftTypes = await leftTable.getTypes();\n const rightTypes = await rightTable.getTypes();\n const leftColumn =\n options.leftColumn ?? findGeoColumnFromSchema(leftTypes, \"joinGeo()\", leftTable.name);\n const rightColumn =\n options.rightColumn ?? findGeoColumnFromSchema(rightTypes, \"joinGeo()\", rightTable.name);\n\n const leftTableColumns = Object.keys(leftTypes);\n const rightTableColumns = Object.keys(rightTypes);\n const sharedColumn = leftColumn === rightColumn ? leftColumn : \"\";\n const identicalColumns = getIdenticalColumns(leftTableColumns, rightTableColumns).filter(\n (d) => d !== sharedColumn,\n );\n if (identicalColumns.length > 0) {\n throw new Error(\n `The tables have columns with identical names ${\n sharedColumn !== \"\"\n ? `(excluding the columns ${quoteIdentifier(sharedColumn)} used for the geospatial join)`\n : \"\"\n }. Rename or remove ${identicalColumns\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")} in one of the two tables before doing the join.`,\n );\n }\n\n const excludeLeftGeometry = options.excludeLeftGeometry ?? false;\n const excludeRightGeometry = options.excludeRightGeometry ?? false;\n const retainSharedGeometries =\n sharedColumn !== \"\" && !excludeLeftGeometry && !excludeRightGeometry;\n const rightGeometryOutputColumn = retainSharedGeometries\n ? `${rightColumn}${capitalize(rightTable.name)}`\n : undefined;\n\n if (\n rightGeometryOutputColumn !== undefined &&\n [...leftTableColumns, ...rightTableColumns]\n .filter((column) => column !== rightColumn)\n .includes(rightGeometryOutputColumn)\n ) {\n throw new Error(\n `Cannot name the right geometry column ${quoteIdentifier(\n rightGeometryOutputColumn,\n )} because a column with that name already exists. Rename the existing ${quoteIdentifier(\n rightGeometryOutputColumn,\n )} column before calling joinGeo(), or call joinGeo() with { excludeRightGeometry: true }.`,\n );\n }\n\n const leftSelect = `${quoteIdentifier(leftTable.name)}.*${\n excludeLeftGeometry ? ` EXCLUDE (${quoteIdentifier(leftColumn)})` : \"\"\n }`;\n const excludeRightFromStar = excludeRightGeometry || retainSharedGeometries;\n const rightSelect = `${quoteIdentifier(rightTable.name)}.*${\n excludeRightFromStar ? ` EXCLUDE (${quoteIdentifier(rightColumn)})` : \"\"\n }`;\n const selectList = [\n leftSelect,\n rightSelect,\n ...(rightGeometryOutputColumn === undefined\n ? []\n : [\n `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(rightColumn)} AS ${quoteIdentifier(\n rightGeometryOutputColumn,\n )}`,\n ]),\n ].join(\", \");\n\n const type = options.type ?? \"left\";\n\n return joinGeoQuery(\n leftTable.name,\n leftColumn,\n method,\n rightTable.name,\n rightColumn,\n type,\n selectList,\n options.distance,\n options.distanceMethod,\n );\n}\n\nfunction joinGeoQuery(\n leftTable: string,\n leftColumn: string,\n method: \"intersect\" | \"inside\" | \"withinDistance\",\n rightTable: string,\n rightColumn: string,\n join: \"inner\" | \"left\" | \"right\" | \"full\",\n selectList: string,\n distance: number | undefined,\n distanceMethod: \"srs\" | \"haversine\" | \"spheroid\" | undefined,\n) {\n let query = `SELECT ${selectList}`;\n if (join === \"inner\") {\n query += ` FROM ${quoteIdentifier(leftTable)} JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"left\") {\n query += ` FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"right\") {\n query += ` FROM ${quoteIdentifier(leftTable)} RIGHT JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"full\") {\n query += ` FROM ${quoteIdentifier(leftTable)} FULL JOIN ${quoteIdentifier(rightTable)}`;\n } else {\n throw new Error(`Unknown ${String(join)} join.`);\n }\n\n if (method === \"intersect\") {\n query += ` ON ST_Intersects(${quoteIdentifier(leftTable)}.${quoteIdentifier(\n leftColumn,\n )}, ${quoteIdentifier(rightTable)}.${quoteIdentifier(rightColumn)})`;\n } else if (method === \"inside\") {\n // Order is important\n query += ` ON ST_Covers(${quoteIdentifier(rightTable)}.${quoteIdentifier(\n rightColumn,\n )}, ${quoteIdentifier(leftTable)}.${quoteIdentifier(leftColumn)})`;\n } else if (method === \"withinDistance\") {\n if (typeof distance === \"number\") {\n if (distanceMethod === undefined || distanceMethod === \"srs\") {\n query += ` ON ST_DWithin(${quoteIdentifier(leftTable)}.${quoteIdentifier(\n leftColumn,\n )}, ${quoteIdentifier(rightTable)}.${quoteIdentifier(rightColumn)}, ${distance})`;\n } else if (distanceMethod === \"haversine\") {\n // Maybe ST_DWithin_Sphere will be available soon?\n query += ` ON ST_Distance_Sphere(${quoteIdentifier(leftTable)}.${quoteIdentifier(\n leftColumn,\n )}, ${quoteIdentifier(rightTable)}.${quoteIdentifier(rightColumn)}) < ${distance}`;\n } else if (distanceMethod === \"spheroid\") {\n // Should be using ST_DWithin_Spheroid but doesn't work?\n query += ` ON ST_Distance_Spheroid(${quoteIdentifier(leftTable)}.${quoteIdentifier(\n leftColumn,\n )}::GEOMETRY, ${quoteIdentifier(rightTable)}.${quoteIdentifier(\n rightColumn,\n )}::GEOMETRY) < ${distance}`;\n } else {\n throw new Error(`Unknown ${String(distanceMethod)}`);\n }\n } else {\n throw new Error(\"options.distance must be a number\");\n }\n } else {\n throw new Error(`Unknown ${String(method)} method`);\n }\n\n return query;\n}\n","/**\n * Formats a duration into a human-readable string, breaking it down into years, months, days, hours, minutes, seconds, and milliseconds. This function is useful for displaying elapsed time in a user-friendly format, such as for performance logging, task completion times, or general time tracking.\n *\n * The function can calculate the duration from a given start time to the current time, or between a specified start and end time. It provides options for logging the output directly to the console and adding custom prefixes or suffixes to the formatted string. Note that for simplicity, months are approximated as 30 days and years as 365 days.\n *\n * @example\n * ```ts\n * // A starting Date somewhere in your code.\n * const startDate = new Date(); // or Date.now()\n *\n * // When you want to know the elapsed duration, pass the start date.\n * const duration = prettyDuration(startDate);\n * console.log(duration); // Returns something like \"22 days, 6 h, 3 min, 15 sec, 3 ms\"\n * ```\n *\n * @example\n * ```ts\n * // If you want to console.log it directly, set the `log` option to `true`.\n * // This will print the duration to the console and also return the string.\n * const startDateForLog = new Date();\n * // ... some operations ...\n * prettyDuration(startDateForLog, { log: true });\n * ```\n *\n * @example\n * ```ts\n * // You can also use a prefix and/or suffix for the output string.\n * const startDateWithPrefixSuffix = new Date();\n * // ... some operations ...\n * prettyDuration(startDateWithPrefixSuffix, { log: true, prefix: \"Elapsed time: \", suffix: \" (Main function)\" });\n * // Returns and logs something like \"Total duration: 3 min, 15 sec, 3 ms (Main function)\"\n * ```\n *\n * @example\n * ```ts\n * // If you want to format the duration between two specific dates, use the `end` option.\n * const start = new Date(\"2024-01-01T17:00:00Z\");\n * const end = new Date(\"2024-01-23T23:03:15Z\");\n * const specificDuration = prettyDuration(start, { end });\n * console.log(specificDuration); // Returns \"22 days, 6 h, 3 min, 15 sec, 0 ms\"\n * ```\n *\n * @param start - The starting point of the duration. This can be a `Date` object or a Unix timestamp (number of milliseconds since epoch).\n *\n * @param options - Optional settings to customize the duration formatting and output.\n * @param options.log - If `true`, the formatted duration string will be logged to the console. Defaults to `false`.\n * @param options.end - The ending point of the duration. This can be a `Date` object or a Unix timestamp. If omitted, the current time (`Date.now()`) will be used as the end point.\n * @param options.prefix - A string to prepend to the formatted duration string (e.g., \"Elapsed time: \").\n * @param options.suffix - A string to append to the formatted duration string (e.g., \" (Task completed)\").\n *\n * @returns A human-readable string representing the duration.\n *\n * @category Formatting\n */\nexport default function prettyDuration(\n start: Date | number,\n options: {\n log?: boolean;\n end?: Date | number;\n prefix?: string;\n suffix?: string;\n } = {},\n): string {\n if (start instanceof Date) {\n start = start.getTime();\n }\n\n let end;\n if (options.end instanceof Date) {\n end = options.end.getTime();\n } else if (typeof options.end === \"number\") {\n end = options.end;\n } else {\n end = Date.now();\n }\n\n const differenceInMs = end - start;\n\n let prettyDuration = \"\";\n\n if (differenceInMs < 1000) {\n // Less than a second\n prettyDuration = `${differenceInMs} ms`;\n } else if (differenceInMs < 60_000) {\n // Less than a minute\n const sec = Math.floor(differenceInMs / 1000);\n const ms = differenceInMs % 1000;\n prettyDuration = `${sec} sec, ${ms} ms`;\n } else if (differenceInMs < 3_600_000) {\n // Less than an hour\n const min = Math.floor(differenceInMs / 60_000);\n const remainingMs = differenceInMs % 60_000;\n const sec = Math.floor(remainingMs / 1000);\n const ms = remainingMs % 1000;\n prettyDuration = `${min} min, ${sec} sec, ${ms} ms`;\n } else if (differenceInMs < 86_400_000) {\n // Less than a day\n const hours = Math.floor(differenceInMs / 3_600_000);\n const remainingMsAfterHours = differenceInMs % 3_600_000;\n const min = Math.floor(remainingMsAfterHours / 60_000);\n const remainingMsAfterMinutes = remainingMsAfterHours % 60_000;\n const sec = Math.floor(remainingMsAfterMinutes / 1000);\n const ms = remainingMsAfterMinutes % 1000;\n prettyDuration = `${hours} h, ${min} min, ${sec} sec, ${ms} ms`;\n } else if (differenceInMs < 2_592_000_000) {\n // Less than a month\n const days = Math.floor(differenceInMs / 86_400_000);\n const remainingMsAfterDays = differenceInMs % 86_400_000;\n const hours = Math.floor(remainingMsAfterDays / 3_600_000);\n const remainingMsAfterHours = remainingMsAfterDays % 3_600_000;\n const min = Math.floor(remainingMsAfterHours / 60_000);\n const remainingMsAfterMin = remainingMsAfterHours % 60_000;\n const sec = Math.floor(remainingMsAfterMin / 1000);\n const ms = remainingMsAfterMin % 1000;\n prettyDuration = `${days} ${\n days <= 1 ? \"day\" : \"days\"\n }, ${hours} h, ${min} min, ${sec} sec, ${ms} ms`;\n } else if (differenceInMs < 31_536_000_000) {\n // Less than a year\n const months = Math.floor(differenceInMs / 2_592_000_000);\n const remainingMsAfterMonths = differenceInMs % 2_592_000_000;\n const days = Math.floor(remainingMsAfterMonths / 86_400_000);\n const remainingMsAfterDays = differenceInMs % 86_400_000;\n const hours = Math.floor(remainingMsAfterDays / 3_600_000);\n const remainingMsAfterHours = remainingMsAfterDays % 3_600_000;\n const min = Math.floor(remainingMsAfterHours / 60_000);\n const remainingMsAfterMin = remainingMsAfterHours % 60_000;\n const sec = Math.floor(remainingMsAfterMin / 1000);\n const ms = remainingMsAfterMin % 1000;\n prettyDuration = `${months} ${months <= 1 ? \"month\" : \"months\"}, ${days} ${\n days <= 1 ? \"day\" : \"days\"\n }, ${hours} h, ${min} min, ${sec} sec, ${ms} ms`;\n } else {\n // More than a year\n const years = Math.floor(differenceInMs / 31_536_000_000);\n const remainingMsAfterYears = differenceInMs % 31_536_000_000;\n const months = Math.floor(remainingMsAfterYears / 2_592_000_000);\n const remainingMsAfterMonths = differenceInMs % 2_592_000_000;\n const days = Math.floor(remainingMsAfterMonths / 86_400_000);\n const remainingMsAfterDays = differenceInMs % 86_400_000;\n const hours = Math.floor(remainingMsAfterDays / 3_600_000);\n const remainingMsAfterHours = remainingMsAfterDays % 3_600_000;\n const min = Math.floor(remainingMsAfterHours / 60_000);\n const remainingMsAfterMin = remainingMsAfterHours % 60_000;\n const sec = Math.floor(remainingMsAfterMin / 1000);\n const ms = remainingMsAfterMin % 1000;\n prettyDuration = `${years} ${years <= 1 ? \"year\" : \"years\"}, ${months} ${\n months <= 1 ? \"month\" : \"months\"\n }, ${days} ${days <= 1 ? \"day\" : \"days\"}, ${hours} h, ${min} min, ${sec} sec, ${ms} ms`;\n }\n\n if (typeof options.prefix === \"string\") {\n prettyDuration = `${options.prefix}${prettyDuration}`;\n }\n if (typeof options.suffix === \"string\") {\n prettyDuration = `${prettyDuration}${options.suffix}`;\n }\n\n if (options.log === true) {\n console.log(prettyDuration);\n }\n\n return prettyDuration;\n}\n","type Token = {\n kind: \"word\" | \"punctuation\" | \"literal\" | \"template\";\n text: string;\n lineBreak: boolean;\n};\n\nconst lineTerminator = /[\\r\\n\\u2028\\u2029]/u;\nconst word = /^[$_\\p{ID_Start}][$\\u200c\\u200d\\p{ID_Continue}]*/u;\nconst number =\n /^(?:0[xX][\\da-fA-F_]+n?|0[bB][01_]+n?|0[oO][0-7_]+n?|(?:\\d[\\d_]*(?:\\.[\\d_]*)?|\\.[\\d_]+)(?:[eE][+-]?[\\d_]+)?n?)/;\nconst punctuation =\n /^(?:>>>=|===|!==|\\*\\*=|&&=|\\|\\|=|\\?\\?=|>>>|<<=|>>=|=>|==|!=|<=|>=|\\+\\+|--|&&|\\|\\||\\?\\?|\\?\\.(?!\\d)|\\*\\*|<<|>>|\\+=|-=|\\*=|%=|&=|\\|=|\\^=|\\.\\.\\.|[{}()[\\].,;:?~!+*%<>=&|^\\-#])/;\nconst expressionPrefixes = new Set([\n \"(\",\n \"[\",\n \"{\",\n \",\",\n \";\",\n \":\",\n \"?\",\n \"=\",\n \"=>\",\n \"!\",\n \"~\",\n \"+\",\n \"-\",\n \"*\",\n \"**\",\n \"%\",\n \"&\",\n \"|\",\n \"^\",\n \"&&\",\n \"||\",\n \"??\",\n \"==\",\n \"===\",\n \"!=\",\n \"!==\",\n \"<\",\n \">\",\n \"<=\",\n \">=\",\n \"<<\",\n \">>\",\n \">>>\",\n \"+=\",\n \"-=\",\n \"*=\",\n \"**=\",\n \"%=\",\n \"&=\",\n \"|=\",\n \"^=\",\n \"&&=\",\n \"||=\",\n \"??=\",\n \"<<=\",\n \">>=\",\n \">>>=\",\n \"/\",\n \"/=\",\n]);\nconst expressionKeywords = new Set([\n \"return\",\n \"throw\",\n \"case\",\n \"delete\",\n \"void\",\n \"typeof\",\n \"new\",\n \"in\",\n \"instanceof\",\n \"yield\",\n \"await\",\n \"else\",\n \"do\",\n]);\nconst restrictedLineBreaks = new Set([\n \"return\",\n \"throw\",\n \"break\",\n \"continue\",\n \"yield\",\n \"async\",\n \"++\",\n \"--\",\n]);\n\n/**\n * Normalizes comments, whitespace, and known optional punctuation without\n * dependencies or executing user code. Literal contents and token boundaries\n * stay intact. Potentially significant line breaks are retained; ambiguous\n * slash syntax falls back to exact source instead of risking a stale cache hit.\n */\nexport default function normalizeCacheCode(source: string): string {\n let position = 0;\n let uncertain = false;\n\n function quoted(quote: string): string | undefined {\n const start = position++;\n while (position < source.length) {\n const character = source[position++];\n if (character === \"\\\\\") {\n position++;\n } else if (character === quote) {\n return source.slice(start, position);\n } else if (lineTerminator.test(character)) {\n return undefined;\n }\n }\n }\n\n function template(): string | undefined {\n const parts: string[] = [];\n let start = ++position;\n while (position < source.length) {\n if (source[position] === \"\\\\\") {\n position += 2;\n } else if (source[position] === \"`\") {\n parts.push(source.slice(start, position++));\n return JSON.stringify(parts);\n } else if (source.startsWith(\"${\", position)) {\n parts.push(source.slice(start, position));\n position += 2;\n const tokens = scan(true);\n if (uncertain) return undefined;\n parts.push(serialize(tokens));\n start = position;\n } else {\n position++;\n }\n }\n }\n\n function regex(): string | undefined {\n const start = position++;\n let inClass = false;\n while (position < source.length) {\n const character = source[position++];\n if (lineTerminator.test(character)) return undefined;\n if (character === \"\\\\\") {\n position++;\n } else if (character === \"[\") {\n // Nested character classes depend on the v flag. Leave these opaque.\n if (inClass) return undefined;\n inClass = true;\n } else if (character === \"]\") {\n inClass = false;\n } else if (character === \"/\" && !inClass) {\n const flags = source.slice(position).match(word)?.[0] ?? \"\";\n position += flags.length;\n return source.slice(start, position);\n }\n }\n }\n\n function scan(interpolation = false): Token[] {\n const tokens: Token[] = [];\n let braces = 0;\n let lineBreak = false;\n while (position < source.length) {\n const rest = source.slice(position);\n const character = source[position];\n if (/\\s/u.test(character)) {\n lineBreak ||= lineTerminator.test(character);\n position++;\n continue;\n }\n if (rest.startsWith(\"//\")) {\n while (position < source.length && !lineTerminator.test(source[position])) {\n position++;\n }\n continue;\n }\n if (rest.startsWith(\"/*\")) {\n const end = source.indexOf(\"*/\", position + 2);\n if (end === -1) break;\n lineBreak ||= lineTerminator.test(source.slice(position, end + 2));\n position = end + 2;\n continue;\n }\n if (interpolation && character === \"}\" && braces === 0) {\n position++;\n return tokens;\n }\n // Legacy HTML comments and native function text are not ordinary tokens.\n if (rest.startsWith(\"<!--\") || rest.startsWith(\"-->\") || rest.startsWith(\"[native code]\"))\n break;\n\n const previous = tokens.at(-1);\n let kind: Token[\"kind\"] = \"punctuation\";\n let text: string | undefined;\n if (character === \"'\" || character === '\"') {\n kind = \"literal\";\n text = quoted(character);\n } else if (character === \"`\") {\n kind = \"template\";\n text = template();\n } else if (character === \"/\") {\n const property = [\".\", \"?.\"].includes(tokens.at(-2)?.text ?? \"\");\n if (\n !previous ||\n (previous.kind === \"punctuation\" && expressionPrefixes.has(previous.text)) ||\n (previous.kind === \"word\" && !property && expressionKeywords.has(previous.text))\n ) {\n kind = \"literal\";\n text = regex();\n } else if (previous.kind === \"literal\" || previous.kind === \"template\") {\n text = rest.startsWith(\"/=\") ? \"/=\" : \"/\";\n position += text.length;\n } else {\n // After a closing block/parenthesis or contextual keyword, deciding\n // between division and a regex can require a full JavaScript parser.\n break;\n }\n } else {\n text = rest.match(word)?.[0];\n if (text !== undefined) {\n kind = \"word\";\n } else {\n text = rest.match(number)?.[0];\n if (text !== undefined) kind = \"literal\";\n else text = rest.match(punctuation)?.[0];\n }\n if (text !== undefined) position += text.length;\n }\n if (text === undefined) {\n uncertain = true;\n break;\n }\n if (kind === \"punctuation\") {\n if (text === \"{\") braces++;\n if (text === \"}\") braces--;\n }\n tokens.push({ kind, text, lineBreak });\n lineBreak = false;\n }\n if (position < source.length || interpolation) uncertain = true;\n return tokens;\n }\n\n const tokens = scan();\n return uncertain\n ? JSON.stringify([\"source\", source])\n : JSON.stringify([\"tokens\", serialize(tokens)]);\n}\n\nfunction serialize(tokens: Token[]): string {\n tokens = normalizePunctuation(tokens);\n return JSON.stringify(\n tokens.map((token, index) => {\n const previous = tokens[index - 1];\n // Only discard newlines where continuation is certain. Keeping other\n // newlines permits conservative misses rather than unsafe cache hits.\n const significant =\n token.lineBreak &&\n previous !== undefined &&\n (restrictedLineBreaks.has(previous.text) ||\n [\"++\", \"--\"].includes(token.text) ||\n !(\n (previous.kind === \"punctuation\" &&\n (expressionPrefixes.has(previous.text) ||\n [\".\", \"?.\", \"}\"].includes(previous.text))) ||\n (token.kind === \"punctuation\" &&\n ([\")\", \"]\", \"}\", \",\", \";\", \".\", \"?.\"].includes(token.text) ||\n (expressionPrefixes.has(token.text) &&\n ![\"(\", \"[\", \"{\", \"!\", \"~\"].includes(token.text))))\n ));\n return [token.kind, token.text, significant];\n }),\n );\n}\n\nfunction normalizePunctuation(input: Token[]): Token[] {\n const tokens = input.map((token) => ({ ...token }));\n const result: Token[] = [];\n const brackets: { text: string; control: boolean }[] = [];\n const controls = new Set([\"if\", \"while\", \"for\", \"with\", \"switch\", \"catch\"]);\n let previousControl = false;\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const next = tokens[i + 1];\n const previous = result.at(-1);\n if (token.kind === \"literal\" && /^[\"']/.test(token.text) && !token.text.includes(\"\\\\\")) {\n token.text = JSON.stringify(token.text.slice(1, -1));\n }\n // A single arrow parameter has the same binding with or without parentheses.\n if (\n token.text === \"(\" &&\n tokens[i + 1]?.kind === \"word\" &&\n tokens[i + 2]?.text === \")\" &&\n tokens[i + 3]?.text === \"=>\"\n ) {\n result.push({ ...tokens[i + 1], lineBreak: token.lineBreak });\n i += 2;\n previousControl = false;\n continue;\n }\n // Retain commas representing array holes, including the final hole.\n if (\n token.text === \",\" &&\n [\")\", \"]\", \"}\"].includes(next?.text ?? \"\") &&\n previous &&\n ![\",\", \"[\", \"(\"].includes(previous.text)\n )\n continue;\n\n const expressionEnd =\n previous &&\n (previous.kind !== \"punctuation\" ||\n previous.text === \"]\" ||\n (previous.text === \")\" && !previousControl));\n if (\n token.text === \";\" &&\n brackets.at(-1)?.text === \"{\" &&\n expressionEnd &&\n !restrictedLineBreaks.has(previous.text)\n ) {\n if (next?.text === \"}\") continue;\n // A call followed by an identifier starts a new statement. Preserve that\n // boundary as a newline so explicit and automatically inserted semicolons\n // agree. Never do this in a for header or after a control header.\n if (\n previous.text === \")\" &&\n next?.kind === \"word\" &&\n ![\"in\", \"instanceof\", \"of\"].includes(next.text)\n ) {\n next.lineBreak = true;\n continue;\n }\n }\n previousControl = false;\n if ([\"(\", \"[\", \"{\"].includes(token.text)) {\n brackets.push({\n text: token.text,\n control:\n token.text === \"(\" &&\n (controls.has(previous?.text ?? \"\") ||\n (previous?.text === \"await\" && result.at(-2)?.text === \"for\")),\n });\n } else if ([\")\", \"]\", \"}\"].includes(token.text)) {\n previousControl = brackets.pop()?.control ?? false;\n }\n result.push(token);\n }\n return result;\n}\n","const MONTHS = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\",\n];\n\n/**\n * Formats a `Date` object into a human-readable string using only the format\n * strings actually used in the project.\n *\n * @example\n * ```ts\n * // Format a date with time (local time).\n * const date = new Date(\"2023-01-01T01:35:00\");\n * const formatted = formatDate(date, \"Month DD, YYYY, at HH:MM period\");\n * console.log(formatted); // \"January 1, 2023, at 1:35 a.m.\"\n * ```\n *\n * @example\n * ```ts\n * // Format a date as month and day only (UTC).\n * const formatted = formatDate(new Date(\"2023-01-01\"), \"Month DD\", { utc: true });\n * console.log(formatted); // \"January 1\"\n * ```\n *\n * @example\n * ```ts\n * // Minutes of \":00\" are omitted.\n * const formatted = formatDate(new Date(\"2023-01-01T01:00:00\"), \"Month DD, YYYY, at HH:MM period\", { utc: true });\n * console.log(formatted); // \"January 1, 2023, at 1 a.m.\"\n * ```\n *\n * @param date - The `Date` object to format.\n *\n * @param format - The format string to use. Only `\"Month DD, YYYY, at HH:MM period\"` and `\"Month DD\"` are supported.\n *\n * @param options - Optional settings.\n *\n * @param options.utc - If `true`, format the date in UTC instead of local time. Defaults to `false`.\n *\n * @returns The formatted date string.\n */\nexport default function formatDate(\n date: Date,\n format: \"Month DD, YYYY, at HH:MM period\" | \"Month DD\",\n options: { utc?: boolean } = {},\n): string {\n const year = options.utc ? date.getUTCFullYear() : date.getFullYear();\n const month = MONTHS[options.utc ? date.getUTCMonth() : date.getMonth()];\n const day = options.utc ? date.getUTCDate() : date.getDate();\n const hours = options.utc ? date.getUTCHours() : date.getHours();\n const minutes = options.utc ? date.getUTCMinutes() : date.getMinutes();\n\n const period = hours >= 12 ? \"p.m.\" : \"a.m.\";\n const displayHours = hours % 12 || 12;\n const displayMinutes = minutes.toString().padStart(2, \"0\");\n\n if (format === \"Month DD, YYYY, at HH:MM period\") {\n const time =\n minutes === 0 ? `${displayHours} ${period}` : `${displayHours}:${displayMinutes} ${period}`;\n return `${month} ${day}, ${year}, at ${time}`;\n } else if (format === \"Month DD\") {\n return `${month} ${day}`;\n }\n\n return \"\";\n}\n","import formatDate from \"./formatDate.ts\";\nimport prettyDuration from \"./prettyDuration.ts\";\n\nexport function cacheEntryExpired(creation: number, ttl: number | undefined, now: number): boolean {\n return ttl !== undefined && now - creation >= ttl * 1000;\n}\n\nexport function cacheTtlMessage(\n creation: number,\n ttl: number,\n now: number,\n expired: boolean,\n): string {\n const creationDate = formatDate(new Date(creation), \"Month DD, YYYY, at HH:MM period\");\n const ttlDuration = prettyDuration(0, { end: ttl * 1000 });\n if (expired) {\n return `TTL of ${ttlDuration} has expired.\\nThe creation date is ${creationDate}.\\nIt was created ${prettyDuration(\n creation,\n { end: now },\n )} ago.`;\n }\n\n const ttlLimit = creation + ttl * 1000;\n return `TTL of ${ttlDuration} has not expired.\\nThe creation date is ${creationDate}.\\nThere are ${prettyDuration(\n now,\n { end: ttlLimit },\n )} left.`;\n}\n\nexport function cacheLoadMessage(\n start: number,\n end: number,\n cachedDuration: number | undefined,\n): string {\n const loaded = `Data loaded in ${prettyDuration(start, { end })}.`;\n if (cachedDuration === undefined) {\n return loaded;\n }\n return `${loaded}\\nRunning computations previously took ${prettyDuration(0, {\n end: cachedDuration,\n })}.\\nYou saved ${prettyDuration(end - start, { end: cachedDuration })}.`;\n}\n","import SimpleTable from \"../class/SimpleTable.ts\";\nimport { getTableGeneration } from \"./tableGeneration.ts\";\nimport normalizeCacheCode from \"./normalizeCacheCode.ts\";\n\n/**\n * Converts cache inputs to a deterministic, type-tagged representation.\n * SimpleTable values are represented by their name and current generation.\n */\nexport default function serializeCacheInputs(inputs: readonly unknown[]): string {\n if (!Array.isArray(inputs)) {\n throw new TypeError(\"cache() options.inputs must be an array.\");\n }\n return serializeValue(inputs, \"inputs\", new Set<object>());\n}\n\n/** Returns a user-facing cache diagnostic label for supported input values. */\nexport function getCacheInputLabel(value: unknown): string | undefined {\n return value instanceof SimpleTable ? `table ${JSON.stringify(value.name)}` : undefined;\n}\n\nfunction serializeValue(value: unknown, path: string, ancestors: Set<object>): string {\n if (value === null) {\n return JSON.stringify([\"null\"]);\n }\n\n switch (typeof value) {\n case \"undefined\":\n return JSON.stringify([\"undefined\"]);\n case \"boolean\":\n return JSON.stringify([\"boolean\", value]);\n case \"string\":\n return JSON.stringify([\"string\", value]);\n case \"number\":\n return serializeNumber(value);\n case \"bigint\":\n return JSON.stringify([\"bigint\", value.toString()]);\n case \"function\":\n return JSON.stringify([\n \"function\",\n normalizeCacheCode(Function.prototype.toString.call(value)),\n ]);\n case \"symbol\":\n throw new TypeError(`cache() ${path} cannot be a symbol.`);\n }\n\n if (value instanceof SimpleTable) {\n return JSON.stringify([\"SimpleTable\", value.name, getTableGeneration(value)]);\n }\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) {\n throw new TypeError(`cache() ${path} is an invalid Date.`);\n }\n return JSON.stringify([\"Date\", value.toISOString()]);\n }\n\n if (ancestors.has(value)) {\n throw new TypeError(`cache() ${path} is cyclic.`);\n }\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n const serializedItems: string[] = [];\n for (let i = 0; i < value.length; i++) {\n serializedItems.push(serializeValue(value[i], `${path}[${i}]`, ancestors));\n }\n return JSON.stringify([\"array\", serializedItems]);\n }\n\n if (!isPlainObject(value)) {\n const name = value.constructor?.name || \"unknown\";\n throw new TypeError(\n `cache() ${path} is an unsupported ${name} instance. Pass its deterministic state instead.`,\n );\n }\n\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw new TypeError(`cache() ${path} cannot have symbol properties.`);\n }\n const serializedEntries: [string, string][] = [];\n for (const key of Object.keys(value).sort()) {\n serializedEntries.push([key, serializeValue(value[key], propertyPath(path, key), ancestors)]);\n }\n return JSON.stringify([\"object\", serializedEntries]);\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction serializeNumber(value: number): string {\n if (Number.isNaN(value)) {\n return JSON.stringify([\"number\", \"NaN\"]);\n }\n if (value === Infinity) {\n return JSON.stringify([\"number\", \"Infinity\"]);\n }\n if (value === -Infinity) {\n return JSON.stringify([\"number\", \"-Infinity\"]);\n }\n if (Object.is(value, -0)) {\n return JSON.stringify([\"number\", \"-0\"]);\n }\n return JSON.stringify([\"number\", value.toString()]);\n}\n\nfunction isPlainObject(value: unknown): value is Readonly<Record<string, unknown>> {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction propertyPath(path: string, key: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)\n ? `${path}.${key}`\n : `${path}[${JSON.stringify(key)}]`;\n}\n","/** The metadata required to identify and recreate a DuckDB HNSW index. */\nexport type VssIndexDefinition = {\n kind: \"vss\";\n name: string;\n column: string;\n options: {\n efConstruction?: number;\n efSearch?: number;\n M?: number;\n };\n};\n\n/** The metadata required to identify and recreate a DuckDB full-text index. */\nexport type FtsIndexDefinition = {\n kind: \"fts\";\n name: string;\n idColumn: string;\n textColumn: string;\n options: {\n stemmer?: string;\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n };\n};\n\n/** A complete index definition stored by a SimpleTable. */\nexport type IndexDefinition = VssIndexDefinition | FtsIndexDefinition;\n\nexport type IndexCacheStrategy = \"persist\" | \"rebuild\";\n\nconst INDEX_CACHE_STRATEGIES: Record<IndexDefinition[\"kind\"], IndexCacheStrategy> = {\n fts: \"persist\",\n vss: \"rebuild\",\n};\n\nexport function getIndexCacheStrategy(index: IndexDefinition): IndexCacheStrategy {\n return INDEX_CACHE_STRATEGIES[index.kind];\n}\n","import stringifyUnknown from \"./stringifyUnknown.ts\";\n/**\n * Converts a JavaScript value to a SQL literal. Strings are quoted with embedded\n * quotes escaped, dates become quoted ISO strings, and null, undefined, or NaN\n * become `\"NULL\"`. Numbers and booleans are returned unchanged.\n *\n * @example\n * ```ts\n * import { parseValue } from \"@nshiab/simple-data-analysis-core/helpers\";\n * console.log(parseValue(\"O'Brien\")); // \"'O''Brien'\"\n * console.log(parseValue(null)); // \"NULL\"\n * ```\n *\n * @param value - A string, number, boolean, Date, null, or undefined.\n *\n * @returns A SQL literal, or the original number or boolean.\n *\n * @throws If the value has an unsupported type.\n */\nexport default function parseValue(value: unknown): string | boolean | number {\n if (Number.isNaN(value) || value === undefined || value === null) {\n return \"NULL\";\n } else if (value instanceof Date) {\n return `'${value.toISOString()}'`;\n } else if (typeof value === \"string\") {\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n } else if (typeof value === \"boolean\") {\n return value;\n } else if (typeof value === \"number\") {\n return value;\n } else {\n throw new Error(`Unknown type ${typeof value} of ${stringifyUnknown(value, \"template\")}.`);\n }\n}\n","import type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport parseValue from \"./parseValue.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport default function buildCreateIndexQuery(table: string, index: IndexDefinition): string {\n switch (index.kind) {\n case \"fts\":\n return buildFtsIndexQuery(table, index);\n case \"vss\":\n return buildVssIndexQuery(table, index);\n default:\n return assertNever(index);\n }\n}\n\nfunction assertNever(value: never): never {\n throw new Error(`Unsupported index definition: ${JSON.stringify(value)}`);\n}\n\nfunction buildVssIndexQuery(\n table: string,\n index: Extract<IndexDefinition, { kind: \"vss\" }>,\n): string {\n const withOptions = [\"metric = 'cosine'\"];\n if (index.options.efConstruction !== undefined) {\n withOptions.push(`ef_construction = ${index.options.efConstruction}`);\n }\n if (index.options.efSearch !== undefined) {\n withOptions.push(`ef_search = ${index.options.efSearch}`);\n }\n if (index.options.M !== undefined) {\n withOptions.push(`M = ${index.options.M}`);\n }\n return `CREATE INDEX ${quoteIdentifier(index.name)} ON ${quoteIdentifier(table)}\n USING HNSW (${quoteIdentifier(index.column)})\n WITH (${withOptions.join(\", \")});`;\n}\n\nfunction buildFtsIndexQuery(\n table: string,\n index: Extract<IndexDefinition, { kind: \"fts\" }>,\n): string {\n const options = index.options;\n return `PRAGMA create_fts_index(${quoteIdentifier(table)}, ${quoteIdentifier(\n index.idColumn,\n )}, ${quoteIdentifier(index.textColumn)}${\n options.stemmer ? `, stemmer = ${parseValue(options.stemmer)}` : \"\"\n }${\n options.stopwords ? `, stopwords = ${parseValue(options.stopwords)}` : \"\"\n }${options.ignore ? `, ignore = ${parseValue(options.ignore)}` : \"\"}${\n options.stripAccents !== undefined ? `, strip_accents = ${options.stripAccents ? 1 : 0}` : \"\"\n }${options.lower !== undefined ? `, lower = ${options.lower ? 1 : 0}` : \"\"});`;\n}\n","import { existsSync, renameSync, rmSync } from \"node:fs\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport { getIndexCacheStrategy } from \"./indexDefinitions.ts\";\nimport buildCreateIndexQuery from \"./indexQueries.ts\";\nimport cleanPath from \"./cleanPath.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nconst CACHE_DATABASE = \"__sda_cache_entry\";\n\ntype DatabaseRow = { database_name: string };\n\nexport async function writeCacheDatabase(\n table: SimpleTable,\n file: string,\n indexes: IndexDefinition[],\n): Promise<void> {\n const temporaryFile = `${file}.${crypto.randomUUID()}.tmp.db`;\n const cacheDatabase = quoteIdentifier(CACHE_DATABASE);\n const currentDatabase = quoteIdentifier(await getCurrentDatabase(table));\n const persistedIndexes = indexes.filter((index) => getIndexCacheStrategy(index) === \"persist\");\n await loadIndexExtensions(table, persistedIndexes);\n try {\n await table.sdb.customQuery(\n `ATTACH '${cleanPath(temporaryFile)}' AS ${cacheDatabase}\n (STORAGE_VERSION 'latest');\n CREATE TABLE ${cacheDatabase}.${quoteIdentifier(table.name)} AS\n SELECT * FROM ${quoteIdentifier(table.name)};`,\n );\n if (persistedIndexes.length > 0) {\n await table.sdb.customQuery(`USE ${cacheDatabase};`);\n await table.sdb.customQuery(buildIndexQueries(table.name, persistedIndexes));\n await table.sdb.customQuery(`USE ${currentDatabase};`);\n }\n await table.sdb.customQuery(\n `CHECKPOINT ${cacheDatabase};\n DETACH ${cacheDatabase};`,\n );\n try {\n renameSync(temporaryFile, file);\n } catch (error) {\n if (!isReplaceRenameError(error) || !existsSync(file)) {\n throw error;\n }\n rmSync(file);\n renameSync(temporaryFile, file);\n }\n } catch (error) {\n await restoreDatabaseAfterFailure(table, currentDatabase, cacheDatabase);\n if (existsSync(temporaryFile)) {\n rmSync(temporaryFile);\n }\n throw error;\n }\n}\n\nfunction isReplaceRenameError(error: unknown): boolean {\n if (!(error instanceof Error) || !(\"code\" in error)) {\n return false;\n }\n return error.code === \"EEXIST\" || error.code === \"EPERM\";\n}\n\nexport async function loadCacheDatabase(\n table: SimpleTable,\n file: string,\n indexes: IndexDefinition[],\n geo: boolean,\n): Promise<void> {\n const cacheDatabase = quoteIdentifier(CACHE_DATABASE);\n const currentDatabase = quoteIdentifier(await getCurrentDatabase(table));\n if (geo) {\n await table.sdb.customQuery(\"INSTALL spatial; LOAD spatial;\");\n }\n await loadIndexExtensions(table, indexes);\n table.indexes = [];\n\n const dropFts = `DROP SCHEMA IF EXISTS ${quoteIdentifier(`fts_main_${table.name}`)} CASCADE;`;\n try {\n await table.sdb.customQuery(\n `${dropFts}\n DROP TABLE IF EXISTS ${quoteIdentifier(table.name)};\n ATTACH '${cleanPath(file)}' AS ${cacheDatabase} (READ_ONLY);\n COPY FROM DATABASE ${cacheDatabase} TO ${currentDatabase};\n DETACH ${cacheDatabase};`,\n );\n const indexesToRebuild = indexes.filter((index) => getIndexCacheStrategy(index) === \"rebuild\");\n const indexQueries = buildIndexQueries(table.name, indexesToRebuild);\n if (indexQueries.length > 0) {\n await table.sdb.customQuery(indexQueries);\n }\n } catch (error) {\n await restoreDatabaseAfterFailure(table, currentDatabase, cacheDatabase);\n throw error;\n }\n\n table.indexes = structuredClone(indexes);\n}\n\nasync function getCurrentDatabase(table: SimpleTable): Promise<string> {\n const rows = (await table.sdb.customQuery(\"SELECT current_database() AS database_name;\", {\n returnData: true,\n })) as DatabaseRow[];\n return rows[0].database_name;\n}\n\nasync function loadIndexExtensions(table: SimpleTable, indexes: IndexDefinition[]): Promise<void> {\n const queries: string[] = [];\n if (indexes.some((index) => index.kind === \"vss\")) {\n queries.push(\"INSTALL vss; LOAD vss;\");\n }\n if (indexes.some((index) => index.kind === \"fts\")) {\n queries.push(\"INSTALL fts; LOAD fts;\");\n }\n if (queries.length > 0) {\n await table.sdb.customQuery(queries.join(\"\\n\"));\n }\n}\n\nfunction buildIndexQueries(table: string, indexes: IndexDefinition[]): string {\n return indexes\n .map(\n (index) =>\n `${\n index.kind === \"vss\" ? \"SET hnsw_enable_experimental_persistence = true;\\n\" : \"\"\n }${buildCreateIndexQuery(table, index)}`,\n )\n .join(\"\\n\");\n}\n\nasync function restoreDatabaseAfterFailure(\n table: SimpleTable,\n currentDatabase: string,\n cacheDatabase: string,\n): Promise<void> {\n try {\n await table.sdb.customQuery(`USE ${currentDatabase};`);\n } catch {\n // Preserve the original cache error.\n }\n try {\n await table.sdb.customQuery(`DETACH ${cacheDatabase};`);\n } catch {\n // The cache database may not have been attached yet.\n }\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\n\n/** Executes generated database-file SQL without rewriting paths or metadata. */\nexport default function queryDbFile(\n sdb: SimpleDB,\n sql: string,\n options: { returnData?: boolean } = {},\n) {\n return queryDB(\n sdb,\n sql,\n mergeOptions(sdb, {\n table: null,\n method: \"database file operation\",\n parameters: null,\n returnData: options.returnData,\n noClean: true,\n }),\n );\n}\n","import queryDbFile from \"./queryDbFile.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport parseValue from \"./parseValue.ts\";\n\n/** Reads embedded SDA metadata when present. */\nexport default async function readDbMetadata(\n sdb: SimpleDB,\n database: string,\n): Promise<Record<string, IndexDefinition[]>> {\n const schemas = await queryDbFile(\n sdb,\n `SELECT schema_name FROM duckdb_schemas()\n WHERE database_name = ${parseValue(database)} AND schema_name = '__sda';`,\n { returnData: true },\n );\n if (schemas!.length > 0) {\n const rows = await queryDbFile(\n sdb,\n `SELECT version, indexes FROM ${quoteIdentifier(database)}.__sda.metadata;`,\n { returnData: true },\n );\n if (rows!.length !== 1 || rows![0].version !== 1 || typeof rows![0].indexes !== \"string\") {\n throw new Error(\"Unsupported SDA database metadata in the reserved __sda schema.\");\n }\n return validateIndexes(JSON.parse(rows![0].indexes));\n }\n return {};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function validateIndexes(value: unknown): Record<string, IndexDefinition[]> {\n if (!isRecord(value)) throw new Error(\"Invalid SDA index metadata.\");\n for (const definitions of Object.values(value)) {\n if (!Array.isArray(definitions)) {\n throw new Error(\"Invalid SDA index metadata.\");\n }\n for (const definition of definitions) {\n if (\n !isRecord(definition) ||\n typeof definition.name !== \"string\" ||\n !isRecord(definition.options)\n ) {\n throw new Error(\"Invalid SDA index definition.\");\n }\n const options = definition.options;\n if (definition.kind === \"fts\") {\n if (\n typeof definition.idColumn !== \"string\" ||\n typeof definition.textColumn !== \"string\" ||\n [\"stemmer\", \"stopwords\", \"ignore\"].some(\n (key) => options[key] !== undefined && typeof options[key] !== \"string\",\n ) ||\n [\"stripAccents\", \"lower\"].some(\n (key) => options[key] !== undefined && typeof options[key] !== \"boolean\",\n )\n ) {\n throw new Error(\"Invalid SDA FTS index definition.\");\n }\n } else if (definition.kind === \"vss\") {\n if (\n typeof definition.column !== \"string\" ||\n [\"efConstruction\", \"efSearch\", \"M\"].some(\n (key) =>\n options[key] !== undefined &&\n (typeof options[key] !== \"number\" || !Number.isFinite(options[key])),\n )\n ) {\n throw new Error(\"Invalid SDA VSS index definition.\");\n }\n } else {\n throw new Error(\"Unsupported SDA index definition.\");\n }\n }\n }\n return value as Record<string, IndexDefinition[]>;\n}\n","import { readFileSync } from \"node:fs\";\nimport type { TableGenerationId } from \"./tableGeneration.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport type { CacheTableDependency } from \"./cacheTableDependencies.ts\";\nimport { validateIndexes } from \"./readDbMetadata.ts\";\n\nexport type CacheSource = {\n file: string | null;\n creation: number;\n duration: number;\n geo: boolean;\n entryGeneration?: TableGenerationId | null;\n generationId?: TableGenerationId;\n indexes?: IndexDefinition[];\n formatVersion?: string;\n codeHash?: string;\n inputHashes?: string[];\n tableDependencies?: CacheTableDependency[];\n};\n\nexport type CacheSources = {\n [key: string]: CacheSource;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nfunction isCacheSource(value: unknown): value is CacheSource {\n if (!isRecord(value)) return false;\n if (value.indexes !== undefined) validateIndexes({ source: value.indexes });\n return (\n (value.file === null || typeof value.file === \"string\") &&\n typeof value.creation === \"number\" &&\n typeof value.duration === \"number\" &&\n typeof value.geo === \"boolean\" &&\n (value.entryGeneration === undefined ||\n value.entryGeneration === null ||\n typeof value.entryGeneration === \"string\") &&\n (value.generationId === undefined || typeof value.generationId === \"string\") &&\n (value.formatVersion === undefined || typeof value.formatVersion === \"string\") &&\n (value.codeHash === undefined || typeof value.codeHash === \"string\") &&\n (value.inputHashes === undefined ||\n (isArray(value.inputHashes) &&\n value.inputHashes.every((hash) => typeof hash === \"string\"))) &&\n (value.tableDependencies === undefined ||\n (isArray(value.tableDependencies) &&\n value.tableDependencies.every(\n (dependency) =>\n isRecord(dependency) &&\n typeof dependency.tableName === \"string\" &&\n typeof dependency.generationId === \"string\",\n )))\n );\n}\n\n/** Reads persisted table-cache metadata, validating JSON before it is used. */\nexport default function readCacheSources(path: string): CacheSources {\n const value: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n if (!isRecord(value)) throw new Error(\"Invalid SDA table cache metadata.\");\n const sources: [string, CacheSource][] = [];\n for (const [id, source] of Object.entries(value)) {\n if (!isCacheSource(source))\n throw new Error(`Invalid SDA table cache entry ${JSON.stringify(id)}.`);\n sources.push([id, source]);\n }\n return Object.fromEntries(sources);\n}\n","import { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport crypto from \"node:crypto\";\nimport flushAllTables from \"../helpers/flushAllTables.ts\";\nimport prettyDuration from \"../helpers/prettyDuration.ts\";\nimport normalizeCacheCode from \"../helpers/normalizeCacheCode.ts\";\nimport {\n cacheEntryExpired,\n cacheLoadMessage,\n cacheTtlMessage,\n} from \"../helpers/cacheDiagnostics.ts\";\nimport serializeCacheInputs, { getCacheInputLabel } from \"../helpers/serializeCacheInputs.ts\";\nimport {\n createTableGenerationId,\n peekTableGeneration,\n restoreTableGeneration,\n type TableGenerationId,\n} from \"../helpers/tableGeneration.ts\";\nimport { loadCacheDatabase, writeCacheDatabase } from \"../helpers/cacheDatabase.ts\";\nimport readCacheSources, {\n type CacheSource,\n type CacheSources,\n} from \"../helpers/readCacheSources.ts\";\nimport {\n assertCacheTableMutation,\n cacheTableDependenciesMatch,\n type CacheTableDependency,\n captureCacheTableDependencies,\n changedCacheTableDependenciesMessage,\n recordCacheTableAccess,\n unchangedCacheTableDependenciesMessage,\n} from \"../helpers/cacheTableDependencies.ts\";\n\nconst CACHE_FORMAT_VERSION = \"duckdb-v5\";\n\ntype CacheDiagnosticSource = CacheSource & {\n formatVersion: string;\n codeHash: string;\n inputHashes: string[];\n tableDependencies: CacheTableDependency[];\n};\n\nexport default async function cache<Table extends SimpleTable>(\n table: Table,\n compute: (table: Table) => void | Promise<void>,\n options: {\n ttl?: number;\n inputs?: readonly unknown[];\n verbose?: boolean;\n } = {},\n) {\n // If cache() is itself called from another cache computation, the outer\n // computation depends on the table produced here.\n assertCacheTableMutation(table);\n recordCacheTableAccess(table);\n if (options.verbose) {\n console.log(`\\ncache() for ${table.name}`);\n }\n\n // cache() is an observation point even when a cache hit has no artifact to\n // load, so all earlier database-wide work must complete before it returns.\n await flushAllTables(table.sdb);\n\n const cachePath = \"./.sda-cache\";\n if (!existsSync(cachePath)) {\n mkdirSync(cachePath);\n }\n const cacheSourcesPath = `${cachePath}/sources.json`;\n let cacheSources: CacheSources = {};\n if (existsSync(cacheSourcesPath)) {\n cacheSources = readCacheSources(cacheSourcesPath);\n }\n\n const functionBody = normalizeCacheCode(compute.toString());\n const entryGeneration = peekTableGeneration(table) ?? null;\n const inputs = options.inputs?.filter((input) => input !== table) ?? [];\n const hasInputs = inputs.length > 0;\n const serializedInputs = hasInputs ? serializeCacheInputs(inputs) : null;\n const codeHash = createHash(JSON.stringify([table.sdb.expressionSyntax, functionBody]));\n const inputHashes = hasInputs\n ? inputs.map((input) => createHash(serializeCacheInputs([input])))\n : [];\n const hash = createHash(\n JSON.stringify([\n CACHE_FORMAT_VERSION,\n table.sdb.expressionSyntax,\n table.name,\n entryGeneration,\n functionBody,\n serializedInputs,\n ]),\n );\n const requestedId = `${table.name}.${hash}`;\n let id = requestedId;\n let cache: CacheSource | undefined = cacheSources[id];\n if (cache === undefined) {\n const alreadyApplied = findAlreadyAppliedCache(\n table,\n cacheSources,\n entryGeneration,\n codeHash,\n inputHashes,\n );\n if (alreadyApplied !== undefined) {\n [id, cache] = alreadyApplied;\n }\n }\n if (cache !== undefined && !cacheTableDependenciesMatch(table, cache.tableDependencies)) {\n cache = undefined;\n }\n const now = Date.now();\n\n if (cache !== undefined) {\n ensureCacheDiagnostics(cache, cacheSources, cacheSourcesPath, codeHash, inputHashes);\n }\n\n if (cache === undefined) {\n if (options.verbose) {\n logCacheMiss(table, cacheSources, codeHash, inputHashes, inputs, entryGeneration);\n }\n await runAndWrite(\n table,\n compute,\n cacheSources,\n cacheSourcesPath,\n cachePath,\n id,\n codeHash,\n inputHashes,\n entryGeneration,\n );\n } else if (options.ttl !== undefined && cacheEntryExpired(cache.creation, options.ttl, now)) {\n const refreshId = cache.entryGeneration === entryGeneration ? id : requestedId;\n if (options.verbose) {\n console.log(\n `Cache entry is stale.\\n${identityMatchMessage(\n inputHashes,\n cache.tableDependencies ?? [],\n )}\\n${cacheTtlMessage(\n cache.creation,\n options.ttl,\n now,\n true,\n )}\\nRunning computations and refreshing the cache entry.`,\n );\n }\n await runAndWrite(\n table,\n compute,\n cacheSources,\n cacheSourcesPath,\n cachePath,\n refreshId,\n codeHash,\n inputHashes,\n entryGeneration,\n );\n } else {\n if (options.verbose) {\n console.log(\n `Cache hit.\\n${identityMatchMessage(inputHashes, cache.tableDependencies ?? [])}`,\n );\n }\n if (typeof options.ttl === \"number\") {\n if (options.verbose) {\n console.log(cacheTtlMessage(cache.creation, options.ttl, now, false));\n }\n }\n if (cache.file === null) {\n console.log(\"No data in cache. Nothing to load.\");\n } else {\n const start = Date.now();\n try {\n await loadCacheDatabase(table, cache.file, cache.indexes ?? [], cache.geo);\n } catch {\n if (options.verbose) {\n console.log(\"Could not load cached data. Recomputing...\");\n }\n if (existsSync(cache.file)) {\n rmSync(cache.file);\n }\n delete cacheSources[id];\n await runAndWrite(\n table,\n compute,\n cacheSources,\n cacheSourcesPath,\n cachePath,\n requestedId,\n codeHash,\n inputHashes,\n entryGeneration,\n );\n return;\n }\n if (table.sdb.cacheSourcesUsed.indexOf(id) < 0) {\n table.sdb.cacheSourcesUsed.push(id);\n }\n const end = Date.now();\n const duration = end - start;\n if (options.verbose) {\n console.log(`${cacheLoadMessage(start, end, cache.duration)}\\n`);\n table.sdb.cacheTimeSaved += cache.duration - duration;\n }\n }\n restoreCachedGeneration(table, cache, cacheSources, cacheSourcesPath);\n }\n}\n\nasync function runAndWrite<Table extends SimpleTable>(\n table: Table,\n compute: (table: Table) => void | Promise<void>,\n cacheSources: CacheSources,\n cacheSourcesPath: string,\n cachePath: string,\n id: string,\n codeHash: string,\n inputHashes: string[],\n entryGeneration: TableGenerationId | null,\n) {\n // Complete any work queued before cache() before dependency observation\n // begins. Operations queued by compute are flushed inside the observation.\n await flushAllTables(table.sdb);\n const start = Date.now();\n const tableDependencies = await captureCacheTableDependencies(table, async () => {\n await compute(table);\n });\n const end = Date.now();\n const duration = end - start;\n const generationId = createTableGenerationId();\n if (table.sdb.cacheVerbose) {\n console.log(`Computations done in ${prettyDuration(start, { end })}.`);\n }\n if (!(await table.sdb.hasTable(table.name))) {\n console.log(`No data in table ${table.name}. Nothing stored in cache.`);\n cacheSources[id] = {\n creation: Date.now(),\n duration,\n file: null,\n geo: false,\n entryGeneration,\n generationId,\n indexes: [],\n formatVersion: CACHE_FORMAT_VERSION,\n codeHash,\n inputHashes,\n tableDependencies,\n };\n } else {\n const types = await table.getTypes();\n const geometriesColumns = Object.values(types).filter((d) =>\n d.toLowerCase().includes(\"geometry\"),\n ).length;\n const file = `${cachePath}/${id}.db`;\n const indexes = structuredClone(table.indexes);\n const writeStart = Date.now();\n await writeCacheDatabase(table, file, indexes);\n const writeEnd = Date.now();\n if (table.sdb.cacheVerbose) {\n console.log(`Wrote in cache in ${prettyDuration(writeStart, { end: writeEnd })}.\\n`);\n }\n table.sdb.cacheTimeWriting += writeEnd - writeStart;\n cacheSources[id] = {\n creation: Date.now(),\n duration,\n file,\n geo: geometriesColumns > 0,\n entryGeneration,\n generationId,\n indexes,\n formatVersion: CACHE_FORMAT_VERSION,\n codeHash,\n inputHashes,\n tableDependencies,\n };\n if (table.sdb.cacheSourcesUsed.indexOf(id) < 0) {\n table.sdb.cacheSourcesUsed.push(id);\n }\n }\n\n writeFileSync(cacheSourcesPath, JSON.stringify(cacheSources));\n restoreTableGeneration(table, generationId);\n}\n\nfunction restoreCachedGeneration(\n table: SimpleTable,\n cache: CacheSource,\n cacheSources: CacheSources,\n cacheSourcesPath: string,\n): void {\n if (cache.generationId === undefined) {\n cache.generationId = createTableGenerationId();\n writeFileSync(cacheSourcesPath, JSON.stringify(cacheSources));\n }\n restoreTableGeneration(table, cache.generationId);\n}\n\nfunction ensureCacheDiagnostics(\n cache: CacheSource,\n cacheSources: CacheSources,\n cacheSourcesPath: string,\n codeHash: string,\n inputHashes: string[],\n): void {\n if (\n cache.formatVersion === undefined ||\n cache.codeHash === undefined ||\n cache.inputHashes === undefined\n ) {\n cache.formatVersion = CACHE_FORMAT_VERSION;\n cache.codeHash = codeHash;\n cache.inputHashes = inputHashes;\n writeFileSync(cacheSourcesPath, JSON.stringify(cacheSources));\n }\n}\n\nfunction createHash(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction identityMatchMessage(\n inputHashes: string[],\n tableDependencies: CacheTableDependency[],\n): string {\n const inputsMessage =\n inputHashes.length === 0\n ? \"Compute function unchanged.\"\n : `Compute function unchanged.\\nInputs unchanged (${inputHashes.length} checked).`;\n const dependenciesMessage =\n tableDependencies.length === 0\n ? \"\"\n : `\\n${unchangedCacheTableDependenciesMessage(tableDependencies)}`;\n return `${inputsMessage}${dependenciesMessage}`;\n}\n\nfunction findAlreadyAppliedCache(\n table: SimpleTable,\n cacheSources: CacheSources,\n entryGeneration: TableGenerationId | null,\n codeHash: string,\n inputHashes: string[],\n): [string, CacheSource] | undefined {\n if (entryGeneration === null) {\n return undefined;\n }\n return Object.entries(cacheSources)\n .filter(\n ([id, source]) =>\n id.startsWith(`${table.name}.`) &&\n source.formatVersion === CACHE_FORMAT_VERSION &&\n source.generationId === entryGeneration &&\n source.codeHash === codeHash &&\n arraysEqual(source.inputHashes, inputHashes) &&\n cacheTableDependenciesMatch(table, source.tableDependencies),\n )\n .reduce<[string, CacheSource] | undefined>(\n (latest, candidate) =>\n latest === undefined || candidate[1].creation > latest[1].creation ? candidate : latest,\n undefined,\n );\n}\n\nfunction arraysEqual(left: readonly string[] | undefined, right: readonly string[]): boolean {\n return (\n left !== undefined &&\n left.length === right.length &&\n left.every((value, index) => value === right[index])\n );\n}\n\nfunction logCacheMiss(\n table: SimpleTable,\n cacheSources: CacheSources,\n codeHash: string,\n inputHashes: string[],\n inputs: readonly unknown[],\n entryGeneration: TableGenerationId | null,\n): void {\n const candidates = Object.entries(cacheSources)\n .filter(([id]) => id.startsWith(`${table.name}.`))\n .map(([, source]) => source)\n .filter(isCacheDiagnosticSource);\n\n let reason: string;\n if (candidates.length === 0) {\n const hasLegacyCandidate = Object.keys(cacheSources).some((id) =>\n id.startsWith(`${table.name}.`),\n );\n reason = hasLegacyCandidate\n ? \"A previous entry exists, but it predates detailed cache diagnostics. Its code, inputs, or cache format changed.\"\n : \"No matching cache entry exists for this computation.\";\n } else {\n const sameFormat = candidates.filter((source) => source.formatVersion === CACHE_FORMAT_VERSION);\n const sameCode = latestCacheSource(sameFormat.filter((source) => source.codeHash === codeHash));\n\n if (sameCode !== undefined) {\n const inputsMessage = changedInputsMessage(sameCode.inputHashes, inputHashes, inputs);\n const tableMessage =\n sameCode.entryGeneration === entryGeneration ? \"\" : \"The current table has changed.\";\n const dependenciesMessage = changedCacheTableDependenciesMessage(\n table,\n sameCode.tableDependencies,\n );\n const changes = [tableMessage, inputsMessage, dependenciesMessage].filter(\n (message) => message.length > 0,\n );\n reason =\n changes.length === 0\n ? \"Compute function unchanged.\"\n : `Compute function unchanged.\\n${changes.join(\"\\n\")}`;\n } else if (sameFormat.length === 0) {\n reason = \"The cache format changed.\";\n } else {\n reason = \"No matching cache entry exists for this computation.\";\n }\n }\n\n console.log(`Cache miss.\\n${reason}\\nRunning computations and storing a new cache entry.`);\n}\n\nfunction latestCacheSource(\n cacheSources: CacheDiagnosticSource[],\n): CacheDiagnosticSource | undefined {\n return cacheSources.reduce<CacheDiagnosticSource | undefined>(\n (latest, source) =>\n latest === undefined || source.creation > latest.creation ? source : latest,\n undefined,\n );\n}\n\nfunction isCacheDiagnosticSource(source: CacheSource): source is CacheDiagnosticSource {\n return (\n source.formatVersion !== undefined &&\n source.codeHash !== undefined &&\n source.inputHashes !== undefined &&\n source.tableDependencies !== undefined\n );\n}\n\nfunction changedInputsMessage(\n previousHashes: string[],\n inputHashes: string[],\n inputs: readonly unknown[],\n): string {\n const changes: string[] = [];\n const sharedLength = Math.min(previousHashes.length, inputHashes.length);\n for (let i = 0; i < sharedLength; i++) {\n if (previousHashes[i] !== inputHashes[i]) {\n changes.push(`${getCacheInputLabel(inputs[i]) ?? `inputs[${i}]`} changed`);\n }\n }\n for (let i = sharedLength; i < inputHashes.length; i++) {\n changes.push(`${getCacheInputLabel(inputs[i]) ?? `inputs[${i}]`} was added`);\n }\n for (let i = sharedLength; i < previousHashes.length; i++) {\n changes.push(`inputs[${i}] was removed`);\n }\n\n return changes.length === 0\n ? inputHashes.length === 0\n ? \"\"\n : `Inputs unchanged (${inputHashes.length} checked).`\n : `Inputs changed: ${changes.join(\", \")}.`;\n}\n","import capitalize from \"./capitalize.ts\";\n\n/**\n * Converts a string into camelCase. This is useful for creating variable\n * names or object keys from human-readable text.\n *\n * @example\n * ```ts\n * // Basic conversion\n * const result1 = camelCase(\"hello world\");\n * console.log(result1); // \"helloWorld\"\n * ```\n *\n * @example\n * ```ts\n * // With punctuation and mixed case\n * const result2 = camelCase(\" --Some@Thing is- happening-- \");\n * console.log(result2); // \"someThingIsHappening\"\n * ```\n *\n * @example\n * ```ts\n * // With a single word\n * const result3 = camelCase(\"Journalism\");\n * console.log(result3); // \"journalism\"\n * ```\n *\n * @param input - The string to convert to camelCase. It can contain spaces,\n * punctuation, and mixed casing.\n *\n * @returns The camelCased version of the input string.\n */\nexport default function camelCase(input: string): string {\n const words = input\n .replace(/[^a-zA-Z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((d) => d !== \"\");\n\n const camelCaseString = words\n .map((word, index) => {\n word = word.toLowerCase();\n if (index > 0) {\n word = capitalize(word);\n }\n return word;\n })\n .join(\"\");\n\n return camelCaseString;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function fill(\n simpleTable: SimpleTable,\n columns: string | string[],\n options: {\n by?: string | string[];\n interpolate?: boolean;\n interpolateBy?: string;\n } = {},\n) {\n // This validation doesn't need the database, so it stays at call time.\n if (options.interpolateBy && options.interpolate === false) {\n throw new Error(`interpolate cannot be false when interpolateBy is set.`);\n }\n\n // The fill order is based on rowid, which only exists on the materialized\n // table: it executes as a barrier.\n columns = Array.isArray(columns) ? [...columns] : columns;\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"fill()\",\n parameters: { columns, options },\n execute: () => executeFill(simpleTable, columns, options),\n });\n}\n\nasync function executeFill(\n simpleTable: SimpleTable,\n columns: string | string[],\n options: {\n by?: string | string[];\n interpolate?: boolean;\n interpolateBy?: string;\n },\n): Promise<void> {\n const by = options.by ? stringToArray(options.by) : [];\n\n const cols = stringToArray(columns);\n const excludeList = cols.map((col) => `${quoteIdentifier(col)}`).join(\", \");\n let selectList: string;\n\n if (options.interpolate || options.interpolateBy) {\n // Use interpolateBy for the window function's ORDER BY (correct\n // interpolation math), but always order the final output by rowid to\n // preserve input row order.\n const windowOrder = options.interpolateBy\n ? `${quoteIdentifier(options.interpolateBy)}`\n : \"rowid\";\n const overClause =\n by.length > 0 ? `(PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")})` : `()`;\n selectList = cols\n .map(\n (col) =>\n `fill(${quoteIdentifier(\n col,\n )} ORDER BY ${windowOrder}) OVER ${overClause} as ${quoteIdentifier(col)}`,\n )\n .join(\", \");\n } else if (by.length > 0) {\n const partition = `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}`;\n selectList = cols\n .map(\n (col) =>\n `COALESCE(${quoteIdentifier(col)}, LAG(${quoteIdentifier(\n col,\n )} IGNORE NULLS) OVER(${partition} ORDER BY rowid)) as ${quoteIdentifier(col)}`,\n )\n .join(\", \");\n } else {\n selectList = cols\n .map(\n (col) =>\n `COALESCE(${quoteIdentifier(col)}, LAG(${quoteIdentifier(\n col,\n )} IGNORE NULLS) OVER(ORDER BY rowid)) as ${quoteIdentifier(col)}`,\n )\n .join(\", \");\n }\n\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT * EXCLUDE(${excludeList}), ${selectList} FROM ${quoteIdentifier(\n simpleTable.name,\n )} ORDER BY rowid;`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"fill()\",\n parameters: { columns, ...options },\n }),\n );\n}\n","/** Validates and snapshots a two-dimensional WGS84 GeoJSON geometry cell. */\nexport default function prepareGeometry(\n value: unknown,\n column: string,\n row: number,\n): string | null {\n if (value === null) return null;\n const fail = (message: string): never => {\n throw new Error(`Column ${JSON.stringify(column)}, row ${row}: ${message}`);\n };\n const active = new Set<object>();\n let hasSignedZero = false;\n function position(value: unknown): number[] {\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n !Array.from(value).every((n) => typeof n === \"number\" && Number.isFinite(n))\n ) {\n fail(\n \"Expected a finite two-dimensional [longitude, latitude] position; Z/M coordinates are unsupported.\",\n );\n }\n const point = value as number[];\n if (Math.abs(point[0]) > 180 || Math.abs(point[1]) > 90) {\n fail(\n \"Expected WGS84 longitude [-180, 180] and latitude [-90, 90]; reproject the input first.\",\n );\n }\n hasSignedZero ||= Object.is(point[0], -0) || Object.is(point[1], -0);\n return [...point];\n }\n function list(value: unknown, convert: (v: unknown) => unknown): unknown[] {\n if (!Array.isArray(value)) fail(\"Expected a coordinate array.\");\n return Array.from(value as unknown[], convert);\n }\n function line(value: unknown): unknown[] {\n const points = list(value, position);\n if (points.length < 2) {\n fail(\"A LineString must contain at least two positions.\");\n }\n return points;\n }\n function ring(value: unknown): unknown[] {\n const points = list(value, position) as number[][];\n if (\n points.length < 4 ||\n points[0][0] !== points.at(-1)![0] ||\n points[0][1] !== points.at(-1)![1]\n ) {\n fail(\"A polygon ring must contain at least four positions and be closed.\");\n }\n return points;\n }\n function geometry(value: unknown): object {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n fail(\"Expected a GeoJSON geometry object or null.\");\n }\n const object = value as Record<string, unknown>;\n if (active.has(object)) fail(\"Cyclic GeometryCollections are unsupported.\");\n if (active.size >= 100) {\n fail(\"GeometryCollections may nest at most 100 levels.\");\n }\n active.add(object);\n try {\n const type = object.type;\n if (type === \"Feature\" || type === \"FeatureCollection\") {\n fail(\n \"Expected a GeoJSON geometry object, not a Feature or FeatureCollection; extract each feature's geometry first.\",\n );\n }\n if (\"crs\" in object) {\n fail(\n \"Geometry crs members are unsupported; supply WGS84 coordinates and declare GEOMETRY('EPSG:4326').\",\n );\n }\n let coordinates: unknown;\n switch (type) {\n case \"Point\":\n coordinates = position(object.coordinates);\n break;\n case \"MultiPoint\":\n coordinates = list(object.coordinates, position);\n break;\n case \"LineString\":\n coordinates = line(object.coordinates);\n break;\n case \"MultiLineString\":\n coordinates = list(object.coordinates, line);\n break;\n case \"Polygon\":\n coordinates = list(object.coordinates, ring);\n break;\n case \"MultiPolygon\":\n coordinates = list(object.coordinates, (v) => list(v, ring));\n break;\n case \"GeometryCollection\":\n return { type, geometries: list(object.geometries, geometry) };\n default:\n fail(\"Expected a supported GeoJSON geometry type.\");\n }\n return { type, coordinates };\n } finally {\n active.delete(object);\n }\n }\n const prepared = geometry(value);\n if (!hasSignedZero) return JSON.stringify(prepared);\n // JSON.stringify normalizes -0. Only supported geometry type names survive\n // validation as strings, so the \"-0\" marker cannot collide with input text.\n // Emit a decimal literal so DuckDB also preserves its sign when parsing JSON.\n return JSON.stringify(prepared, (_key, cell: unknown) =>\n Object.is(cell, -0) ? \"-0\" : cell,\n ).replaceAll('\"-0\"', \"-0.0\");\n}\n","/** Validates and snapshots a JavaScript JSON value without dropping information. */\nexport default function prepareJSON(value: unknown, column: string, row: number): string | null {\n if (value === null || value === undefined) return null;\n const active = new Set<object>();\n const fail = (path: string, message: string): never => {\n throw new Error(`Column ${JSON.stringify(column)}, row ${row}, ${path}: ${message}`);\n };\n function serialize(value: unknown, path: string): string {\n if (value === null) return \"null\";\n if (typeof value === \"string\" || typeof value === \"boolean\") {\n return JSON.stringify(value);\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Object.is(value, -0) ? \"-0.0\" : JSON.stringify(value);\n }\n if (typeof value !== \"object\") {\n return fail(\n path,\n \"Expected a JSON value: finite numbers, strings, booleans, null, arrays, or plain objects.\",\n );\n }\n if (active.has(value)) {\n return fail(path, \"Cyclic JSON values are unsupported.\");\n }\n if (active.size >= 100) {\n return fail(path, \"JSON values may nest at most 100 levels.\");\n }\n const array = Array.isArray(value);\n if (\n !array &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n ) {\n return fail(\n path,\n \"Expected a plain JSON object; convert class instances to JSON values first.\",\n );\n }\n if (Object.getOwnPropertySymbols(value).length) {\n return fail(path, \"JSON cannot represent symbol keys.\");\n }\n active.add(value);\n try {\n if (array) {\n if (Object.keys(value).length !== value.length) {\n return fail(path, \"JSON arrays must be dense and have no extra properties.\");\n }\n return `[${Array.from(value, (item: unknown, i) => serialize(item, `${path}[${i}]`)).join(\n \",\",\n )}]`;\n }\n return `{${Object.entries(value)\n .map(\n ([key, item]: [string, unknown]) =>\n `${JSON.stringify(key)}:${serialize(item, `${path}[${JSON.stringify(key)}]`)}`,\n )\n .join(\",\")}}`;\n } finally {\n active.delete(value);\n }\n }\n return serialize(value, \"$\");\n}\n","/** Converts validated GeoJSON SQL text to an explicitly typed WGS84 geometry. */\nexport default function geometryFromJSON(expression: string): string {\n return `ST_GeomFromGeoJSON(${expression})::GEOMETRY('EPSG:4326')`;\n}\n","export default function parseType(\n type:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`,\n) {\n const typeLowerCase = type.toLowerCase();\n if (typeLowerCase === \"integer\") {\n return \"INTEGER\";\n } else if (typeLowerCase === \"float\" || typeLowerCase === \"number\") {\n return \"DOUBLE\";\n } else if (typeLowerCase === \"string\") {\n return \"VARCHAR\";\n } else if (typeLowerCase === \"datetime\") {\n return \"TIMESTAMP\";\n } else if (typeLowerCase === \"datetimetz\") {\n return \"TIMESTAMP WITH TIME ZONE\";\n } else if (\n [\n \"date\",\n \"time\",\n \"bigint\",\n \"hugeint\",\n \"double\",\n \"varchar\",\n \"timestamp\",\n \"timestamp with time zone\",\n \"boolean\",\n \"json\",\n ].includes(typeLowerCase)\n ) {\n return type.toUpperCase();\n } else if (/^float\\[[1-9]\\d*\\]$/.test(typeLowerCase)) {\n return type.toUpperCase();\n } else if (typeLowerCase.includes(\"geometry\")) {\n return type.toUpperCase();\n } else {\n throw new Error(`Unknown type ${type}`);\n }\n}\n","import {\n ARRAY,\n BIGINT,\n BOOLEAN,\n DATE,\n DOUBLE,\n FLOAT,\n INTEGER,\n TIME,\n TIMESTAMP,\n TIMESTAMPTZ,\n VARCHAR,\n} from \"@duckdb/node-api\";\n\nexport default function parseDuckDBType(type: string) {\n if (type === \"INTEGER\") {\n return INTEGER;\n } else if (type === \"BIGINT\") {\n return BIGINT;\n } else if (type === \"DOUBLE\") {\n return DOUBLE;\n } else if (type === \"VARCHAR\") {\n return VARCHAR;\n } else if (type === \"TIMESTAMP\") {\n return TIMESTAMP;\n } else if (type === \"TIMESTAMP WITH TIME ZONE\") {\n return TIMESTAMPTZ;\n } else if (type === \"DATE\") {\n return DATE;\n } else if (type === \"TIME\") {\n return TIME;\n } else if (type === \"BOOLEAN\") {\n return BOOLEAN;\n } else if (type.includes(\"FLOAT[\")) {\n // For embeddings\n const size = type.replace(\"FLOAT[\", \"\").replace(\"]\", \"\");\n return ARRAY(FLOAT, parseInt(size));\n } else {\n throw new Error(`Type ${type} not supported.`);\n }\n}\n","import stringifyUnknown from \"../helpers/stringifyUnknown.ts\";\nimport {\n arrayValue,\n type DuckDBConnection,\n DuckDBDateValue,\n DuckDBTimestampTZValue,\n DuckDBTimestampValue,\n DuckDBTimeValue,\n type DuckDBValue,\n} from \"@duckdb/node-api\";\nimport appendColumnBatches from \"../helpers/appendColumnBatches.ts\";\nimport prepareGeometry from \"../helpers/prepareGeometry.ts\";\nimport prepareJSON from \"../helpers/prepareJSON.ts\";\nimport geometryFromJSON from \"../helpers/geometryFromJSON.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport parseType from \"../helpers/parseTypes.ts\";\nimport parseDuckDBType from \"../helpers/parseDuckDBType.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default function loadArray(\n simpleTable: SimpleTable,\n rows: { [key: string]: unknown }[],\n options: NonNullable<Parameters<SimpleTable[\"loadArray\"]>[1]> = {},\n) {\n // This validation doesn't need the database, so it stays at call time.\n if (rows.length === 0) {\n throw new Error(\n \"The array is empty. loadArray needs at least one object to infer the column types.\",\n );\n }\n\n const prepared = prepareArray(rows, options.columnTypes, true);\n\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"loadArray()\",\n parameters: { rows: `${rows.length} rows` },\n execute: () => executePreparedArray(simpleTable, prepared),\n });\n}\n\ntype PreparedArray = {\n keys: string[];\n types: string[];\n columnsData: DuckDBValue[][];\n rowCount: number;\n};\n\nexport function prepareArray(\n rows: { [key: string]: unknown }[],\n columnTypes: { [key: string]: string } = {},\n requireExplicitNestedTypes = false,\n): PreparedArray {\n const keys = Object.keys(rows[0]);\n const overrides = new Map<string, string>();\n for (const [key, type] of Object.entries(columnTypes)) {\n if (!keys.includes(key)) {\n throw new Error(`Unknown column ${JSON.stringify(key)} in loadArray columnTypes.`);\n }\n if (type.toUpperCase() === \"JSON\") {\n overrides.set(key, \"JSON\");\n continue;\n }\n if (/^geometry/i.test(type)) {\n if (!/^geometry\\('EPSG:4326'\\)$/i.test(type)) {\n throw new Error(\n `Unsupported type ${JSON.stringify(type)} for column ${JSON.stringify(\n key,\n )}. GeoJSON ingestion requires GEOMETRY('EPSG:4326'); reproject input to WGS84 first.`,\n );\n }\n overrides.set(key, \"GEOMETRY('EPSG:4326')\");\n continue;\n }\n try {\n const normalized = parseType(type as Parameters<typeof parseType>[0]);\n parseDuckDBType(normalized);\n overrides.set(key, normalized);\n } catch {\n throw new Error(\n `Unsupported type ${JSON.stringify(type)} for column ${JSON.stringify(key)}.`,\n );\n }\n }\n const firstNonNullValue = keys.map(\n (key) => rows.find((obj) => obj[key] !== null && obj[key] !== undefined)?.[key],\n );\n const types: string[] = [];\n const columnsData: DuckDBValue[][] = keys.map(() => {\n const values: DuckDBValue[] = [];\n values.length = rows.length;\n return values;\n });\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const columnData = columnsData[i];\n const override = overrides.get(key);\n if (override !== undefined) {\n types[i] = override;\n for (let j = 0; j < rows.length; j++) {\n columnData[j] = prepareTypedValue(rows[j][key], override, key, j + 1);\n }\n continue;\n }\n if (requireExplicitNestedTypes) {\n for (let j = 0; j < rows.length; j++) {\n const cell = rows[j][key];\n if (cell !== null && typeof cell === \"object\" && !(cell instanceof Date)) {\n throw new Error(\n `Column ${JSON.stringify(key)}, row ${\n j + 1\n }: array and object cells require an explicit columnTypes entry. Use JSON for nested data, FLOAT[n] for fixed-size vectors, or GEOMETRY('EPSG:4326') for GeoJSON geometries.`,\n );\n }\n }\n }\n const value = firstNonNullValue[i];\n const type = typeof value;\n if (type === \"symbol\" || type === \"function\") {\n throw new Error(\n `Type ${type} not supported for ${key}. Value: ${stringifyUnknown(value, \"template\")}`,\n );\n } else if (type === \"undefined\") {\n types[i] = \"VARCHAR\";\n for (let j = 0; j < rows.length; j++) {\n columnData[j] = null;\n }\n } else if (type === \"object\") {\n if (value instanceof Date) {\n types[i] = \"TIMESTAMP\";\n for (let j = 0; j < rows.length; j++) {\n const d = rows[j][key];\n if (d === null || d === undefined || Number.isNaN(d)) {\n columnData[j] = null;\n } else {\n const date = d as Date;\n columnData[j] = new DuckDBTimestampValue(BigInt(date.getTime() * 1000));\n }\n }\n } else if (Array.isArray(value)) {\n types[i] = `FLOAT[${value.length}]`;\n for (let j = 0; j < rows.length; j++) {\n const d = rows[j][key];\n columnData[j] = d === null || d === undefined ? null : arrayValue([...(d as number[])]);\n }\n } else {\n throw new Error(\n `Type object not supported for ${key}. Value: ${stringifyUnknown(value, \"template\")}`,\n );\n }\n } else {\n types[i] = parseType(type);\n for (let j = 0; j < rows.length; j++) {\n const d = rows[j][key];\n columnData[j] =\n d === null || d === undefined || Number.isNaN(d) ? null : (d as DuckDBValue);\n }\n }\n }\n\n return { keys, types, columnsData, rowCount: rows.length };\n}\n\nexport async function executePreparedArray(simpleTable: SimpleTable, prepared: PreparedArray) {\n if (simpleTable.connection === undefined) {\n await simpleTable.sdb.start();\n simpleTable.connection = simpleTable.sdb.connection;\n }\n\n const { keys, types, columnsData, rowCount } = prepared;\n\n const hasGeometry = types.includes(\"GEOMETRY('EPSG:4326')\");\n const needsConversion = hasGeometry || types.includes(\"JSON\");\n const staged = needsConversion\n ? `__sda_array_${crypto.randomUUID().replaceAll(\"-\", \"\")}`\n : simpleTable.name;\n const storageTypes = types.map((type) =>\n type.startsWith(\"GEOMETRY\") || type === \"JSON\" ? \"VARCHAR\" : type,\n );\n if (hasGeometry && !simpleTable.sdb.spatialLoaded) {\n await simpleTable.sdb.customQuery(\n \"INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\",\n );\n simpleTable.sdb.spatialLoaded = true;\n }\n try {\n await simpleTable.sdb.customQuery(\n `CREATE ${needsConversion ? \"TEMP\" : \"OR REPLACE\"} TABLE ${quoteIdentifier(staged)}(${keys\n .map((key, i) => `${quoteIdentifier(key)} ${storageTypes[i]}`)\n .join(\", \")})`,\n );\n\n await appendColumnBatches(\n simpleTable.connection as DuckDBConnection,\n staged,\n storageTypes.map((type) => parseDuckDBType(type)),\n rowCount,\n (column, start, end) => columnsData[column].slice(start, end),\n );\n if (!needsConversion) return;\n // CTAS is atomic: conversion must finish before the destination is replaced.\n await simpleTable.sdb.customQuery(\n `CREATE OR REPLACE TABLE ${quoteIdentifier(simpleTable.name)} AS SELECT ${keys\n .map((key, i) =>\n types[i].startsWith(\"GEOMETRY\")\n ? `${geometryFromJSON(quoteIdentifier(key))} AS ${quoteIdentifier(key)}`\n : types[i] === \"JSON\"\n ? `${quoteIdentifier(key)}::JSON AS ${quoteIdentifier(key)}`\n : quoteIdentifier(key),\n )\n .join(\", \")} FROM ${quoteIdentifier(staged)}`,\n );\n } finally {\n if (needsConversion) {\n await simpleTable.sdb.customQuery(`DROP TABLE IF EXISTS ${quoteIdentifier(staged)}`);\n }\n }\n}\n\n/** Validates and snapshots a value for an explicitly declared destination type. */\nfunction prepareTypedValue(value: unknown, type: string, column: string, row: number): DuckDBValue {\n if (type === \"JSON\") return prepareJSON(value, column, row);\n if (type === \"GEOMETRY('EPSG:4326')\") {\n return prepareGeometry(value, column, row);\n }\n if (value === null || value === undefined || Number.isNaN(value)) return null;\n let compatible = false;\n if (type === \"VARCHAR\" && typeof value === \"string\") return value;\n if (type === \"BOOLEAN\" && typeof value === \"boolean\") return value;\n if (type === \"DOUBLE\") {\n if (typeof value === \"number\") return value;\n compatible = typeof value === \"bigint\";\n if (typeof value === \"bigint\") {\n const number = Number(value);\n if (Number.isFinite(number) && BigInt(number) === value) return number;\n }\n } else if (type === \"INTEGER\") {\n compatible = typeof value === \"number\" || typeof value === \"bigint\";\n if (typeof value === \"number\") {\n if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {\n return value;\n }\n } else if (typeof value === \"bigint\" && value >= -2147483648n && value <= 2147483647n) {\n return Number(value);\n }\n } else if (type === \"BIGINT\") {\n compatible = typeof value === \"number\" || typeof value === \"bigint\";\n if (typeof value === \"bigint\") {\n if (value >= -9223372036854775808n && value <= 9223372036854775807n) {\n return value;\n }\n } else if (\n typeof value === \"number\" &&\n Number.isInteger(value) &&\n value >= -(2 ** 63) &&\n value < 2 ** 63\n ) {\n // The upper bound is exclusive: 2 ** 63 - 1 rounds up as a JS number.\n return BigInt(value);\n }\n } else if ([\"DATE\", \"TIME\", \"TIMESTAMP\", \"TIMESTAMP WITH TIME ZONE\"].includes(type)) {\n if (type === \"TIME\" && value instanceof DuckDBTimeValue) {\n if (value.micros >= 0n && value.micros <= 86400000000n) {\n return new DuckDBTimeValue(value.micros);\n }\n compatible = true;\n } else if (value instanceof Date) {\n const millis = value.getTime();\n compatible = Number.isFinite(millis);\n if (compatible) {\n if (type === \"DATE\" && millis % 86400000 === 0) {\n return new DuckDBDateValue(millis / 86400000);\n }\n const micros = BigInt(millis) * 1000n;\n if (type === \"TIMESTAMP\") return new DuckDBTimestampValue(micros);\n if (type === \"TIMESTAMP WITH TIME ZONE\") {\n return new DuckDBTimestampTZValue(micros);\n }\n }\n }\n } else if (type.startsWith(\"FLOAT[\") && Array.isArray(value)) {\n compatible = true;\n const size = Number(type.slice(6, -1));\n if (\n value.length === size &&\n value.every(\n (item) =>\n item === null ||\n item === undefined ||\n (typeof item === \"number\" && (Number.isNaN(item) || Math.fround(item) === item)),\n )\n ) {\n return arrayValue(\n value.map((item: unknown) =>\n item === undefined || Number.isNaN(item) ? null : (item as number | null),\n ),\n );\n }\n }\n const displayed = typeof value === \"string\" ? JSON.stringify(value) : stringifyUnknown(value);\n throw new Error(\n `Column ${JSON.stringify(column)}, row ${row}: value ${displayed} ${\n compatible\n ? `cannot be stored as ${type} without losing information`\n : `is incompatible with ${type}`\n }. Select a type compatible with this value.`,\n );\n}\n","import type { DuckDBConnection, DuckDBInstance, DuckDBValue } from \"@duckdb/node-api\";\n\n/**\n * Shared implementation of the properties used by SimpleDB and SimpleTable.\n * This base class is not intended for direct instantiation.\n * @internal\n */\nexport default class Simple {\n /**\n * The number of rows to display when logging a table.\n *\n * @defaultValue `10`\n */\n rowsToLog: number;\n /**\n * A flag indicating whether to include data types when logging a table.\n *\n * @defaultValue `false`\n */\n typesToLog: boolean;\n /**\n * The maximum number of characters to display for text and stringified nested cells, including the truncation marker. This does not control column width. Set to Infinity to show the entire text.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({ charsToLog: 150 });\n * await sdb.newTable().loadArray([{ text: \"x\".repeat(200) }]).log();\n * ```\n *\n * @defaultValue `75`\n */\n charsToLog: number | undefined;\n /**\n * A DuckDB database instance.\n */\n db!: DuckDBInstance;\n /**\n * A connection to a DuckDB database.\n */\n connection!: DuckDBConnection;\n /**\n * A flag indicating if the table name was assigned by default.\n *\n * @defaultValue `false`\n */\n defaultTableName: boolean;\n /**\n * A function for running SQL queries. Subclasses can wrap this seam to observe\n * execution while forwarding every argument. To run custom SQL, use\n * `SimpleDB.customQuery()` instead.\n *\n * @example\n * ```ts\n * const original = table.runQuery;\n * table.runQuery = (query, connection, returnData, options) => {\n * console.log(query);\n * return original(query, connection, returnData, options);\n * };\n * ```\n *\n * @param query - The exact SQL statement to execute.\n * @param connection - The DuckDB connection that executes the statement.\n * @param returnData - Whether to convert and return result rows.\n * @param options - Error-attribution, binding, and observability options.\n * @param options.method - The SDA method responsible for the query, when available.\n * @param options.parameters - The method arguments recorded for error attribution.\n * @param options.table - The table associated with returned values and warnings.\n * @param options.values - Data values bound to placeholders in the SQL statement.\n * @param options.logSQL - Whether to log the SQL immediately before execution.\n * @param options.explainSQL - Whether to log a supported DuckDB query plan before execution.\n * @returns The converted rows when requested, otherwise `null`.\n */\n runQuery!: (\n query: string,\n connection: DuckDBConnection,\n returnData: boolean,\n options: {\n method: string | null;\n parameters: { [key: string]: unknown } | null;\n table?: string | null;\n values?: DuckDBValue[];\n logSQL: boolean;\n explainSQL: boolean;\n },\n ) => Promise<\n | {\n [key: string]: unknown;\n }[]\n | null\n >;\n\n constructor(\n options: {\n rowsToLog?: number;\n charsToLog?: number;\n typesToLog?: boolean;\n } = {},\n ) {\n this.rowsToLog = options.rowsToLog ?? 10;\n this.charsToLog = options.charsToLog ?? 75;\n this.typesToLog = options.typesToLog ?? false;\n this.defaultTableName = false;\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getIdenticalColumns from \"../helpers/getIdenticalColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\n\nexport default function join(\n leftTable: SimpleTable,\n rightTable: SimpleTable,\n options: {\n on?: string | string[];\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n assertSameDatabase(leftTable.sdb, [rightTable], \"join()\");\n options = structuredClone(options);\n // The output table instance is created at call time so it can be returned\n // synchronously and chained on right away.\n const outputTable =\n typeof options.outputTable === \"string\"\n ? leftTable.sdb.newTable(options.outputTable)\n : leftTable;\n\n queueOp(outputTable, {\n kind: \"source\",\n rawSQL: [quoteIdentifier(leftTable.name), quoteIdentifier(rightTable.name)],\n method: \"join()\",\n parameters: { rightTable: rightTable.name, options },\n buildSelect: () => buildJoinSelect(leftTable, rightTable, options),\n });\n\n return outputTable;\n}\n\nasync function buildJoinSelect(\n leftTable: SimpleTable,\n rightTable: SimpleTable,\n options: {\n on?: string | string[];\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n },\n): Promise<string> {\n const leftTableColumns = await leftTable.getColumns();\n const rightTableColumns = await rightTable.getColumns();\n const identicalColumns = getIdenticalColumns(leftTableColumns, rightTableColumns);\n\n let on: string[] | undefined;\n if (typeof options.on === \"string\") {\n on = [options.on];\n } else if (Array.isArray(options.on)) {\n on = options.on;\n } else {\n if (identicalColumns.length === 0) {\n throw new Error(\n `join() cannot infer a join column because tables ${quoteIdentifier(\n leftTable.name,\n )} and ${quoteIdentifier(\n rightTable.name,\n )} have no columns in common. Pass { on: \"column\" } after ensuring that column exists in both tables.`,\n );\n } else if (identicalColumns.length === 1) {\n on = identicalColumns;\n } else {\n throw new Error(\n `join() found ${identicalColumns.length} possible join columns shared by tables ${quoteIdentifier(\n leftTable.name,\n )} and ${quoteIdentifier(rightTable.name)}: ${identicalColumns\n .map(quoteIdentifier)\n .join(\", \")}. Pass { on: \"column\" } or { on: [\"column1\", \"column2\"] } to choose.`,\n );\n }\n }\n\n const identicalColumnsForError = identicalColumns.filter((d) => !on.includes(d));\n if (identicalColumnsForError.length > 0) {\n if (identicalColumnsForError.length === 1) {\n throw new Error(\n `The tables have columns with identical names (excluding ${on\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")} used for the join). Rename or remove ${identicalColumnsForError\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\n \", \",\n )} in one of the two tables before doing the join. If relevant, you can also add it to the on option.`,\n );\n } else {\n throw new Error(\n `The tables have columns with identical names (excluding ${on\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")} used for the join). Rename or remove ${identicalColumnsForError\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\n \", \",\n )} in one of the two tables before doing the join. If relevant, you can also add them to the on option.`,\n );\n }\n }\n\n // The right table's copies of the join columns are excluded from the\n // SELECT directly, instead of dropping them with a rewrite after the join.\n // The join columns come from the side that has a value for every row of\n // the result: the left table for inner and left joins, the right table for\n // right joins, and whichever side matched for full joins.\n const type = options.type ?? \"left\";\n const joinColumn = (d: string) => {\n if (type === \"right\") {\n return `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)} AS ${quoteIdentifier(d)}`;\n }\n if (type === \"full\") {\n return `COALESCE(${quoteIdentifier(leftTable.name)}.${quoteIdentifier(\n d,\n )}, ${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)}) AS ${quoteIdentifier(d)}`;\n }\n return `${quoteIdentifier(leftTable.name)}.${quoteIdentifier(d)}`;\n };\n const selectList = [\n ...leftTableColumns.map((d) =>\n on.includes(d) ? joinColumn(d) : `${quoteIdentifier(leftTable.name)}.${quoteIdentifier(d)}`,\n ),\n ...rightTableColumns\n .filter((d) => !on.includes(d))\n .map((d) => `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)}`),\n ].join(\", \");\n\n return joinQuery(leftTable.name, rightTable.name, on, type, selectList);\n}\n\nfunction joinQuery(\n leftTable: string,\n rightTable: string,\n on: string[],\n join: \"inner\" | \"left\" | \"right\" | \"full\",\n selectList: string,\n) {\n let query = `SELECT ${selectList}`;\n\n if (join === \"inner\") {\n query += ` FROM ${quoteIdentifier(leftTable)} JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"left\") {\n query += ` FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"right\") {\n query += ` FROM ${quoteIdentifier(leftTable)} RIGHT JOIN ${quoteIdentifier(rightTable)}`;\n } else if (join === \"full\") {\n query += ` FROM ${quoteIdentifier(leftTable)} FULL JOIN ${quoteIdentifier(rightTable)}`;\n } else {\n throw new Error(`Unknown ${String(join)} join.`);\n }\n\n query += ` ON (${on\n .map(\n (d) =>\n `${quoteIdentifier(leftTable)}.${quoteIdentifier(d)} = ${quoteIdentifier(\n rightTable,\n )}.${quoteIdentifier(d)}`,\n )\n .join(\" AND \")})`;\n\n return query;\n}\n","export type FuzzyMethod = \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n\nexport default function buildFuzzyMatchSql(\n leftExpression: string,\n rightExpression: string,\n method: FuzzyMethod,\n threshold: number,\n options: {\n decimals?: number;\n prefilterPrefixLength?: number;\n } = {},\n): { scoreExpression: string; condition: string } {\n const fuzzyExpression = `rapidfuzz_${method}(${leftExpression}, ${rightExpression})`;\n const scoreExpression =\n options.decimals === undefined\n ? fuzzyExpression\n : `ROUND(${fuzzyExpression}, ${options.decimals})`;\n\n let condition = `${scoreExpression} >= ${threshold}`;\n\n if (method === \"ratio\") {\n const maxDiffMultiplier = (200 - 2 * threshold) / (200 - threshold);\n condition += ` AND ABS(LENGTH(${leftExpression}) - LENGTH(${rightExpression})) <= ${maxDiffMultiplier} * GREATEST(LENGTH(${leftExpression}), LENGTH(${rightExpression}))`;\n }\n if (options.prefilterPrefixLength !== undefined) {\n condition += ` AND SUBSTR(${leftExpression}, 1, ${options.prefilterPrefixLength}) = SUBSTR(${rightExpression}, 1, ${options.prefilterPrefixLength})`;\n }\n\n return { scoreExpression, condition };\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getIdenticalColumns from \"../helpers/getIdenticalColumns.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\nimport buildFuzzyMatchSql, { type FuzzyMethod } from \"../helpers/buildFuzzyMatchSql.ts\";\n\nexport default function fuzzyJoin(\n leftTable: SimpleTable,\n rightTable: SimpleTable,\n leftColumn: string,\n rightColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n similarityColumn?: string;\n outputTable?: string | boolean;\n prefilterPrefixLength?: number;\n } = {},\n): SimpleTable {\n assertSameDatabase(leftTable.sdb, [rightTable], \"fuzzyJoin()\");\n options = structuredClone(options);\n // This validation doesn't need the database, so it stays at call time.\n if (leftColumn === rightColumn) {\n throw new Error(\n `The leftColumn and rightColumn have the same name ${quoteIdentifier(\n leftColumn,\n )}. Rename one of them before doing the fuzzy join.`,\n );\n }\n\n // The output table instance is created at call time so it can be returned\n // synchronously and chained on right away.\n const outputTable =\n typeof options.outputTable === \"string\"\n ? leftTable.sdb.newTable(options.outputTable)\n : leftTable;\n\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"fuzzyJoin()\",\n parameters: {\n leftColumn,\n rightColumn,\n rightTable: rightTable.name,\n threshold,\n options,\n },\n execute: () =>\n executeFuzzyJoin(\n leftTable,\n rightTable,\n outputTable,\n leftColumn,\n rightColumn,\n threshold,\n options,\n ),\n });\n\n return outputTable;\n}\n\nasync function executeFuzzyJoin(\n leftTable: SimpleTable,\n rightTable: SimpleTable,\n outputTable: SimpleTable,\n leftColumn: string,\n rightColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n similarityColumn?: string;\n prefilterPrefixLength?: number;\n },\n): Promise<void> {\n const leftCols = await leftTable.getColumns();\n const rightCols = await rightTable.getColumns();\n const identicalColumns = getIdenticalColumns(leftCols, rightCols);\n\n // Any column shared between both tables — other than rightColumn (whose\n // potential _1 duplicate we clean up) — would produce ambiguous output.\n const identicalColumnsForError = identicalColumns.filter((d) => d !== rightColumn);\n if (identicalColumnsForError.length > 0) {\n if (identicalColumnsForError.length === 1) {\n throw new Error(\n `The tables have columns with identical names. Rename or remove \"${\n identicalColumnsForError[0]\n }\" in one of the two tables before doing the fuzzy join.`,\n );\n } else {\n throw new Error(\n `The tables have columns with identical names. Rename or remove ${identicalColumnsForError\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")} in one of the two tables before doing the fuzzy join.`,\n );\n }\n }\n\n const method = options.method ?? \"ratio\";\n const similarityColumn = options.similarityColumn;\n const queryOptions = mergeOptions(leftTable, {\n table: outputTable.name,\n method: \"fuzzyJoin()\",\n parameters: {\n leftColumn,\n rightColumn,\n rightTable: rightTable.name,\n threshold,\n options,\n },\n });\n const deduplicate = await shouldDeduplicateFuzzyJoin(\n leftTable,\n rightTable,\n leftColumn,\n rightColumn,\n queryOptions,\n );\n\n // The right table's copy of a column shared with the left table (only\n // rightColumn can be shared, checked above) is excluded from the SELECT\n // directly, instead of dropping its _1 duplicate with a rewrite after the\n // join.\n const rightSelect = rightCols\n .filter((d) => !leftCols.includes(d))\n .map((d) => `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)}`)\n .join(\", \");\n\n const sql =\n `INSTALL rapidfuzz FROM community; LOAD rapidfuzz;\\n` +\n fuzzyJoinQuery(\n leftTable.name,\n leftColumn,\n rightTable.name,\n rightColumn,\n method,\n threshold,\n outputTable.name,\n similarityColumn,\n rightSelect,\n options.prefilterPrefixLength,\n deduplicate,\n );\n\n await queryDB(leftTable, sql, queryOptions);\n}\n\nasync function shouldDeduplicateFuzzyJoin(\n leftTable: SimpleTable,\n rightTable: SimpleTable,\n leftColumn: string,\n rightColumn: string,\n queryOptions: Parameters<typeof queryDB>[2],\n): Promise<boolean> {\n const left = quoteIdentifier(leftTable.name);\n const right = quoteIdentifier(rightTable.name);\n const counts = (await queryDB(\n leftTable,\n `SELECT (SELECT COUNT(*) FROM ${left}) AS left_count,\n (SELECT COUNT(*) FROM ${right}) AS right_count`,\n { ...queryOptions, returnData: true },\n ))![0];\n const leftCount = Number(counts.left_count);\n const rightCount = Number(counts.right_count);\n const comparisons = leftCount * rightCount;\n // Avoid distinct scans for small joins and short lookup tables. For larger\n // joins, require at least a twofold reduction to pay for grouping and rejoining.\n if (comparisons < 100_000 || Math.min(leftCount, rightCount) < 32) {\n return false;\n }\n const distinct = (await queryDB(\n leftTable,\n `SELECT\n (SELECT COUNT(DISTINCT ENCODE(${quoteIdentifier(leftColumn)})) FROM ${left}) AS left_count,\n (SELECT COUNT(DISTINCT ENCODE(${quoteIdentifier(\n rightColumn,\n )})) FROM ${right}) AS right_count`,\n { ...queryOptions, returnData: true },\n ))![0];\n return Number(distinct.left_count) * Number(distinct.right_count) <= comparisons / 2;\n}\n\nfunction fuzzyJoinQuery(\n leftTable: string,\n leftColumn: string,\n rightTable: string,\n rightColumn: string,\n method: FuzzyMethod,\n threshold: number,\n outputTable: string,\n similarityColumn: string | undefined,\n rightSelect: string,\n prefilterPrefixLength?: number,\n deduplicate = false,\n) {\n const leftExpression = `${quoteIdentifier(leftTable)}.${quoteIdentifier(leftColumn)}`;\n const rightExpression = `${quoteIdentifier(rightTable)}.${quoteIdentifier(rightColumn)}`;\n const { scoreExpression, condition } = buildFuzzyMatchSql(\n leftExpression,\n rightExpression,\n method,\n threshold,\n { decimals: 2, prefilterPrefixLength },\n );\n\n let cte = \"\";\n let from = `FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(\n rightTable,\n )} ON ${condition}`;\n let score = scoreExpression;\n if (deduplicate) {\n const matches = quoteIdentifier(\n `__sda_fuzzy_matches_${crypto.randomUUID().replaceAll(\"-\", \"\")}`,\n );\n const match = buildFuzzyMatchSql(\"l.value\", \"r.value\", method, threshold, {\n decimals: 2,\n prefilterPrefixLength,\n });\n // Keep the original value's collation for prefix matching, but use byte\n // keys for deduplication and expansion: fuzzy scores distinguish case even\n // when an input column has a case-insensitive collation.\n cte = `WITH ${matches} AS MATERIALIZED (\n SELECT l.key AS left_key, r.key AS right_key,\n ${match.scoreExpression} AS score\n FROM (\n SELECT DISTINCT ${quoteIdentifier(leftColumn)} AS value,\n ENCODE(${quoteIdentifier(leftColumn)}) AS key\n FROM ${quoteIdentifier(leftTable)}\n WHERE ${quoteIdentifier(leftColumn)} IS NOT NULL\n ) l\n INNER JOIN (\n SELECT DISTINCT ${quoteIdentifier(rightColumn)} AS value,\n ENCODE(${quoteIdentifier(rightColumn)}) AS key\n FROM ${quoteIdentifier(rightTable)}\n WHERE ${quoteIdentifier(rightColumn)} IS NOT NULL\n ) r ON ${match.condition}\n )`;\n from = `FROM ${quoteIdentifier(leftTable)}\n LEFT JOIN ${matches} ON ENCODE(${leftExpression}) = ${matches}.left_key\n LEFT JOIN ${quoteIdentifier(rightTable)}\n ON ENCODE(${rightExpression}) = ${matches}.right_key`;\n score = `${matches}.score`;\n }\n\n if (similarityColumn) {\n return `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable)} AS\n${cte}\nSELECT * EXCLUDE (\"_sda_score\"), \"_sda_score\" AS ${quoteIdentifier(similarityColumn)}\nFROM (\n SELECT ${quoteIdentifier(leftTable)}.*, ${rightSelect}, ${score} AS \"_sda_score\"\n ${from}\n) _sda\nORDER BY ${quoteIdentifier(leftColumn)}, \"_sda_score\" DESC;\\n`;\n }\n\n return `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable)} AS\n${cte}\nSELECT *\nFROM (\n SELECT ${quoteIdentifier(leftTable)}.*, ${rightSelect}\n ${from}\n) _sda\nORDER BY ${quoteIdentifier(leftColumn)}, ${quoteIdentifier(rightColumn)};\\n`;\n}\n","export type FuzzyPair = {\n left_value: string;\n right_value: string;\n left_cnt: number;\n right_cnt: number;\n score: number;\n};\n\nexport type FuzzyStrategy =\n | \"mostCommon\"\n | \"longestString\"\n | \"shortestString\"\n | \"mostCentral\"\n | \"maxScore\";\n\n/** Groups matching values transitively and chooses each component's canonical value. */\nexport default function selectFuzzyReplacements(\n pairs: FuzzyPair[],\n strategy: FuzzyStrategy,\n): Map<string, string> {\n // Build count map from the pairs — no separate query needed.\n const countMap = new Map<string, number>();\n for (const { left_value, left_cnt, right_value, right_cnt } of pairs) {\n countMap.set(left_value, Number(left_cnt));\n countMap.set(right_value, Number(right_cnt));\n }\n\n // Union-Find — only over values that actually participate in a pair.\n const parent = new Map<string, string>();\n\n const find = (x: string): string => {\n if (!parent.has(x)) parent.set(x, x);\n if (parent.get(x) !== x) parent.set(x, find(parent.get(x)!));\n return parent.get(x)!;\n };\n\n const union = (a: string, b: string) => {\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n };\n\n for (const v of countMap.keys()) find(v);\n for (const { left_value, right_value } of pairs) {\n union(left_value, right_value);\n }\n\n // Group values by their cluster root.\n const clusters = new Map<string, string[]>();\n for (const v of countMap.keys()) {\n const root = find(v);\n if (!clusters.has(root)) clusters.set(root, []);\n clusters.get(root)!.push(v);\n }\n\n // Pick the canonical value for each cluster.\n const replacement = new Map<string, string>();\n\n // Every pair belongs to exactly one component. Accumulate scores globally,\n // at most once, instead of scanning all pairs separately for each cluster.\n // Keep this lazy: distinct counts/lengths can choose a winner without scores.\n // Iterating in the original pair order also preserves floating-point ties.\n let scoreSum: Map<string, number> | null = null;\n const getScoreSum = (): Map<string, number> => {\n if (scoreSum === null) {\n scoreSum = new Map();\n for (const { left_value, right_value, score } of pairs) {\n scoreSum.set(left_value, (scoreSum.get(left_value) ?? 0) + score);\n scoreSum.set(right_value, (scoreSum.get(right_value) ?? 0) + score);\n }\n }\n return scoreSum;\n };\n\n let scoreMax: Map<string, number> | null = null;\n const getScoreMax = (): Map<string, number> => {\n if (scoreMax === null) {\n scoreMax = new Map();\n for (const { left_value, right_value, score } of pairs) {\n scoreMax.set(left_value, Math.max(scoreMax.get(left_value) ?? 0, score));\n scoreMax.set(right_value, Math.max(scoreMax.get(right_value) ?? 0, score));\n }\n }\n return scoreMax;\n };\n\n for (const members of clusters.values()) {\n if (members.length === 1) continue;\n\n // Sum-based comparator: highest total similarity, then alphabetical.\n const byScore = (a: string, b: string): string => {\n const sum = getScoreSum();\n const sa = sum.get(a) ?? 0;\n const sb = sum.get(b) ?? 0;\n if (sa !== sb) return sa > sb ? a : b;\n return a <= b ? a : b; // alphabetical tie-break\n };\n\n // Max-based comparator: highest single-pair score, then sum, then alphabetical.\n const byMaxScore = (a: string, b: string): string => {\n const mx = getScoreMax();\n const ma = mx.get(a) ?? 0;\n const mb = mx.get(b) ?? 0;\n if (ma !== mb) return ma > mb ? a : b;\n return byScore(a, b); // sum then alphabetical tie-break\n };\n\n let canonical: string;\n if (strategy === \"longestString\") {\n canonical = members.reduce((a, b) => {\n if (a.length !== b.length) return a.length > b.length ? a : b;\n return byScore(a, b);\n });\n } else if (strategy === \"shortestString\") {\n canonical = members.reduce((a, b) => {\n if (a.length !== b.length) return a.length < b.length ? a : b;\n return byScore(a, b);\n });\n } else if (strategy === \"mostCommon\") {\n canonical = members.reduce((a, b) => {\n const ca = countMap.get(a) ?? 0;\n const cb = countMap.get(b) ?? 0;\n if (ca !== cb) return ca > cb ? a : b;\n return byScore(a, b);\n });\n } else if (strategy === \"mostCentral\") {\n // Most central string — highest total similarity to all other cluster members.\n canonical = members.reduce((a, b) => byScore(a, b));\n } else {\n // \"maxScore\": the string participating in the single highest-scoring pair.\n canonical = members.reduce((a, b) => byMaxScore(a, b));\n }\n\n for (const m of members) {\n if (m !== canonical) replacement.set(m, canonical);\n }\n }\n\n return replacement;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport { DuckDBListValue } from \"@duckdb/node-api\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport buildFuzzyMatchSql from \"../helpers/buildFuzzyMatchSql.ts\";\nimport selectFuzzyReplacements, { type FuzzyPair } from \"../helpers/selectFuzzyReplacements.ts\";\n\nexport default function fuzzyClean(\n table: SimpleTable,\n column: string,\n newColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n strategy?: \"mostCommon\" | \"longestString\" | \"shortestString\" | \"mostCentral\" | \"maxScore\";\n prefilterPrefixLength?: number;\n } = {},\n): void {\n // This implementation clusters fuzzy pairs in JS and writes the mapping\n // back to DuckDB, so it executes as a barrier.\n options = structuredClone(options);\n queueOp(table, {\n kind: \"barrier\",\n method: \"fuzzyClean()\",\n parameters: { column, newColumn, threshold, options },\n execute: () => executeFuzzyClean(table, column, newColumn, threshold, options),\n });\n}\n\nasync function executeFuzzyClean(\n table: SimpleTable,\n column: string,\n newColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n strategy?: \"mostCommon\" | \"longestString\" | \"shortestString\" | \"mostCentral\" | \"maxScore\";\n prefilterPrefixLength?: number;\n } = {},\n): Promise<void> {\n const method = options.method ?? \"ratio\";\n const strategy = options.strategy ?? \"mostCommon\";\n const { scoreExpression, condition } = buildFuzzyMatchSql(\n \"a.value\",\n \"b.value\",\n method,\n threshold,\n { prefilterPrefixLength: options.prefilterPrefixLength },\n );\n\n // Compute fuzzy pairs and embed counts for both sides. Only values that\n // appear in at least one pair above the threshold can be normalized —\n // singletons need no processing at all.\n const pairsData = (await queryDB(\n table,\n `INSTALL rapidfuzz FROM community; LOAD rapidfuzz;\n WITH uniques AS (\n SELECT ${quoteIdentifier(column)} AS value, COUNT(*) AS cnt\n FROM ${quoteIdentifier(table.name)}\n WHERE ${quoteIdentifier(column)} IS NOT NULL\n GROUP BY ${quoteIdentifier(column)}\n )\n SELECT\n a.value AS left_value,\n b.value AS right_value,\n a.cnt AS left_cnt,\n b.cnt AS right_cnt,\n ${scoreExpression} AS score\n FROM uniques a\n JOIN uniques b\n ON ${condition}\n AND a.value < b.value`,\n mergeOptions(table, {\n table: table.name,\n method: \"fuzzyClean()\",\n parameters: { column, newColumn, threshold, options },\n returnData: true,\n }),\n )) as FuzzyPair[] | null;\n\n const pairs = pairsData ?? [];\n if (pairs.length === 0) {\n if (newColumn !== column) {\n await queryDB(\n table,\n `ALTER TABLE ${quoteIdentifier(table.name)} ADD ${quoteIdentifier(newColumn)} VARCHAR;\n UPDATE ${quoteIdentifier(table.name)}\n SET ${quoteIdentifier(newColumn)} = ${quoteIdentifier(column)};`,\n mergeOptions(table, {\n table: table.name,\n method: \"fuzzyClean()\",\n parameters: { column, newColumn, threshold, options },\n }),\n );\n }\n return;\n }\n\n const replacement = selectFuzzyReplacements(pairs, strategy);\n\n if (replacement.size === 0) return;\n\n // Two bound lists keep the SQL and parameter count fixed as the mapping\n // grows. Side-by-side UNNEST zips the equally sized lists into mapping rows,\n // which DuckDB can hash-join to the original table.\n const values = [\n new DuckDBListValue([...replacement.keys()]),\n new DuckDBListValue([...replacement.values()]),\n ];\n const mapping = `WITH mapping(original, canonical) AS (\n SELECT UNNEST(?::VARCHAR[]), UNNEST(?::VARCHAR[])\n )`;\n\n const query =\n newColumn !== column\n ? `ALTER TABLE ${quoteIdentifier(table.name)} ADD ${quoteIdentifier(newColumn)} VARCHAR;\n UPDATE ${quoteIdentifier(table.name)}\n SET ${quoteIdentifier(newColumn)} = ${quoteIdentifier(column)};\n ${mapping}\n UPDATE ${quoteIdentifier(table.name)}\n SET ${quoteIdentifier(newColumn)} = m.canonical\n FROM mapping m\n WHERE ${quoteIdentifier(table.name)}.${quoteIdentifier(newColumn)} = m.original`\n : `${mapping}\n UPDATE ${quoteIdentifier(table.name)}\n SET ${quoteIdentifier(column)} = m.canonical\n FROM mapping m\n WHERE ${quoteIdentifier(table.name)}.${quoteIdentifier(column)} = m.original`;\n\n await queryDB(\n table,\n query,\n mergeOptions(table, {\n table: table.name,\n method: \"fuzzyClean()\",\n parameters: { column, newColumn, options },\n values,\n }),\n );\n}\n","import findGeoColumnFromSchema from \"./findGeoColumnFromSchema.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Returns the only geometry column in a table.\n *\n * @example\n * ```ts\n * const column = await findGeoColumn(table, \"getGeoData()\");\n * ```\n *\n * @param simpleTable - The table to inspect.\n *\n * @param method - The SDA method requesting a geometry column.\n *\n * @returns A promise resolving to the name of the only geometry column.\n */\nexport default async function findGeoColumn(\n simpleTable: SimpleTable,\n method: string,\n): Promise<string> {\n return findGeoColumnFromSchema(await simpleTable.getTypes(), method, simpleTable.name);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport camelCase from \"../helpers/camelCase.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { FtsIndexDefinition } from \"../helpers/indexDefinitions.ts\";\nimport buildCreateIndexQuery from \"../helpers/indexQueries.ts\";\n\nexport default function createFtsIndex(\n simpleTable: SimpleTable,\n idColumn: string,\n textColumn: string,\n options: {\n stemmer?:\n | \"arabic\"\n | \"basque\"\n | \"catalan\"\n | \"danish\"\n | \"dutch\"\n | \"english\"\n | \"finnish\"\n | \"french\"\n | \"german\"\n | \"greek\"\n | \"hindi\"\n | \"hungarian\"\n | \"indonesian\"\n | \"irish\"\n | \"italian\"\n | \"lithuanian\"\n | \"nepali\"\n | \"norwegian\"\n | \"porter\"\n | \"portuguese\"\n | \"romanian\"\n | \"russian\"\n | \"serbian\"\n | \"spanish\"\n | \"swedish\"\n | \"tamil\"\n | \"turkish\"\n | \"none\";\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n overwrite?: boolean;\n verbose?: boolean;\n } = {},\n) {\n // Index creation is multi-statement by nature: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"createFtsIndex()\",\n parameters: { idColumn, textColumn, options },\n execute: () => executeCreateFtsIndex(simpleTable, idColumn, textColumn, options),\n });\n}\n\n/**\n * Creates the index immediately, without queueing. For use inside a\n * barrier's execute, which runs during a flush.\n */\nexport async function executeCreateFtsIndex(\n simpleTable: SimpleTable,\n idColumn: string,\n textColumn: string,\n options: {\n stemmer?: string;\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n overwrite?: boolean;\n verbose?: boolean;\n },\n): Promise<void> {\n const indexName = `fts_index_${camelCase(simpleTable.name)}`;\n const indexPosition = simpleTable.indexes.findIndex(({ name }) => name === indexName);\n const indexExists = indexPosition >= 0;\n\n if (indexExists && options.overwrite) {\n if (options.verbose) {\n console.log(`\\nDropping existing FTS index on ${quoteIdentifier(textColumn)} column...`);\n }\n\n await simpleTable.sdb.customQuery(\n `PRAGMA drop_fts_index(${quoteIdentifier(simpleTable.name)});`,\n );\n\n if (options.verbose) {\n console.log(\"FTS index dropped.\");\n }\n }\n\n if (!indexExists || options.overwrite) {\n if (options.verbose) {\n console.log(`\\nCreating FTS index on ${quoteIdentifier(textColumn)} column...`);\n }\n\n const indexOptions: FtsIndexDefinition[\"options\"] = {};\n if (options.stemmer !== undefined) {\n indexOptions.stemmer = options.stemmer;\n }\n if (options.stopwords !== undefined) {\n indexOptions.stopwords = options.stopwords;\n }\n if (options.ignore !== undefined) {\n indexOptions.ignore = options.ignore;\n }\n if (options.stripAccents !== undefined) {\n indexOptions.stripAccents = options.stripAccents;\n }\n if (options.lower !== undefined) {\n indexOptions.lower = options.lower;\n }\n const definition: FtsIndexDefinition = {\n kind: \"fts\",\n name: indexName,\n idColumn,\n textColumn,\n options: indexOptions,\n };\n await simpleTable.sdb.customQuery(buildCreateIndexQuery(simpleTable.name, definition));\n if (indexExists) {\n simpleTable.indexes[indexPosition] = definition;\n } else {\n simpleTable.indexes.push(definition);\n }\n\n if (options.verbose) {\n console.log(\"FTS index created successfully.\");\n }\n } else {\n if (options.verbose) {\n console.log(\"FTS index already exists.\");\n }\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport camelCase from \"../helpers/camelCase.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { VssIndexDefinition } from \"../helpers/indexDefinitions.ts\";\nimport buildCreateIndexQuery from \"../helpers/indexQueries.ts\";\n\nexport default function createVssIndex(\n simpleTable: SimpleTable,\n column: string,\n options: {\n overwrite?: boolean;\n verbose?: boolean;\n efConstruction?: number;\n efSearch?: number;\n M?: number;\n } = {},\n) {\n // Index creation is multi-statement by nature: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"createVssIndex()\",\n parameters: { column, options },\n execute: () => executeCreateVssIndex(simpleTable, column, options),\n });\n}\n\nasync function executeCreateVssIndex(\n simpleTable: SimpleTable,\n column: string,\n options: {\n overwrite?: boolean;\n verbose?: boolean;\n efConstruction?: number;\n efSearch?: number;\n M?: number;\n },\n): Promise<void> {\n const indexName = `vss_cosine_index_${camelCase(simpleTable.name)}`;\n const indexPosition = simpleTable.indexes.findIndex(({ name }) => name === indexName);\n const indexExists = indexPosition >= 0;\n\n if (indexExists && options.overwrite) {\n if (options.verbose) {\n console.log(`\\nDropping existing VSS index on ${quoteIdentifier(column)} column...`);\n }\n\n await simpleTable.sdb.customQuery(`DROP INDEX IF EXISTS ${indexName};`);\n\n if (options.verbose) {\n console.log(\"VSS index dropped.\");\n }\n }\n\n if (!indexExists || options.overwrite) {\n if (options.verbose) {\n console.log(`\\nCreating VSS index on ${quoteIdentifier(column)} column...`);\n }\n\n const indexOptions: VssIndexDefinition[\"options\"] = {};\n if (options.efConstruction !== undefined) {\n indexOptions.efConstruction = options.efConstruction;\n }\n if (options.efSearch !== undefined) {\n indexOptions.efSearch = options.efSearch;\n }\n if (options.M !== undefined) {\n indexOptions.M = options.M;\n }\n const definition: VssIndexDefinition = {\n kind: \"vss\",\n name: indexName,\n column,\n options: indexOptions,\n };\n await simpleTable.sdb.customQuery(\n `INSTALL vss; LOAD vss;${\n simpleTable.sdb.file !== \":memory:\"\n ? \"\\nSET hnsw_enable_experimental_persistence=true;\"\n : \"\"\n }\n ${buildCreateIndexQuery(simpleTable.name, definition)}`,\n );\n if (indexExists) {\n simpleTable.indexes[indexPosition] = definition;\n } else {\n simpleTable.indexes.push(definition);\n }\n\n if (options.verbose) {\n console.log(\"VSS index created successfully.\");\n }\n } else {\n if (options.verbose) {\n console.log(\"VSS index already exists.\");\n }\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport { executeCreateFtsIndex } from \"./createFtsIndex.ts\";\n\nexport default function bm25(\n simpleTable: SimpleTable,\n text: string,\n idColumn: string,\n textColumn: string,\n count: number,\n options: {\n stemmer?:\n | \"arabic\"\n | \"basque\"\n | \"catalan\"\n | \"danish\"\n | \"dutch\"\n | \"english\"\n | \"finnish\"\n | \"french\"\n | \"german\"\n | \"greek\"\n | \"hindi\"\n | \"hungarian\"\n | \"indonesian\"\n | \"irish\"\n | \"italian\"\n | \"lithuanian\"\n | \"nepali\"\n | \"norwegian\"\n | \"porter\"\n | \"portuguese\"\n | \"romanian\"\n | \"russian\"\n | \"serbian\"\n | \"spanish\"\n | \"swedish\"\n | \"tamil\"\n | \"turkish\"\n | \"none\";\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n k?: number;\n b?: number;\n minScore?: number;\n scoreColumn?: string;\n overwriteIndex?: boolean;\n conjunctive?: boolean;\n outputTable?: string;\n verbose?: boolean;\n } = {},\n): SimpleTable {\n options = structuredClone(options);\n // This uses the fts extension\n // https://duckdb.org/docs/stable/core_extensions/full_text_search\n\n // The output table instance is created at call time so it can be returned\n // synchronously and chained on right away.\n const outputTable =\n typeof options.outputTable === \"string\"\n ? simpleTable.sdb.newTable(options.outputTable)\n : simpleTable;\n\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"bm25()\",\n parameters: { text, idColumn, textColumn, count, options },\n execute: () =>\n executeBm25(simpleTable, outputTable, text, idColumn, textColumn, count, options),\n });\n\n return outputTable;\n}\n\nasync function executeBm25(\n simpleTable: SimpleTable,\n outputTable: SimpleTable,\n text: string,\n idColumn: string,\n textColumn: string,\n count: number,\n options: {\n stemmer?: string;\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n k?: number;\n b?: number;\n minScore?: number;\n scoreColumn?: string;\n overwriteIndex?: boolean;\n conjunctive?: boolean;\n outputTable?: string;\n verbose?: boolean;\n },\n): Promise<void> {\n // The index creation runs directly (not with the sync createFtsIndex\n // builder, which would queue for the next flush).\n await executeCreateFtsIndex(simpleTable, idColumn, textColumn, {\n stemmer: options.stemmer,\n stopwords: options.stopwords,\n ignore: options.ignore,\n stripAccents: options.stripAccents,\n lower: options.lower,\n overwrite: options.overwriteIndex,\n verbose: options.verbose,\n });\n\n const minScoreCondition =\n typeof options.minScore === \"number\" ? ` AND score >= ${options.minScore}` : \"\";\n\n const selectClause =\n typeof options.scoreColumn === \"string\"\n ? `* EXCLUDE(score), score AS ${quoteIdentifier(options.scoreColumn)}`\n : `* EXCLUDE(score)`;\n\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n outputTable.name,\n )} AS SELECT ${selectClause} FROM (SELECT *, ${quoteIdentifier(\n `fts_main_${simpleTable.name}`,\n )}.match_bm25(${quoteIdentifier(idColumn)}, ?${\n typeof options.k === \"number\" ? `, k := ${options.k}` : \"\"\n }${typeof options.b === \"number\" ? `, b := ${options.b}` : \"\"}${\n options.conjunctive === true ? `, conjunctive := 1` : \"\"\n }) AS score FROM ${quoteIdentifier(\n simpleTable.name,\n )}) sq WHERE score NOT NULL${minScoreCondition} ORDER BY score DESC LIMIT ${count};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"bm25\",\n parameters: {\n text,\n idColumn,\n textColumn,\n count,\n minScore: options.minScore,\n scoreColumn: options.scoreColumn,\n k: options.k,\n b: options.b,\n stemmer: options.stemmer,\n stopwords: options.stopwords,\n ignore: options.ignore,\n stripAccents: options.stripAccents,\n lower: options.lower,\n table: options.outputTable ?? simpleTable.name,\n },\n values: [text],\n }),\n );\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Fetches sample data from the simple-data-analysis-core GitHub repository.\n *\n * @param table - The SimpleTable instance to load the data into.\n * @param sample - The name of the sample to load.\n */\nexport default function loadSample(\n table: SimpleTable,\n sample: \"fires\" | \"recipes\" | \"temperatures\" | \"temperaturesCities\" | \"canada\" | \"firesGeo\",\n): SimpleTable {\n const samples = {\n fires: {\n url: \"https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/firesCanada2023.csv\",\n geo: false,\n },\n recipes: {\n url: \"https://github.com/nshiab/simple-data-analysis-core/raw/refs/heads/main/test/data/files/recipes.parquet\",\n geo: false,\n },\n temperatures: {\n url: \"https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/data/files/dailyTemperatures.csv\",\n geo: false,\n },\n temperaturesCities: {\n url: \"https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/data/files/cities.csv\",\n geo: false,\n },\n canada: {\n url: \"https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/CanadianProvincesAndTerritories.json\",\n geo: true,\n },\n firesGeo: {\n url: \"https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/firesCanada2023.geojson\",\n geo: true,\n },\n };\n\n const sampleToLoad = samples[sample];\n\n // This validation doesn't need the database, so it stays at call time.\n if (!sampleToLoad) {\n throw new Error(\n `loadSample() does not recognize sample ${JSON.stringify(\n sample,\n )}. Available samples: ${Object.keys(samples)\n .map((name) => JSON.stringify(name))\n .join(\", \")}.`,\n );\n }\n\n if (sampleToLoad.geo) {\n return table.loadGeoData(sampleToLoad.url);\n } else {\n return table.loadData(sampleToLoad.url);\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\n\nexport default function normalizeString(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: { stripPunctuation?: boolean } = {},\n): void {\n const { stripPunctuation = true } = options;\n\n const accentRemoved = `strip_accents(${quoteIdentifier(column)})`;\n\n const lowercased = `lower(${accentRemoved})`;\n\n const punctuationRemoved = stripPunctuation\n ? `regexp_replace(${lowercased}, '[[:punct:]]', '', 'g')`\n : lowercased;\n\n const normalizedClause = `trim(regexp_replace(${punctuationRemoved}, '\\\\s+', ' ', 'g'))`;\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"normalizeString()\",\n parameters: { column, newColumn, stripPunctuation },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT *,\n CASE\n WHEN ${quoteIdentifier(column)} IS NULL THEN NULL\n ELSE ${normalizedClause}\n END AS ${quoteIdentifier(newColumn)}\n FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function distance(\n simpleTable: SimpleTable,\n column1: string,\n column2: string,\n newColumn: string,\n options: {\n unit?: \"m\" | \"km\";\n method?: \"srs\" | \"haversine\" | \"spheroid\";\n decimals?: number;\n } = {},\n) {\n // Building the expression doesn't need the database, so invalid options\n // throw at call time.\n const expression = distanceExpression(column1, column2, options);\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"distance()\",\n parameters: { column1, column2, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"distance()\");\n return `SELECT *, CAST(${expression} AS DOUBLE) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n\nfunction distanceExpression(\n column1: string,\n column2: string,\n options: {\n unit?: \"m\" | \"km\";\n method?: \"srs\" | \"spheroid\" | \"haversine\";\n decimals?: number;\n } = {},\n) {\n options = structuredClone(options);\n options.method = options.method ?? \"srs\";\n\n if (options.method === \"srs\" && typeof options.unit === \"string\") {\n throw new Error(\n \"Using the SRS unit. You can't specify options.unit unless you set options.method to 'spheroid' or 'haversine'.\",\n );\n } else if ([\"spheroid\", \"haversine\"].includes(options.method)) {\n options.unit = options.unit ?? \"m\";\n if (![\"m\", \"km\"].includes(options.unit)) {\n throw new Error(`Unknown unit ${options.unit}. Choose between 'm' and 'km'.`);\n }\n }\n\n let expression = \"\";\n if (options.method === \"srs\") {\n expression = `ST_Distance(${quoteIdentifier(column1)}, ${quoteIdentifier(column2)})`;\n } else if (options.method === \"haversine\") {\n expression = `ST_Distance_Sphere(${quoteIdentifier(column1)}, ${quoteIdentifier(\n column2,\n )}) ${options.unit === \"km\" ? \"/ 1000\" : \"\"}`;\n } else if (options.method === \"spheroid\") {\n expression = `ST_Distance_Spheroid(${quoteIdentifier(column1)}::GEOMETRY, ${quoteIdentifier(\n column2,\n )}::GEOMETRY) ${options.unit === \"km\" ? \"/ 1000\" : \"\"}`;\n } else {\n throw new Error(\n `distance() received an unknown method: ${String(options.method)}. Choose \"srs\", \"haversine\", or \"spheroid\".`,\n );\n }\n\n return typeof options.decimals === \"number\"\n ? `ROUND(${expression}, ${options.decimals})`\n : expression;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function extractLatLon(\n simpleTable: SimpleTable,\n column: string,\n latColumn: string,\n lonColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"extractLatLon()\",\n parameters: { column, latColumn, lonColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [latColumn, lonColumn], \"extractLatLon()\");\n return `SELECT *, CAST(ST_Y(${quoteIdentifier(column)}) AS DOUBLE) AS ${quoteIdentifier(\n latColumn,\n )}, CAST(ST_X(${quoteIdentifier(column)}) AS DOUBLE) AS ${quoteIdentifier(\n lonColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function coveredBy(\n simpleTable: SimpleTable,\n column: string,\n containerColumn: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"coveredBy()\",\n parameters: { column, containerColumn, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"coveredBy()\");\n return `SELECT *, CAST(ST_Covers(${quoteIdentifier(containerColumn)}, ${quoteIdentifier(\n column,\n )}) AS BOOLEAN) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function intersects(\n simpleTable: SimpleTable,\n column1: string,\n column2: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"intersects()\",\n parameters: { column1, column2, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"intersects()\");\n return `SELECT *, CAST(ST_Intersects(${quoteIdentifier(column1)}, ${quoteIdentifier(\n column2,\n )}) AS BOOLEAN) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function normalize(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n decimals?: number;\n range?: [number, number];\n } = {},\n) {\n if (\n options.range !== undefined &&\n (!Array.isArray(options.range) ||\n options.range.length !== 2 ||\n !Number.isFinite(options.range[0]) ||\n !Number.isFinite(options.range[1]) ||\n options.range[0] >= options.range[1])\n ) {\n throw new Error(\n \"normalize() options.range must contain two finite numbers in ascending order.\",\n );\n }\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"normalize()\",\n parameters: { column, newColumn, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"normalize()\");\n\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}` : \"\";\n\n const normalizedQuery = `(${quoteIdentifier(column)} - MIN(${quoteIdentifier(\n column,\n )}) OVER(${partition}))\n /\n (MAX(${quoteIdentifier(column)}) OVER(${partition}) - MIN(${quoteIdentifier(\n column,\n )}) OVER(${partition}))`;\n const [rangeMin, rangeMax] = options.range ?? [0, 1];\n const scaledQuery =\n options.range === undefined\n ? normalizedQuery\n : `${rangeMin} + (${normalizedQuery}) * ${rangeMax - rangeMin}`;\n\n return `SELECT *, (\n ${\n typeof options.decimals === \"number\"\n ? `ROUND(${scaledQuery}, ${options.decimals})`\n : scaledQuery\n }\n ) AS ${quoteIdentifier(newColumn)},\n FROM ${input}`;\n },\n });\n}\n","import stringifyUnknown from \"./stringifyUnknown.ts\";\nimport { DuckDBTimestampValue, type DuckDBValue } from \"@duckdb/node-api\";\n\n/** Converts a supported JavaScript data value to its DuckDB binding value. */\nexport default function toDuckDBValue(value: unknown): DuckDBValue {\n if (value === null || value === undefined || Number.isNaN(value)) {\n return null;\n }\n if (value instanceof Date) {\n return new DuckDBTimestampValue(BigInt(value.getTime() * 1000));\n }\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return value;\n }\n throw new Error(`Unknown bind value type ${typeof value} of ${stringifyUnknown(value)}`);\n}\n","import assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport assertColumnsExist from \"../helpers/assertColumnsExist.ts\";\nimport getStatExpression, { type Stat } from \"../helpers/getStatExpression.ts\";\nimport keepNumericalColumns from \"../helpers/keepNumericalColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport toDuckDBValue from \"../helpers/toDuckDBValue.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { DuckDBTimestampTZValue, type DuckDBValue } from \"@duckdb/node-api\";\n\nconst indexValueStats = [\"min\", \"max\", \"mean\", \"median\"] as const satisfies readonly Stat[];\n\ntype IndexValueStat = (typeof indexValueStats)[number];\n\ntype IndexValueReference =\n | {\n stat: IndexValueStat;\n column?: never;\n equals?: never;\n at?: never;\n }\n | {\n column: string;\n equals: string | number | bigint | boolean | Date;\n stat?: never;\n at?: never;\n }\n | {\n column: string;\n at: \"min\" | \"max\";\n stat?: never;\n equals?: never;\n };\n\ntype IndexValueOptions = {\n by?: string | string[];\n base?: number;\n decimals?: number;\n};\n\nexport default function indexValues(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n reference: IndexValueReference,\n options: IndexValueOptions = {},\n) {\n validateReference(reference);\n if (options.base !== undefined && (!Number.isFinite(options.base) || options.base <= 0)) {\n throw new Error(\"indexValues() options.base must be a finite number greater than 0.\");\n }\n if (\n options.decimals !== undefined &&\n (!Number.isFinite(options.decimals) ||\n !Number.isInteger(options.decimals) ||\n options.decimals < 0)\n ) {\n throw new Error(\n \"indexValues() options.decimals must be a finite integer greater than or equal to 0.\",\n );\n }\n reference = structuredClone(reference);\n options = structuredClone(options);\n const columnReference =\n typeof reference.column === \"string\"\n ? (reference as Exclude<IndexValueReference, { column?: never }>)\n : undefined;\n const exactReference =\n columnReference?.equals !== undefined\n ? (columnReference as Extract<IndexValueReference, { equals: unknown }>)\n : undefined;\n const columnAtReference =\n columnReference?.at !== undefined\n ? (columnReference as Extract<IndexValueReference, { at: \"min\" | \"max\" }>)\n : undefined;\n const statReference =\n columnReference === undefined\n ? (reference as Extract<IndexValueReference, { column?: never }>)\n : undefined;\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"indexValues()\",\n parameters: { column, newColumn, reference, options },\n needsSchema: true,\n values:\n exactReference === undefined\n ? undefined\n : (schema) => [bindReferenceValue(exactReference.equals, schema[exactReference.column])],\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"indexValues()\");\n const by = options.by ? stringToArray(options.by) : [];\n assertColumnsExist(\n schema,\n [column, ...by, ...(columnReference === undefined ? [] : [columnReference.column])],\n \"indexValues()\",\n );\n if (!keepNumericalColumns(schema).includes(column)) {\n throw new Error(\n `indexValues() requires a numeric column, but ${quoteIdentifier(\n column,\n )} has type ${schema[column]}. Convert ${quoteIdentifier(\n column,\n )} to a numeric type first.`,\n );\n }\n if (exactReference !== undefined) {\n validateExactReferenceValueType(\n exactReference.equals,\n exactReference.column,\n schema[exactReference.column],\n );\n }\n const partition = by.length === 0 ? \"\" : `PARTITION BY ${by.map(quoteIdentifier).join(\", \")}`;\n const quotedColumn = quoteIdentifier(column);\n if (columnAtReference !== undefined) {\n const rowOrderColumn = temporaryColumn(schema, \"__sda_index_row_order\");\n const extremeColumn = temporaryColumn(schema, \"__sda_index_extreme\", [rowOrderColumn]);\n const matchCountColumn = temporaryColumn(schema, \"__sda_index_match_count\", [\n rowOrderColumn,\n extremeColumn,\n ]);\n const referenceValueColumn = temporaryColumn(schema, \"__sda_index_reference_value\", [\n rowOrderColumn,\n extremeColumn,\n matchCountColumn,\n ]);\n const quotedRowOrderColumn = quoteIdentifier(rowOrderColumn);\n const quotedExtremeColumn = quoteIdentifier(extremeColumn);\n const quotedMatchCountColumn = quoteIdentifier(matchCountColumn);\n const quotedReferenceValueColumn = quoteIdentifier(referenceValueColumn);\n const quotedReferenceColumn = quoteIdentifier(columnAtReference.column);\n const sourceAlias = quoteIdentifier(\"__sda_index_source\");\n const extremaAlias = quoteIdentifier(\"__sda_index_extrema\");\n const referenceAlias = quoteIdentifier(\"__sda_index_reference\");\n const calculatedAlias = quoteIdentifier(\"__sda_index_calculated\");\n const qualify = (alias: string, selectedColumn: string) =>\n `${alias}.${quoteIdentifier(selectedColumn)}`;\n const sourceColumn = qualify(sourceAlias, column);\n const calculatedReferenceValue = qualify(calculatedAlias, referenceValueColumn);\n const calculatedMatchCount = qualify(calculatedAlias, matchCountColumn);\n const expression = getIndexedExpression(\n sourceColumn,\n calculatedReferenceValue,\n options.base ?? 100,\n options.decimals,\n calculatedMatchCount,\n );\n const extremaBySelect = by.length === 0 ? \"\" : `${by.map(quoteIdentifier).join(\", \")}, `;\n const extremaGroupBy =\n by.length === 0 ? \"\" : ` GROUP BY ${by.map(quoteIdentifier).join(\", \")}`;\n const extremaJoin = [\n ...by.map(\n (byColumn) =>\n `${qualify(referenceAlias, byColumn)} IS NOT DISTINCT FROM ${qualify(\n extremaAlias,\n byColumn,\n )}`,\n ),\n `${qualify(referenceAlias, columnAtReference.column)} = ${qualify(\n extremaAlias,\n extremeColumn,\n )}`,\n ].join(\" AND \");\n const calculatedBySelect =\n by.length === 0\n ? \"\"\n : `${by.map((byColumn) => qualify(extremaAlias, byColumn)).join(\", \")}, `;\n const calculatedGroupBy =\n by.length === 0\n ? \"\"\n : ` GROUP BY ${by.map((byColumn) => qualify(extremaAlias, byColumn)).join(\", \")}`;\n const calculatedSubquery = `(SELECT ${calculatedBySelect}\n COUNT(${qualify(\n referenceAlias,\n columnAtReference.column,\n )}) AS ${quotedMatchCountColumn},\n MAX(${qualify(referenceAlias, column)}) AS ${quotedReferenceValueColumn}\n FROM (\n SELECT ${extremaBySelect}${columnAtReference.at.toUpperCase()}(${quotedReferenceColumn}) AS ${quotedExtremeColumn}\n FROM ${input}${extremaGroupBy}\n ) AS ${extremaAlias}\n LEFT JOIN ${input} AS ${referenceAlias} ON ${extremaJoin}${calculatedGroupBy}) AS ${calculatedAlias}`;\n const sourceJoin =\n by.length === 0\n ? `CROSS JOIN ${calculatedSubquery}`\n : `LEFT JOIN ${calculatedSubquery} ON ${by\n .map(\n (byColumn) =>\n `${qualify(sourceAlias, byColumn)} IS NOT DISTINCT FROM ${qualify(\n calculatedAlias,\n byColumn,\n )}`,\n )\n .join(\" AND \")}`;\n return `SELECT ${sourceAlias}.* EXCLUDE (${quotedRowOrderColumn}),\n ${expression} AS ${quoteIdentifier(newColumn)}\n FROM (SELECT *, ROW_NUMBER() OVER () AS ${quotedRowOrderColumn} FROM ${input}) AS ${sourceAlias}\n ${sourceJoin}\n ORDER BY ${qualify(sourceAlias, rowOrderColumn)}`;\n }\n if (exactReference !== undefined) {\n const matchColumn = temporaryColumn(schema, \"__sda_index_match\");\n const matchCountColumn = temporaryColumn(schema, \"__sda_index_match_count\", [matchColumn]);\n const referenceValueColumn = temporaryColumn(schema, \"__sda_index_reference_value\", [\n matchColumn,\n matchCountColumn,\n ]);\n const quotedMatchColumn = quoteIdentifier(matchColumn);\n const quotedMatchCountColumn = quoteIdentifier(matchCountColumn);\n const quotedReferenceValueColumn = quoteIdentifier(referenceValueColumn);\n const expression = getIndexedExpression(\n quotedColumn,\n quotedReferenceValueColumn,\n options.base ?? 100,\n options.decimals,\n quotedMatchCountColumn,\n );\n const quotedReferenceColumn = quoteIdentifier(exactReference.column);\n const matchInput = `SELECT *, ${quotedReferenceColumn} = ? AS ${quotedMatchColumn}\n FROM ${input}`;\n const excludedColumns = [\n quotedMatchColumn,\n quotedMatchCountColumn,\n quotedReferenceValueColumn,\n ].join(\", \");\n return `SELECT * EXCLUDE (${excludedColumns}),\n ${expression} AS ${quoteIdentifier(newColumn)}\n FROM (\n SELECT *,\n COUNT(*) FILTER (WHERE ${quotedMatchColumn}) OVER (${partition}) AS ${quotedMatchCountColumn},\n MAX(${quotedColumn}) FILTER (WHERE ${quotedMatchColumn}) OVER (${partition}) AS ${quotedReferenceValueColumn}\n FROM (\n ${matchInput}\n )\n )`;\n }\n const referenceValue = getWindowStatExpression(\n statReference!.stat,\n schema[column],\n quotedColumn,\n partition,\n );\n const referenceValueColumn = temporaryColumn(schema, \"__sda_index_reference_value\");\n const quotedReferenceValueColumn = quoteIdentifier(referenceValueColumn);\n const expression = getIndexedExpression(\n quotedColumn,\n quotedReferenceValueColumn,\n options.base ?? 100,\n options.decimals,\n );\n return `SELECT * EXCLUDE (${quotedReferenceValueColumn}),\n ${expression} AS ${quoteIdentifier(newColumn)}\n FROM (\n SELECT *, ${referenceValue} AS ${quotedReferenceValueColumn}\n FROM ${input}\n )`;\n },\n });\n}\n\nfunction validateReference(reference: IndexValueReference): void {\n if (reference === null || typeof reference !== \"object\") {\n throw new Error(\n \"indexValues() reference must contain stat, column and equals, or column and at.\",\n );\n }\n if (typeof reference.column !== \"string\") {\n if (\n reference.stat === undefined ||\n reference.equals !== undefined ||\n reference.at !== undefined\n ) {\n throw new Error(\n \"indexValues() reference must contain stat, column and equals, or column and at.\",\n );\n }\n if (!(indexValueStats as readonly string[]).includes(reference.stat)) {\n throw new Error(\n `indexValues() reference.stat must be one of ${indexValueStats\n .map((stat) => JSON.stringify(stat))\n .join(\", \")}.`,\n );\n }\n return;\n }\n if (reference.stat !== undefined) {\n throw new Error(\n \"indexValues() reference.stat cannot be provided with reference.column. Use reference.at to select the minimum or maximum row.\",\n );\n }\n const hasAt = reference.at !== undefined;\n const hasEquals = reference.equals !== undefined;\n if (hasAt === hasEquals) {\n throw new Error(\n hasAt\n ? \"indexValues() reference cannot contain both equals and at.\"\n : \"indexValues() reference must contain stat, column and equals, or column and at.\",\n );\n }\n if (hasAt) {\n if (!(reference.at === \"min\" || reference.at === \"max\")) {\n throw new Error('indexValues() reference.at must be \"min\" or \"max\".');\n }\n return;\n }\n if (reference.equals === null || reference.equals === undefined) {\n throw new Error(\"indexValues() reference.equals cannot be null or undefined.\");\n }\n const valueType = typeof reference.equals;\n if (\n !(reference.equals instanceof Date) &&\n ![\"string\", \"number\", \"bigint\", \"boolean\"].includes(valueType)\n ) {\n throw new Error(\n \"indexValues() reference.equals must be a string, number, bigint, boolean, or Date.\",\n );\n }\n if (typeof reference.equals === \"number\" && Number.isNaN(reference.equals)) {\n throw new Error(\"indexValues() reference.equals cannot be NaN.\");\n }\n if (reference.equals instanceof Date && Number.isNaN(reference.equals.getTime())) {\n throw new Error(\"indexValues() reference.equals must be a valid Date.\");\n }\n}\n\nfunction validateExactReferenceValueType(\n value: string | number | bigint | boolean | Date,\n column: string,\n columnType: string,\n): void {\n const valueType = value instanceof Date ? \"Date\" : typeof value;\n let expected: string | undefined;\n let valid = true;\n\n if (columnType === \"VARCHAR\" || columnType === \"UUID\" || columnType.startsWith(\"ENUM(\")) {\n expected = \"a string\";\n valid = typeof value === \"string\";\n } else if (columnType === \"BOOLEAN\") {\n expected = \"a boolean\";\n valid = typeof value === \"boolean\";\n } else if (\n columnType === \"BIGNUM\" ||\n keepNumericalColumns({ [column]: columnType }).includes(column)\n ) {\n expected = \"a number or bigint\";\n valid = typeof value === \"number\" || typeof value === \"bigint\";\n } else if (\n [\n \"DATE\",\n \"TIMESTAMP\",\n \"TIMESTAMP_S\",\n \"TIMESTAMP_MS\",\n \"TIMESTAMP_NS\",\n \"TIMESTAMP WITH TIME ZONE\",\n ].includes(columnType)\n ) {\n expected = \"a string or Date\";\n valid = typeof value === \"string\" || value instanceof Date;\n } else if ([\"TIME\", \"TIME WITH TIME ZONE\", \"INTERVAL\"].includes(columnType)) {\n expected = \"a string\";\n valid = typeof value === \"string\";\n }\n\n if (!valid) {\n throw new Error(\n `indexValues() reference.equals must be ${expected} for column ${quoteIdentifier(\n column,\n )} with type ${columnType}, but received ${valueType}.`,\n );\n }\n}\n\nfunction getIndexedExpression(\n sourceValue: string,\n referenceValue: string,\n base: number,\n decimals: number | undefined,\n matchCount?: string,\n): string {\n const indexedValue = `${sourceValue} / ${referenceValue} * ${base}`;\n const calculatedValue =\n decimals === undefined ? indexedValue : `ROUND(${indexedValue}, ${decimals})`;\n const referenceAction = matchCount === undefined ? \"calculated\" : \"found\";\n const cardinalityChecks =\n matchCount === undefined\n ? \"\"\n : `WHEN ${matchCount} = 0 THEN error('indexValues() found no reference row for at least one group.')\n WHEN ${matchCount} > 1 THEN error('indexValues() found multiple reference rows for at least one group.')\n `;\n\n return `CASE\n ${cardinalityChecks}WHEN ${referenceValue} IS NULL THEN error('indexValues() ${referenceAction} a null reference value for at least one group.')\n WHEN ${referenceValue} = 0 THEN error('indexValues() ${referenceAction} a zero reference value for at least one group.')\n WHEN ${sourceValue} IS NULL THEN NULL\n ELSE ${calculatedValue}\n END`;\n}\n\nfunction getWindowStatExpression(\n stat: IndexValueStat,\n columnType: string | undefined,\n quotedColumn: string,\n partition: string,\n): string {\n const aggregate = getStatExpression(stat, columnType, quotedColumn, undefined);\n if (aggregate === null) {\n throw new Error(\n `indexValues() cannot calculate ${stat} for column ${quotedColumn} with type ${columnType}.`,\n );\n }\n return `${aggregate} OVER (${partition})`;\n}\n\nfunction bindReferenceValue(\n value: string | number | bigint | boolean | Date,\n columnType: string | undefined,\n): DuckDBValue {\n if (value instanceof Date && columnType?.includes(\"TIMESTAMP WITH TIME ZONE\")) {\n return new DuckDBTimestampTZValue(BigInt(value.getTime()) * 1000n);\n }\n return toDuckDBValue(value);\n}\n\nfunction temporaryColumn(\n schema: { [column: string]: string },\n base: string,\n reserved: string[] = [],\n): string {\n let column = base;\n let suffix = 1;\n while (schema[column] !== undefined || reserved.includes(column)) {\n column = `${base}_${suffix++}`;\n }\n return column;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function zScore(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n decimals?: number;\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"zScore()\",\n parameters: { column, newColumn, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"zScore()\");\n\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}` : \"\";\n\n const tempQuery = `(${quoteIdentifier(column)}-AVG(${quoteIdentifier(\n column,\n )}) OVER(${partition}))\n /\n STDDEV_POP(${quoteIdentifier(column)}) OVER(${partition})`;\n return `SELECT *, (\n ${\n typeof options.decimals === \"number\"\n ? `ROUND(${tempQuery}, ${options.decimals})`\n : tempQuery\n }\n ) AS ${quoteIdentifier(newColumn)},\n FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function rolling(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n stat: \"min\" | \"max\" | \"mean\" | \"median\" | \"sum\",\n preceding: number,\n following: number,\n options: {\n by?: string | string[];\n decimals?: number;\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"rolling()\",\n parameters: { column, newColumn, stat, preceding, following, options },\n needsSchema: true,\n buildSelect: (input, schema) =>\n rollingSelect(input, schema, column, newColumn, stat, preceding, following, options),\n });\n}\n\nfunction rollingSelect(\n input: string,\n schema: TableSchema,\n column: string,\n newColumn: string,\n stat: \"count\" | \"min\" | \"max\" | \"mean\" | \"median\" | \"sum\",\n preceding: number,\n following: number,\n options: {\n by?: string | string[];\n decimals?: number;\n } = {},\n) {\n assertNewColumns(schema, [newColumn], \"rolling()\");\n\n const aggregates: { [key: string]: string } = {\n count: \"COUNT\",\n min: \"MIN\",\n max: \"MAX\",\n mean: \"AVG\",\n median: \"MEDIAN\",\n sum: \"SUM\",\n };\n\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}` : \"\";\n\n const window = `OVER (${partition}\n ROWS BETWEEN ${preceding} PRECEDING AND ${following} FOLLOWING)`;\n\n const tempQuery = `${aggregates[stat]}(${quoteIdentifier(column)}) ${window}`;\n\n // Windows touching the edges of the frame (or of their category) have\n // fewer values than requested, so their result is NULL.\n return `SELECT *,\n CASE\n WHEN COUNT(${quoteIdentifier(column)}) ${window} != ${preceding + following + 1} THEN NULL\n ELSE ${\n typeof options.decimals === \"number\"\n ? `ROUND(${tempQuery}, ${options.decimals})`\n : tempQuery\n }\n END AS ${quoteIdentifier(newColumn)}\n FROM ${input}`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function accumulate(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n) {\n // The accumulation order is based on rowid, which only exists on the\n // materialized table, not on the output of a fused step: it executes as a\n // barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"accumulate()\",\n parameters: { column, newColumn, options },\n execute: async () => {\n // A SELECT *, expr AS col colliding with an existing column would be\n // silently renamed by DuckDB (col -> col_1) instead of erroring.\n assertNewColumns(await simpleTable.getTypes(), [newColumn], \"accumulate()\");\n\n await queryDB(\n simpleTable,\n accumulateQuery(simpleTable.name, column, newColumn, options),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"accumulate()\",\n parameters: { column, newColumn, options },\n }),\n );\n },\n });\n}\n\nfunction accumulateQuery(\n table: string,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n) {\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")} ` : \"\";\n\n const query = `CREATE OR REPLACE TABLE ${quoteIdentifier(\n table,\n )} AS SELECT *, SUM(${quoteIdentifier(\n column,\n )}) OVER (${partition}ORDER BY rowid) AS ${quoteIdentifier(newColumn)}\n FROM ${quoteIdentifier(table)}\n ORDER BY rowid;`;\n\n return query;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function columnProportions(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n base?: number;\n decimals?: number;\n } = {},\n) {\n if (options.base !== undefined && (!Number.isFinite(options.base) || options.base <= 0)) {\n throw new Error(\"columnProportions() options.base must be a finite number greater than 0.\");\n }\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"columnProportions()\",\n parameters: { column, newColumn, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"columnProportions()\");\n\n const by = options.by ? stringToArray(options.by) : [];\n\n const partition =\n by.length === 0 ? \"\" : `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")}`;\n const proportion = `${quoteIdentifier(column)} / sum(${quoteIdentifier(\n column,\n )}) OVER(${partition}) * ${options.base ?? 1}`;\n\n return typeof options.decimals === \"number\"\n ? `SELECT *, ROUND(${proportion}, ${options.decimals}) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`\n : `SELECT *, ${proportion} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function rowProportions(\n simpleTable: SimpleTable,\n columns: string[],\n options: {\n suffix?: string;\n base?: number;\n decimals?: number;\n } = {},\n) {\n if (options.base !== undefined && (!Number.isFinite(options.base) || options.base <= 0)) {\n throw new Error(\"rowProportions() options.base must be a finite number greater than 0.\");\n }\n columns = [...columns];\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"rowProportions()\",\n parameters: { columns, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n const suffix = options.suffix ?? \"Perc\";\n assertNewColumns(\n schema,\n columns.map((col) => `${col}${suffix}`),\n \"rowProportions()\",\n );\n\n let query = `SELECT *,`;\n\n for (const col of columns) {\n const tempQuery = `${quoteIdentifier(col)} / (${columns\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\" + \")}) * ${options.base ?? 1}`;\n if (typeof options.decimals === \"number\") {\n query += ` ROUND(${tempQuery}, ${options.decimals})`;\n } else {\n query += ` ${tempQuery}`;\n }\n query += ` AS ${quoteIdentifier(`${col}${suffix}`)},`;\n }\n\n query += `FROM ${input}`;\n\n return query;\n },\n });\n}\n","import assertColumnsExist from \"../helpers/assertColumnsExist.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport keepNumericalColumns from \"../helpers/keepNumericalColumns.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function rowRanks(\n simpleTable: SimpleTable,\n columns: string[],\n options: {\n nameColumn?: string;\n valueColumn?: string;\n rank?: number;\n order?: \"asc\" | \"desc\";\n ties?: \"strict\" | \"first\" | \"all\";\n },\n) {\n columns = [...columns];\n options = structuredClone(options);\n const rank = options.rank ?? 1;\n const order = options.order ?? \"desc\";\n const ties = options.ties ?? \"strict\";\n\n if (columns.length === 0) {\n throw new Error(\"rowRanks() requires at least one column.\");\n }\n\n const duplicateColumns = columns.filter((column, index) => columns.indexOf(column) !== index);\n if (duplicateColumns.length > 0) {\n const duplicates = [...new Set(duplicateColumns)];\n throw new Error(\n `rowRanks() received duplicate column${duplicates.length === 1 ? \"\" : \"s\"} ${duplicates\n .map(quoteIdentifier)\n .join(\", \")}. Include each column only once.`,\n );\n }\n\n if (options.nameColumn === undefined && options.valueColumn === undefined) {\n throw new Error(\"rowRanks() requires nameColumn, valueColumn, or both.\");\n }\n\n if (options.nameColumn !== undefined && options.nameColumn === options.valueColumn) {\n throw new Error(\n `rowRanks() cannot use ${quoteIdentifier(options.nameColumn)} for both output columns.`,\n );\n }\n\n if (!Number.isInteger(rank) || rank < 1) {\n throw new Error(\"rowRanks() options.rank must be a positive integer.\");\n }\n\n if (rank > columns.length) {\n throw new Error(\n `rowRanks() options.rank is ${rank}, but only ${columns.length} column${\n columns.length === 1 ? \" was\" : \"s were\"\n } provided. Use a rank between 1 and ${columns.length}.`,\n );\n }\n\n if (order !== \"asc\" && order !== \"desc\") {\n throw new Error('rowRanks() options.order must be \"asc\" or \"desc\".');\n }\n\n if (ties !== \"strict\" && ties !== \"first\" && ties !== \"all\") {\n throw new Error('rowRanks() options.ties must be \"strict\", \"first\", or \"all\".');\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"rowRanks()\",\n parameters: { columns, options },\n needsSchema: true,\n values: columns,\n buildSelect: (input, schema) =>\n rowRanksSelect(input, schema, columns, options, rank, order, ties),\n });\n}\n\nfunction rowRanksSelect(\n input: string,\n schema: TableSchema,\n columns: string[],\n options: {\n nameColumn?: string;\n valueColumn?: string;\n },\n rank: number,\n order: \"asc\" | \"desc\",\n ties: \"strict\" | \"first\" | \"all\",\n): string {\n assertColumnsExist(schema, columns, \"rowRanks()\");\n\n const outputColumns = [options.nameColumn, options.valueColumn].filter(\n (column): column is string => column !== undefined,\n );\n assertNewColumns(schema, outputColumns, \"rowRanks()\");\n\n const numericalColumns = new Set(keepNumericalColumns(schema));\n const nonNumericalColumns = columns.filter((column) => !numericalColumns.has(column));\n if (nonNumericalColumns.length > 0) {\n throw new Error(\n `rowRanks() requires numeric columns, but ${nonNumericalColumns\n .map((column) => `${quoteIdentifier(column)} has type ${schema[column]}`)\n .join(\", \")}. Convert ${\n nonNumericalColumns.length === 1 ? \"it\" : \"them\"\n } to a numeric type first.`,\n );\n }\n\n const candidates = columns\n .map((column, index) => `(?, ${quoteIdentifier(column)}, ${index})`)\n .join(\",\\n \");\n const selections: string[] = [];\n if (options.nameColumn !== undefined) {\n selections.push(`selected.selected_name AS ${quoteIdentifier(options.nameColumn)}`);\n }\n if (options.valueColumn !== undefined) {\n selections.push(`selected.selected_value AS ${quoteIdentifier(options.valueColumn)}`);\n }\n\n const tied = `WITH candidates(name, value, position) AS (\n VALUES ${candidates}\n ),\n selected_value AS (\n SELECT value\n FROM candidates\n WHERE value IS NOT NULL\n ORDER BY value ${order.toUpperCase()}, position\n LIMIT 1 OFFSET ${rank - 1}\n ),\n tied AS (\n SELECT name, value, position\n FROM candidates\n WHERE value = (SELECT value FROM selected_value)\n )`;\n\n let selection: string;\n if (ties === \"all\") {\n selection = `${tied}\n SELECT name AS selected_name, value AS selected_value\n FROM tied\n ORDER BY position`;\n } else if (ties === \"strict\") {\n selection = `${tied}\n SELECT FIRST(name ORDER BY position) AS selected_name,\n FIRST(value ORDER BY position) AS selected_value\n FROM tied\n HAVING CASE\n WHEN COUNT(*) > 1 THEN error(CONCAT(\n 'rowRanks() found a tie at rank ${rank} between columns ',\n STRING_AGG(CONCAT('\"', REPLACE(name, '\"', '\"\"'), '\"'), ', ' ORDER BY position),\n '. Use { ties: \"first\" } to select the first tied column, or { ties: \"all\" } to produce one row for each tied column.'\n ))\n ELSE TRUE\n END`;\n } else {\n selection = `${tied}\n SELECT name AS selected_name, value AS selected_value\n FROM tied\n ORDER BY position\n LIMIT 1`;\n }\n\n return `SELECT source.*, ${selections.join(\", \")}\nFROM ${input} AS source\nLEFT JOIN LATERAL (\n ${selection}\n) AS selected ON TRUE`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function quantiles(\n simpleTable: SimpleTable,\n column: string,\n count: number,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"quantiles()\",\n parameters: { column, count, newColumn, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"quantiles()\");\n\n const by = options.by ? stringToArray(options.by) : [];\n\n const partition =\n by.length === 0 ? \"\" : `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")} `;\n\n return `SELECT *, ntile(${count}) OVER (${partition}ORDER BY ${quoteIdentifier(\n column,\n )}) AS ${quoteIdentifier(newColumn)}\n FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function ranks(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n order?: \"asc\" | \"desc\";\n by?: string | string[];\n dense?: boolean;\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"ranks()\",\n parameters: { column, newColumn, options },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(schema, [newColumn], \"ranks()\");\n\n const by = options.by ? stringToArray(options.by) : [];\n\n const partition =\n by.length === 0 ? \"\" : `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\",\")} `;\n\n return `SELECT *, ${\n options.dense ? \"dense_rank()\" : \"rank()\"\n } OVER (${partition}ORDER BY ${quoteIdentifier(column)} ${\n typeof options.order === \"string\" ? options.order.toUpperCase() : \"\"\n }) AS ${quoteIdentifier(newColumn)}\n FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function updateColumn(simpleTable: SimpleTable, column: string, definition: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"updateColumn()\",\n parameters: { column, definition },\n // The schema is needed to keep the column's type: UPDATE casts the\n // definition to the column's type on assignment.\n needsSchema: true,\n rawSQL: [definition],\n preservesSchema: true,\n buildSelect: (input, types) =>\n `SELECT * REPLACE (CAST((${definition}) AS ${types[column]}) AS ${quoteIdentifier(\n column,\n )}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function nest(\n simpleTable: SimpleTable,\n column: string,\n separator: string,\n by: string | string[],\n) {\n by = Array.isArray(by) ? [...by] : by;\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"nest()\",\n parameters: { column, separator, by },\n values: [separator],\n needsSchema: false,\n buildSelect: (input) => {\n const cats = stringToArray(by);\n const groupBy = cats.map((d) => `${quoteIdentifier(d)}`).join(\", \");\n const selectColumns = `${groupBy}, `;\n const orderBy = `\\nORDER BY ${cats.map((d) => `${quoteIdentifier(d)} ASC`).join(\", \")}`;\n\n return `SELECT\n ${selectColumns}STRING_AGG(${quoteIdentifier(column)}, ?) AS ${quoteIdentifier(column)}\nFROM ${input}\nGROUP BY ${groupBy}${orderBy}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function repeatRows(\n simpleTable: SimpleTable,\n column: string,\n options: { index?: string } = {},\n) {\n options = { ...options };\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"repeatRows()\",\n parameters: { column, options },\n needsSchema: options.index !== undefined,\n buildSelect: (input, schema) => {\n if (options.index) {\n assertNewColumns(schema, [options.index], \"repeatRows()\");\n return `SELECT *, UNNEST(range(CAST(${quoteIdentifier(\n column,\n )} AS BIGINT))) AS ${quoteIdentifier(options.index)} FROM ${input}`;\n }\n return `SELECT * EXCLUDE (_index) FROM (SELECT *, UNNEST(range(CAST(${quoteIdentifier(\n column,\n )} AS BIGINT))) AS _index FROM ${input})`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function unnest(simpleTable: SimpleTable, column: string, separator: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"unnest()\",\n parameters: { column, separator },\n values: [separator],\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT\n * EXCLUDE ${quoteIdentifier(column)},\n TRIM(UNNEST(SPLIT(${quoteIdentifier(column)}, ?))) AS ${quoteIdentifier(column)}\nFROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function concatenate(\n simpleTable: SimpleTable,\n columns: string[],\n newColumn: string,\n options: {\n separator?: string;\n } = {},\n) {\n columns = [...columns];\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"concatenate()\",\n parameters: { columns, newColumn, options },\n needsSchema: true,\n values: typeof options.separator === \"string\" ? [options.separator] : undefined,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"concatenate()\");\n const expression =\n typeof options.separator === \"string\"\n ? `CONCAT_WS(?, ${columns.map((d) => `${quoteIdentifier(d)}`).join(\", \")})`\n : `CONCAT(${columns.map((d) => `${quoteIdentifier(d)}`).join(\", \")})`;\n return `SELECT *, CAST(${expression} AS VARCHAR) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function lastChars(simpleTable: SimpleTable, column: string, count: number) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"lastChars()\",\n parameters: { column, count },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (RIGHT(${quoteIdentifier(column)}, ${count}) AS ${quoteIdentifier(\n column,\n )}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function firstChars(simpleTable: SimpleTable, column: string, count: number) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"firstChars()\",\n parameters: { column, count },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (LEFT(${quoteIdentifier(column)}, ${count}) AS ${quoteIdentifier(\n column,\n )}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function splitExtract(\n simpleTable: SimpleTable,\n column: string,\n separator: string,\n index: number,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"splitExtract()\",\n parameters: { column, separator, index, newColumn },\n values: [separator],\n needsSchema: true,\n buildSelect: (input, types) => {\n // Writing back to the split column itself is allowed (in-place); any\n // other existing column is a duplicate, like v1's ALTER TABLE ADD.\n assertNewColumns(types, [newColumn], \"splitExtract()\", [column]);\n const expression = `SPLIT_PART(${quoteIdentifier(column)}, ?, ${index + 1})`;\n return column === newColumn\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function truncate(simpleTable: SimpleTable, column: string, length: number) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"truncate()\",\n parameters: { column, length },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (LEFT(${quoteIdentifier(column)}, ${length}) AS ${quoteIdentifier(\n column,\n )}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function capitalize(simpleTable: SimpleTable, columns: string | string[]) {\n const cols = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"capitalize()\",\n parameters: { columns },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (${cols\n .map(\n (c) =>\n `CONCAT(UPPER(LEFT(${quoteIdentifier(c)}, 1)), LOWER(RIGHT(${quoteIdentifier(\n c,\n )}, LENGTH(${quoteIdentifier(c)})-1))) AS ${quoteIdentifier(c)}`,\n )\n .join(\", \")}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function upper(simpleTable: SimpleTable, columns: string | string[]) {\n const cols = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"upper()\",\n parameters: { columns },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (${cols\n .map((c) => `UPPER(${quoteIdentifier(c)}) AS ${quoteIdentifier(c)}`)\n .join(\", \")}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function lower(simpleTable: SimpleTable, columns: string | string[]) {\n const cols = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"lower()\",\n parameters: { columns },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (${cols\n .map((c) => `LOWER(${quoteIdentifier(c)}) AS ${quoteIdentifier(c)}`)\n .join(\", \")}) FROM ${input}`,\n });\n}\n","import { assertCacheTableMutation } from \"../helpers/cacheTableDependencies.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { retainRegisteredTables } from \"../helpers/tableRegistry.ts\";\n\nexport default async function removeTable(simpleTable: SimpleTable) {\n assertCacheTableMutation(simpleTable);\n await queryDB(\n simpleTable,\n `DROP TABLE ${quoteIdentifier(simpleTable.name)};`,\n mergeOptions(simpleTable, {\n table: null,\n method: \"removeTable()\",\n parameters: {},\n }),\n );\n\n retainRegisteredTables(simpleTable.sdb, (table) => table.name !== simpleTable.name);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function wider(\n simpleTable: SimpleTable,\n namesFrom: string,\n valuesFrom: string,\n options: {\n stat?: \"sum\" | \"count\" | \"min\" | \"max\" | \"mean\" | \"median\" | \"first\";\n } = {},\n) {\n const stat = options.stat ?? \"sum\";\n const aggregateFunction = stat === \"mean\" ? \"avg\" : stat;\n\n // DuckDB rewrites PIVOT into multiple statements internally, so it can't\n // be part of a fused chain: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"wider()\",\n parameters: { namesFrom, valuesFrom, options },\n execute: async () => {\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT * FROM (PIVOT ${quoteIdentifier(simpleTable.name)} ON ${quoteIdentifier(\n namesFrom,\n )} USING ${aggregateFunction}(${quoteIdentifier(valuesFrom)}));`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"wider()\",\n parameters: { namesFrom, valuesFrom, options },\n }),\n );\n },\n });\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function removeRows(simpleTable: SimpleTable, conditions: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"removeRows()\",\n parameters: { conditions },\n needsSchema: false,\n rawSQL: [conditions],\n preservesSchema: true,\n // DELETE removes rows where the conditions are TRUE and keeps rows where\n // they are FALSE or NULL, so the SELECT equivalent is IS NOT TRUE.\n buildSelect: (input) => `SELECT * FROM ${input} WHERE (${conditions}) IS NOT TRUE`,\n });\n}\n","import type { DuckDBValue } from \"@duckdb/node-api\";\nimport toDuckDBValue from \"./toDuckDBValue.ts\";\n\nexport type ValueFilter = {\n column: string;\n values: DuckDBValue[];\n includesNull: boolean;\n};\n\n/** Converts column filter values to bindable values while tracking nulls. */\nexport default function prepareValueFilters(columnsAndValues: {\n [key: string]: unknown;\n}): ValueFilter[] {\n return Object.entries(columnsAndValues).map(([column, value]) => {\n const boundValues = (Array.isArray(value) ? value : [value]).map(toDuckDBValue);\n return {\n column,\n values: boundValues.filter((boundValue) => boundValue !== null),\n includesNull: boundValues.some((boundValue) => boundValue === null),\n };\n });\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport prepareValueFilters, { type ValueFilter } from \"../helpers/prepareValueFilters.ts\";\n\nexport default function removeValues(\n simpleTable: SimpleTable,\n columnsAndValues: { [key: string]: unknown },\n) {\n const captured = Object.fromEntries(\n Object.entries(columnsAndValues).map(([column, values]) => [\n column,\n Array.isArray(values) ? values.map((value: unknown) => value) : values,\n ]),\n ) as typeof columnsAndValues;\n const filters = prepareValueFilters(captured);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"removeValues()\",\n parameters: { columnsAndValues: captured },\n values: filters.flatMap((filter) => filter.values),\n needsSchema: false,\n buildSelect: (input) => removeValuesSelect(input, filters),\n });\n}\n\nfunction removeValuesSelect(input: string, filters: ValueFilter[]) {\n let query = `SELECT * FROM ${input} WHERE\\n`;\n\n const conditions = [];\n for (const filter of filters) {\n const column = quoteIdentifier(filter.column);\n const notInValues =\n filter.values.length > 0\n ? `${column} NOT IN (${filter.values.map(() => \"?\").join(\", \")})`\n : null;\n conditions.push(\n notInValues === null\n ? filter.includesNull\n ? `${column} IS NOT NULL`\n : \"TRUE\"\n : filter.includesNull\n ? `(${notInValues} AND ${column} IS NOT NULL)`\n : `(${notInValues} OR ${column} IS NULL)`,\n );\n }\n\n query += conditions.join(\"\\nAND \");\n\n return query;\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport prepareValueFilters, { type ValueFilter } from \"../helpers/prepareValueFilters.ts\";\n\nexport default function keepValues(\n simpleTable: SimpleTable,\n columnsAndValues: { [key: string]: unknown },\n) {\n const captured = Object.fromEntries(\n Object.entries(columnsAndValues).map(([column, values]) => [\n column,\n Array.isArray(values) ? values.map((value: unknown) => value) : values,\n ]),\n ) as typeof columnsAndValues;\n const filters = prepareValueFilters(captured);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"keepValues()\",\n parameters: { columnsAndValues: captured },\n values: filters.flatMap((filter) => filter.values),\n needsSchema: false,\n buildSelect: (input) => keepValuesSelect(input, filters),\n });\n}\n\nfunction keepValuesSelect(input: string, filters: ValueFilter[]) {\n let query = `SELECT * FROM ${input} WHERE\\n`;\n\n const conditions = [];\n for (const filter of filters) {\n const column = quoteIdentifier(filter.column);\n const inValues =\n filter.values.length > 0 ? `${column} IN (${filter.values.map(() => \"?\").join(\", \")})` : null;\n conditions.push(\n inValues === null\n ? filter.includesNull\n ? `${column} IS NULL`\n : \"FALSE\"\n : filter.includesNull\n ? `(${inValues} OR ${column} IS NULL)`\n : inValues,\n );\n }\n\n query += conditions.join(\"\\nAND \");\n\n return query;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\n\nexport default function filter(simpleTable: SimpleTable, conditions: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"filter()\",\n parameters: { conditions },\n needsSchema: false,\n rawSQL: [conditions],\n preservesSchema: true,\n buildSelect: (input) =>\n `SELECT *\n FROM ${input}\n WHERE ${conditions}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function removeDuplicates(\n simpleTable: SimpleTable,\n options: {\n on?: string | string[];\n } = {},\n) {\n const columnsOn = options.on ? stringToArray(options.on) : null;\n const distinct = columnsOn\n ? `DISTINCT ON(${columnsOn.map((d) => `${quoteIdentifier(d)}`).join(\",\")}) *`\n : \"DISTINCT *\";\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"removeDuplicates()\",\n parameters: { options },\n needsSchema: false,\n preservesSchema: true,\n buildSelect: (input) => `SELECT ${distinct} FROM ${input}`,\n });\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function sample(\n simpleTable: SimpleTable,\n count: number | string,\n options: {\n seed?: number;\n } = {},\n) {\n options = { ...options };\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"sample()\",\n parameters: { count, options },\n needsSchema: false,\n // Seeded reservoir sampling returns a stable row order from a materialized\n // table, but DuckDB can emit those rows in a different order when the\n // sampler consumes a file scan directly.\n requiresMaterializedInput: typeof options.seed === \"number\",\n preservesSchema: true,\n buildSelect: (input) =>\n `SELECT * FROM ${input} USING SAMPLE RESERVOIR(${\n typeof count === \"number\" ? `${count} ROWS` : count\n })${typeof options.seed === \"number\" ? ` REPEATABLE(${options.seed})` : \"\"}`,\n });\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function skip(simpleTable: SimpleTable, count: number) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"skip()\",\n parameters: { count },\n needsSchema: false,\n preservesSchema: true,\n buildSelect: (input) => `SELECT * FROM ${input} OFFSET ${count} ROWS`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function selectColumns(simpleTable: SimpleTable, columns: string | string[]) {\n columns = Array.isArray(columns) ? [...columns] : columns;\n const selectedColumns = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"selectColumns()\",\n parameters: { columns },\n needsSchema: false,\n outputSchema: (types) =>\n Object.fromEntries(\n selectedColumns\n .filter((column) => types[column] !== undefined)\n .map((column) => [column, types[column]]),\n ),\n buildSelect: (input) =>\n `SELECT ${selectedColumns.map((d) => `${quoteIdentifier(d)}`).join(\", \")} FROM ${input}`,\n });\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default function sort(\n simpleTable: SimpleTable,\n order: { [key: string]: \"asc\" | \"desc\" } | null = null,\n options: {\n lang?: { [key: string]: string };\n } = {},\n) {\n const capturedOrder = order === null ? null : { ...order };\n const capturedOptions = {\n ...options,\n lang: options.lang === undefined ? undefined : { ...options.lang },\n };\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"sort()\",\n parameters: { order: capturedOrder, options: capturedOptions },\n needsSchema: false,\n preservesSchema: true,\n buildSelect: (input) => sortSelect(input, capturedOrder, capturedOptions),\n });\n}\n\nfunction sortSelect(\n input: string,\n order: { [key: string]: \"asc\" | \"desc\" } | null,\n options: {\n lang?: { [key: string]: string };\n } = {},\n) {\n let query = `SELECT * FROM ${input}\n ORDER BY`;\n\n if (order === null) {\n query += \" ALL,\";\n } else {\n for (const column of Object.keys(order)) {\n if (options.lang && options.lang[column]) {\n query += `\\n${quoteIdentifier(column)} COLLATE ${options.lang[column]} ${order[\n column\n ].toUpperCase()},`;\n } else {\n query += `\\n${quoteIdentifier(column)} ${order[column].toUpperCase()},`;\n }\n }\n }\n\n return query.slice(0, query.length - 1);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport getExtension from \"../helpers/getExtension.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function loadData(\n simpleTable: SimpleTable,\n files: string | string[],\n options: {\n fileType?: \"csv\" | \"dsv\" | \"json\" | \"parquet\" | \"excel\";\n autoDetect?: boolean;\n conditions?: string;\n limit?: number;\n includeFilename?: boolean;\n unifyColumns?: boolean;\n columnTypes?: { [key: string]: string };\n // column selection\n columns?: string[];\n // csv options\n header?: boolean;\n allText?: boolean;\n delim?: string;\n skip?: number;\n nullPadding?: boolean;\n ignoreErrors?: boolean;\n compression?: \"none\" | \"gzip\" | \"zstd\";\n encoding?: string;\n strict?: boolean;\n // json options\n jsonFormat?: \"unstructured\" | \"newlineDelimited\" | \"array\";\n records?: boolean;\n // excel options\n sheet?: string;\n } = {},\n) {\n files = Array.isArray(files) ? [...files] : files;\n options = structuredClone(options);\n // Building the SELECT doesn't need the database, so invalid arguments\n // (like the columns option with an Excel file) throw at call time.\n const select = loadDataSelect(stringToArray(files), options);\n\n queueOp(simpleTable, {\n kind: \"source\",\n method: \"loadData()\",\n parameters: { files, options },\n rawSQL: options.conditions === undefined ? undefined : [options.conditions],\n schema: knownSourceSchema(stringToArray(files), options),\n buildSelect: () => select,\n });\n}\n\ntype LoadDataOptions = {\n fileType?: \"csv\" | \"dsv\" | \"json\" | \"parquet\" | \"excel\";\n autoDetect?: boolean;\n conditions?: string;\n limit?: number;\n includeFilename?: boolean;\n unifyColumns?: boolean;\n columnTypes?: { [key: string]: string };\n columns?: string[];\n header?: boolean;\n allText?: boolean;\n delim?: string;\n skip?: number;\n nullPadding?: boolean;\n ignoreErrors?: boolean;\n compression?: \"none\" | \"gzip\" | \"zstd\";\n encoding?: string;\n strict?: boolean;\n jsonFormat?: \"unstructured\" | \"newlineDelimited\" | \"array\";\n records?: boolean;\n sheet?: string;\n};\n\nfunction knownSourceSchema(\n files: string[],\n options: LoadDataOptions,\n): { [column: string]: string } | undefined {\n if (options.columns === undefined || options.columns.length === 0) {\n return undefined;\n }\n const extension = getExtension(files[0]);\n const textSource =\n options.fileType === \"csv\" ||\n options.fileType === \"dsv\" ||\n options.fileType === \"excel\" ||\n extension === \"csv\" ||\n extension === \"xlsx\" ||\n typeof options.delim === \"string\";\n if (!textSource) return undefined;\n if (options.allText === true) {\n return Object.fromEntries(options.columns.map((column) => [column, \"VARCHAR\"]));\n }\n if (\n options.columnTypes !== undefined &&\n options.columns.every((column) => options.columnTypes?.[column] !== undefined)\n ) {\n return Object.fromEntries(\n options.columns.map((column) => [column, options.columnTypes![column].toUpperCase()]),\n );\n }\n return undefined;\n}\n\nexport function loadDataQuery(table: string, files: string[], options: LoadDataOptions = {}) {\n return `CREATE OR REPLACE TABLE ${quoteIdentifier(table)} AS ${loadDataSelect(files, options)};`;\n}\n\nfunction loadDataSelect(files: string[], options: LoadDataOptions = {}) {\n if (Object.values(options.columnTypes ?? {}).some((type) => /^\\s*geometry\\b/i.test(type))) {\n throw new Error(\n \"Geometry column types are not supported by loadData(). Use loadGeoData() instead.\",\n );\n }\n const fileExtension = getExtension(files[0]);\n if (\n options.fileType !== undefined &&\n ![\"csv\", \"dsv\", \"json\", \"parquet\", \"excel\"].includes(options.fileType)\n ) {\n throw unsupportedFileTypeError(files[0], options.fileType, fileExtension);\n }\n const filesAsString = \"[\" + files.map((file) => parseValue(file)).join(\", \") + \"]\";\n\n // Column selection: throw for Excel, build SELECT list for others\n const isExcel = options.fileType === \"excel\" || fileExtension === \"xlsx\";\n if (options.columns && options.columns.length > 0 && isExcel) {\n throw new Error(\"The 'columns' option is not supported for Excel files.\");\n }\n const selectColumns =\n options.columns && options.columns.length > 0\n ? options.columns.map((c) => `${quoteIdentifier(c)}`).join(\", \")\n : \"*\";\n\n // General options, except for parquet\n const autoDetect =\n typeof options.autoDetect === \"boolean\"\n ? `, auto_detect=${String(options.autoDetect).toUpperCase()}`\n : \", auto_detect=TRUE\";\n const columnTypes = options.columnTypes\n ? `${Object.entries(options.columnTypes)\n .map(([column, type]) => `${parseValue(column)}: ${parseValue(type)}`)\n .join(\", \")}`\n : null;\n const includeFilename =\n typeof options.includeFilename === \"boolean\"\n ? `, filename=${String(options.includeFilename).toUpperCase()}`\n : \"\";\n const unifyColumns =\n typeof options.unifyColumns === \"boolean\"\n ? `, union_by_name=${String(options.unifyColumns).toUpperCase()}`\n : \"\";\n const generalOptions = `${autoDetect}${includeFilename}${unifyColumns}`;\n\n const conditions = options.conditions ? ` WHERE ${options.conditions}` : \"\";\n const limit = typeof options.limit === \"number\" ? ` LIMIT ${options.limit}` : \"\";\n\n if (\n options.fileType === \"csv\" ||\n fileExtension === \"csv\" ||\n options.fileType === \"dsv\" ||\n typeof options.delim === \"string\"\n ) {\n const header =\n typeof options.header === \"boolean\"\n ? `, header=${String(options.header).toUpperCase()}`\n : \", header=TRUE\";\n const allText =\n typeof options.allText === \"boolean\"\n ? `, all_varchar=${String(options.allText).toUpperCase()}`\n : \"\";\n const delim = options.delim ? `, delim=${parseValue(options.delim)}` : \"\";\n const skip = options.skip ? `, skip=${options.skip}` : \"\";\n const ignoreErrors = options.ignoreErrors ? `, ignore_errors\t=${options.ignoreErrors}` : \"\";\n const nullPadding = options.nullPadding ? `, null_padding=${options.nullPadding}` : \"\";\n const compression = options.compression\n ? `, compression=${parseValue(options.compression)}`\n : \"\";\n const encoding = options.encoding ? `, encoding=${parseValue(options.encoding)}` : \"\";\n const strict = options.strict === false ? `, strict_mode=FALSE` : \"\";\n const types = columnTypes === null ? \"\" : `, types={${columnTypes}}`;\n\n return `SELECT ${selectColumns} FROM read_csv_auto(${filesAsString}${generalOptions}${types}${header}${allText}${delim}${skip}${compression}${encoding}${strict}${nullPadding}${ignoreErrors})${conditions}${limit}`;\n } else if (options.fileType === \"json\" || fileExtension === \"json\") {\n // DuckDB expects \"newline_delimited\" (snake_case), unlike the other two\n // format values, which already match the public camelCase option.\n const jsonFormat = options.jsonFormat\n ? `, format=${parseValue(\n options.jsonFormat === \"newlineDelimited\" ? \"newline_delimited\" : options.jsonFormat,\n )}`\n : \"\";\n const records =\n typeof options.records === \"boolean\"\n ? `, records=${String(options.records).toUpperCase()}`\n : \"\";\n const columns = columnTypes === null ? \"\" : `, columns={${columnTypes}}`;\n return `SELECT ${selectColumns} FROM read_json_auto(${filesAsString}${generalOptions}${columns}${jsonFormat}${records})${conditions}${limit}`;\n } else if (options.fileType === \"parquet\" || fileExtension === \"parquet\") {\n return `SELECT ${selectColumns} FROM read_parquet(${filesAsString}${includeFilename}${unifyColumns})${conditions}${limit}`;\n } else if (options.fileType === \"excel\" || fileExtension === \"xlsx\") {\n if (files.length > 1) {\n throw new Error(\n \"For excel files or files with extension .xlsx, you can pass only one file at the time.\",\n );\n }\n\n const header =\n typeof options.header === \"boolean\"\n ? `, header=${String(options.header).toUpperCase()}`\n : \", header=TRUE\";\n const allText =\n typeof options.allText === \"boolean\"\n ? `, all_varchar=${String(options.allText).toUpperCase()}`\n : \"\";\n\n return `SELECT ${selectColumns} FROM read_xlsx(${parseValue(files[0])}${\n options.sheet ? `, sheet=${parseValue(options.sheet)}` : \"\"\n }${header}${allText})${conditions}${limit}`;\n } else {\n throw unsupportedFileTypeError(files[0], options.fileType, fileExtension);\n }\n}\n\nfunction unsupportedFileTypeError(\n file: string,\n fileType: string | undefined,\n fileExtension: string,\n): Error {\n const receivedFileType = JSON.stringify(fileType) ?? String(fileType);\n return new Error(\n `loadData() could not determine a supported file type for ${JSON.stringify(\n file,\n )}. options.fileType: ${receivedFileType}. Detected extension: ${JSON.stringify(\n `.${fileExtension}`,\n )}. Supported file types: \"csv\", \"dsv\", \"json\", \"parquet\", and \"excel\" (for .xlsx files).`,\n );\n}\n","import { assertCacheTableMutation } from \"../helpers/cacheTableDependencies.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { markTableChanged } from \"../helpers/tableGeneration.ts\";\nimport { assertTableNameAvailable } from \"../helpers/tableRegistry.ts\";\n\nexport default async function renameTable(simpleTable: SimpleTable, name: string) {\n assertCacheTableMutation(simpleTable);\n assertTableNameAvailable(simpleTable.sdb, name, simpleTable);\n await queryDB(\n simpleTable,\n `ALTER TABLE ${quoteIdentifier(simpleTable.name)} RENAME TO ${quoteIdentifier(name)};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"renameTable()\",\n parameters: { name },\n }),\n );\n markTableChanged(simpleTable);\n}\n","/**\n * Transforms an array of objects into an object of arrays. This function is the inverse of `arraysToData` and is useful for converting data from a row-based format to a columnar format.\n *\n * @example\n * ```ts\n * // Basic usage with a simple dataset\n * const rowData = [\n * { name: 'Alice', age: 30, city: 'New York' },\n * { name: 'Bob', age: 25, city: 'London' },\n * { name: 'Charlie', age: 35, city: 'Paris' }\n * ];\n *\n * const columnarData = dataToArrays(rowData);\n *\n * console.log(columnarData);\n * // Expected output:\n * // {\n * // name: ['Alice', 'Bob', 'Charlie'],\n * // age: [30, 25, 35],\n * // city: ['New York', 'London', 'Paris']\n * // }\n * ```\n *\n * @example\n * ```ts\n * // Preparing data for statistical analysis\n * const measurements = [\n * { id: 1, temp: 20, humidity: 60 },\n * { id: 2, temp: 22, humidity: 65 },\n * { id: 3, temp: 18, humidity: 55 }\n * ];\n *\n * const separatedVariables = dataToArrays(measurements);\n *\n * console.log(separatedVariables);\n * // Expected output:\n * // {\n * // id: [1, 2, 3],\n * // temp: [20, 22, 18],\n * // humidity: [60, 65, 55]\n * // }\n * ```\n *\n * @param data An array of objects. Each object is expected to have the same set of keys.\n *\n * @returns An object where each key maps to an array of values, effectively representing the data in a columnar format.\n *\n * @category Formatting\n */\n\nexport default function dataToArrays<T extends Record<string, unknown>>(\n data: T[],\n): { [K in keyof T]: T[K][] } {\n const newData = {} as { [K in keyof T]: T[K][] };\n\n const keys = Object.keys(data[0]) as Array<keyof T>;\n\n for (const key of keys) {\n newData[key] = data.map((d) => d[key]);\n }\n\n return newData;\n}\n","import dataToArrays from \"./dataToArrays.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getExtension from \"./getExtension.ts\";\nimport { writeFileSync } from \"node:fs\";\n\nexport default async function writeDataAsArrays(simpleTable: SimpleTable, file: string) {\n const fileExtension = getExtension(file);\n if (fileExtension === \"json\") {\n const data = await simpleTable.getData();\n writeFileSync(file, JSON.stringify(dataToArrays(data)));\n } else {\n throw new Error(\"The option dataAsArrays works only with json files.\");\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport cleanPath from \"../helpers/cleanPath.ts\";\nimport createDirectory from \"../helpers/createDirectory.ts\";\nimport getExtension from \"../helpers/getExtension.ts\";\nimport hasGeometryColumn from \"../helpers/hasGeometryColumn.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport writeDataAsArrays from \"../helpers/writeDataAsArrays.ts\";\nimport { existsSync, rmSync } from \"node:fs\";\n\nexport default async function writeData(\n simpleTable: SimpleTable,\n file: string,\n options: {\n compression?: boolean;\n dataAsArrays?: boolean;\n formatDates?: boolean;\n } = {},\n) {\n const extension = getExtension(file);\n assertWriteDataOptions(extension, options);\n\n if (await hasGeometryColumn(simpleTable)) {\n throw new Error(\"Table contains geometry columns. Use writeGeoData() instead.\");\n }\n\n createDirectory(file);\n\n if (options.dataAsArrays) {\n await writeDataAsArrays(simpleTable, file);\n } else {\n await queryDB(\n simpleTable,\n writeDataQuery(simpleTable.name, file, extension, options),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"writeData()\",\n parameters: { file, options },\n }),\n );\n }\n}\n\nfunction assertWriteDataOptions(extension: string, options: { dataAsArrays?: boolean }): void {\n const supported = [\"csv\", \"json\", \"parquet\", \"db\", \"sqlite\"];\n if (!supported.includes(extension)) {\n throw new Error(\n `writeData() does not support the extension ${JSON.stringify(\n extension,\n )}. Use .csv, .json, .parquet, .db, or .sqlite.`,\n );\n }\n if (options.dataAsArrays === true && extension !== \"json\") {\n throw new Error(\"writeData() dataAsArrays works only with JSON files.\");\n }\n}\n\nfunction writeDataQuery(\n table: string,\n file: string,\n fileExtension: string,\n options: { compression?: boolean; formatDates?: boolean },\n) {\n const cleanedFile = cleanPath(file);\n if (fileExtension === \"csv\") {\n return `COPY ${quoteIdentifier(table)} TO '${\n options.compression ? cleanedFile + \".gz\" : cleanedFile\n }' (DELIMITER ',', HEADER TRUE${options.compression ? \", COMPRESSION GZIP\" : \"\"}${\n options.formatDates ? \", DATEFORMAT '%xT%X.%gZ', TIMESTAMPFORMAT '%xT%X.%gZ'\" : \"\"\n });`;\n } else if (fileExtension === \"json\") {\n return `COPY ${quoteIdentifier(table)} TO '${\n options.compression ? cleanedFile + \".gz\" : cleanedFile\n }' (FORMAT JSON, ARRAY TRUE${options.compression ? \", COMPRESSION GZIP\" : \"\"}${\n options.formatDates ? \", DATEFORMAT '%xT%X.%gZ', TIMESTAMPFORMAT '%xT%X.%gZ'\" : \"\"\n });`;\n } else if (fileExtension === \"parquet\") {\n if (options.compression) {\n return `COPY ${quoteIdentifier(\n table,\n )} TO '${cleanedFile}' (FORMAT PARQUET, COMPRESSION ZSTD);`;\n } else {\n return `COPY ${quoteIdentifier(table)} TO '${cleanedFile}' (FORMAT PARQUET);`;\n }\n } else if (fileExtension === \"db\") {\n if (existsSync(file)) {\n rmSync(file);\n }\n const database = quoteIdentifier(\"my_database\");\n return `ATTACH '${cleanedFile}' AS ${database};\nCOPY FROM DATABASE ${quoteIdentifier(\"memory\")} TO ${database};\nCREATE OR REPLACE TABLE ${database}.${quoteIdentifier(\n table,\n )} AS SELECT * FROM ${quoteIdentifier(table)};\nDETACH ${database};`;\n } else if (fileExtension === \"sqlite\") {\n if (existsSync(file)) {\n rmSync(file);\n }\n const database = quoteIdentifier(\"my_sqlite_db\");\n return `INSTALL sqlite; LOAD sqlite;\n ATTACH '${cleanedFile}' AS ${database} (TYPE SQLITE);\n CREATE TABLE ${database}.${quoteIdentifier(table)} AS SELECT * FROM ${quoteIdentifier(table)};\n DETACH ${database};`;\n } else {\n throw new Error(`writeData() does not support the extension ${JSON.stringify(fileExtension)}.`);\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumn from \"../helpers/findGeoColumn.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default async function getBoundingBox(\n simpleTable: SimpleTable,\n column?: string,\n): Promise<[number, number, number, number]> {\n const col = column ?? (await findGeoColumn(simpleTable, \"getBoundingBox()\"));\n const result = (await queryDB(\n simpleTable,\n `SELECT\n MIN(ST_YMin(${quoteIdentifier(col)})) AS minX,\n MIN(ST_XMin(${quoteIdentifier(col)})) AS minY,\n MAX(ST_YMax(${quoteIdentifier(col)})) AS maxX,\n MAX(ST_XMax(${quoteIdentifier(col)})) AS maxY,\n from ${quoteIdentifier(simpleTable.name)};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"getBoundingBox()\",\n parameters: { column },\n returnData: true,\n }),\n )) as { minX: number; minY: number; maxX: number; maxY: number }[];\n return [result[0].minY, result[0].minX, result[0].maxY, result[0].maxX];\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function linesToPolygons(simpleTable: SimpleTable, column?: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"linesToPolygons()\",\n parameters: { column },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const col = column ?? findGeoColumnFromSchema(types, \"linesToPolygons()\", simpleTable.name);\n return `SELECT * EXCLUDE(${quoteIdentifier(col)}), ST_MakePolygon(${quoteIdentifier(\n col,\n )}) as ${quoteIdentifier(col)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumn from \"../helpers/findGeoColumn.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function aggregateGeo(\n simpleTable: SimpleTable,\n method: \"union\" | \"intersection\",\n options: {\n column?: string;\n by?: string | string[];\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n options = structuredClone(options);\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n\n if (typeof options.outputTable === \"string\") {\n // The output table instance is created at call time so it can be\n // returned synchronously and chained on right away.\n const outputTable = simpleTable.sdb.newTable(options.outputTable);\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"aggregateGeo()\",\n parameters: { method, options },\n execute: async () => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : await findGeoColumn(simpleTable, \"aggregateGeo()\");\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable.name)} AS ${aggregateGeoSelect(\n `${quoteIdentifier(simpleTable.name)}`,\n column,\n method,\n options,\n )}`,\n mergeOptions(simpleTable, {\n table: outputTable.name,\n method: \"aggregateGeo()\",\n parameters: { column, method, options },\n }),\n );\n },\n });\n return outputTable;\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"aggregateGeo()\",\n parameters: { method, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"aggregateGeo()\", simpleTable.name);\n return aggregateGeoSelect(input, column, method, options);\n },\n });\n return simpleTable;\n}\n\nfunction aggregateGeoSelect(\n input: string,\n column: string,\n method: \"union\" | \"intersection\",\n options: {\n by?: string | string[];\n } = {},\n) {\n const categoriesOptions = options.by ?? [];\n const by = stringToArray(categoriesOptions);\n\n let query = `SELECT${\n by.length > 0 ? ` ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")},` : \"\"\n }`;\n\n if (method === \"union\") {\n query += ` CASE WHEN ST_IsEmpty(ST_Union_Agg(${quoteIdentifier(\n column,\n )})) THEN NULL ELSE ST_Union_Agg(${quoteIdentifier(column)}) END AS ${quoteIdentifier(column)}`;\n } else if (method === \"intersection\") {\n query += ` ST_Intersection_Agg(${quoteIdentifier(column)}) AS ${quoteIdentifier(column)}`;\n } else {\n throw new Error(`aggregateGeo() received an unknown method: ${String(method)}.`);\n }\n\n query += `\\nFROM ${input}`;\n\n if (by.length > 0) {\n query += `\\nGROUP BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}`;\n query += `\\nORDER BY ${by.map((d) => `${quoteIdentifier(d)} ASC`).join(\", \")}`;\n }\n\n return query;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addBoundingBox(\n simpleTable: SimpleTable,\n options: {\n column?: string;\n decimals?: number;\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addBoundingBox()\",\n parameters: { options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const column =\n options.column ?? findGeoColumnFromSchema(types, \"addBoundingBox()\", simpleTable.name);\n const round = (expression: string) =>\n typeof options.decimals === \"number\"\n ? `ROUND(${expression}, ${options.decimals})`\n : expression;\n return `SELECT *,\n ${round(`ST_XMin(${quoteIdentifier(column)})`)} AS minLon,\n ${round(`ST_YMin(${quoteIdentifier(column)})`)} AS minLat,\n ${round(`ST_XMax(${quoteIdentifier(column)})`)} AS maxLon,\n ${round(`ST_YMax(${quoteIdentifier(column)})`)} AS maxLat\n FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function unnestGeo(simpleTable: SimpleTable, column?: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"unnestGeo()\",\n parameters: { column },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const col = column ?? findGeoColumnFromSchema(types, \"unnestGeo()\", simpleTable.name);\n // The recursive UNNEST adds a path column, removed by the outer SELECT.\n return `SELECT * EXCLUDE(path) FROM (SELECT * EXCLUDE(${quoteIdentifier(\n col,\n )}), UNNEST(ST_Dump(${quoteIdentifier(col)}), recursive := TRUE) FROM ${input})`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumn from \"../helpers/findGeoColumn.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport ensureSpatial from \"../helpers/ensureSpatial.ts\";\n\nexport default function randomPoint(\n simpleTable: SimpleTable,\n newColumn: string,\n tries: number,\n options: { column?: string; strict?: boolean } = {},\n) {\n options = structuredClone(options);\n // This validation doesn't need the database, so it stays at call time.\n if (!Number.isFinite(tries) || !Number.isInteger(tries) || tries < 0) {\n throw new Error(\"randomPoint() tries must be a finite integer greater than or equal to 0.\");\n }\n\n // The generated points are checked against the data afterwards, so\n // randomPoint can't be expressed as a single SELECT over its input: it\n // executes as a barrier.\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"randomPoint()\",\n parameters: { newColumn, tries, options },\n execute: () => executeRandomPoint(simpleTable, newColumn, tries, options),\n });\n}\n\nasync function executeRandomPoint(\n simpleTable: SimpleTable,\n newColumn: string,\n tries: number,\n options: { column?: string; strict?: boolean },\n): Promise<void> {\n await ensureSpatial(simpleTable);\n const column =\n typeof options.column === \"string\"\n ? options.column\n : await findGeoColumn(simpleTable, \"randomPoint()\");\n\n const geoType = await simpleTable.getProjection(column);\n\n await queryDB(\n simpleTable,\n randomPointQuery(simpleTable.name, column, newColumn, tries, geoType, options.strict !== false),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"randomPoint()\",\n parameters: { column, newColumn, tries, options, geoType },\n }),\n );\n}\n\nfunction randomPointQuery(\n table: string,\n column: string,\n newColumn: string,\n tries: number,\n geoType: string,\n strict: boolean,\n) {\n // Recursive CTE approach: each iteration only carries forward the rows that\n // have NOT yet found a valid interior point, so DuckDB stops per-row as soon\n // as ST_Within is satisfied — giving O(1) behaviour for easy polygons instead\n // of the O(N) materialisation that occurs with LATERAL + range() + WHERE.\n //\n // Zero-tries contract: `WHERE 1 <= ${tries}` in the base case\n // produces no rows when tries is 0, so the LEFT JOIN returns NULL for\n // every row and the UPDATE sets the column to NULL — no special-case branch\n // needed and the normal UPDATE code path is always exercised.\n //\n // Volatility guard: `CASE WHEN (rid + n) IS NOT NULL THEN random() END`\n // prevents the planner from constant-folding random() across iterations while\n // still evaluating to random() for every non-null row.\n const failedExpression = strict\n ? `CASE WHEN v.failed_count > 0 THEN error(CONCAT(CAST(v.failed_count AS VARCHAR), ' points could not be generated. Consider increasing tries or set options.strict to false.')) ELSE v.pt::${geoType} END`\n : `v.pt::${geoType}`;\n const select =\n newColumn === column\n ? `t.* REPLACE (${failedExpression} AS ${quoteIdentifier(newColumn)})`\n : `t.*, ${failedExpression} AS ${quoteIdentifier(newColumn)}`;\n\n return `CREATE OR REPLACE TABLE ${quoteIdentifier(table)} AS\nWITH RECURSIVE\nbase AS (\n SELECT\n rowid AS rid,\n ${quoteIdentifier(column)} AS geom,\n ST_XMin(${quoteIdentifier(column)}) AS xmin,\n ST_XMax(${quoteIdentifier(column)}) - ST_XMin(${quoteIdentifier(column)}) AS xdiff,\n ST_YMin(${quoteIdentifier(column)}) AS ymin,\n ST_YMax(${quoteIdentifier(column)}) - ST_YMin(${quoteIdentifier(column)}) AS ydiff\n FROM ${quoteIdentifier(table)}\n),\nattempts(rid, geom, xmin, xdiff, ymin, ydiff, pt, n) AS (\n SELECT\n rid, geom, xmin, xdiff, ymin, ydiff,\n ST_Point(\n xmin + CASE WHEN rid IS NOT NULL THEN random() END * xdiff,\n ymin + CASE WHEN rid IS NOT NULL THEN random() END * ydiff\n ),\n 1\n FROM base\n WHERE 1 <= ${tries}\n UNION ALL\n SELECT\n rid, geom, xmin, xdiff, ymin, ydiff,\n ST_Point(\n xmin + CASE WHEN (rid + n) IS NOT NULL THEN random() END * xdiff,\n ymin + CASE WHEN (rid + n) IS NOT NULL THEN random() END * ydiff\n ),\n n + 1\n FROM attempts\n WHERE NOT ST_Within(pt, geom) AND n < ${tries}\n),\nvalid_points AS (\n SELECT rid, pt\n FROM attempts\n WHERE ST_Within(pt, geom)\n QUALIFY ROW_NUMBER() OVER (PARTITION BY rid ORDER BY n) = 1\n),\ngenerated AS (\n SELECT\n b.rid,\n vp.pt,\n COUNT(*) FILTER (WHERE vp.pt IS NULL) OVER () AS failed_count\n FROM (SELECT rowid AS rid FROM ${quoteIdentifier(table)}) b\n LEFT JOIN valid_points vp ON b.rid = vp.rid\n)\nSELECT ${select}\nFROM ${quoteIdentifier(table)} t\nJOIN generated v ON t.rowid = v.rid;`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function centroid(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"centroid()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"centroid()\", simpleTable.name);\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n const expression = `ST_Centroid(${quoteIdentifier(column)})::${types[column]}`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport ensureSpatial from \"../helpers/ensureSpatial.ts\";\nimport findGeoColumn from \"../helpers/findGeoColumn.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function simplify(\n simpleTable: SimpleTable,\n tolerance: number,\n options: { column?: string; simplifyBoundary?: boolean } = {},\n) {\n // The coverage simplification groups by rowid, which only exists on the\n // materialized table: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"simplify()\",\n parameters: { tolerance, options },\n execute: () => executeSimplify(simpleTable, tolerance, options),\n });\n}\n\nasync function executeSimplify(\n simpleTable: SimpleTable,\n tolerance: number,\n options: { column?: string; simplifyBoundary?: boolean },\n): Promise<void> {\n await ensureSpatial(simpleTable);\n\n const column =\n typeof options.column === \"string\"\n ? options.column\n : await findGeoColumn(simpleTable, \"simplify()\");\n\n const geoType = await simpleTable.getProjection(column);\n\n // Each row is its own coverage group: grouping by rowid directly avoids\n // materializing a temporary row-number column. rowid is not part of\n // SELECT *, so the other columns are listed explicitly in the GROUP BY.\n const groupBy = [\n \"rowid\",\n ...(await simpleTable.getColumns())\n .filter((d) => d !== column)\n .map((d) => `${quoteIdentifier(d)}`),\n ].join(\", \");\n\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT * REPLACE(ST_CoverageSimplify(ARRAY_AGG(${quoteIdentifier(column)}), ${tolerance}${\n options.simplifyBoundary === false ? \", FAlSE\" : \"\"\n })::${geoType} AS ${quoteIdentifier(column)}) FROM ${quoteIdentifier(\n simpleTable.name,\n )} GROUP BY ${groupBy};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"simplify()\",\n parameters: { column, tolerance },\n }),\n );\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function union(\n simpleTable: SimpleTable,\n column1: string,\n column2: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"union()\",\n parameters: { column1, column2, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n const expression = `ST_Union(${quoteIdentifier(column1)}, ${quoteIdentifier(\n column2,\n )})::${types[column1]}`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function fillHoles(simpleTable: SimpleTable, column?: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"fillHoles()\",\n parameters: { column },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const col = column ?? findGeoColumnFromSchema(types, \"fillHoles()\", simpleTable.name);\n // Like the previous UPDATE-based implementation, the result is always\n // stored in the \"geom\" column, and the assignment cast keeps its type.\n return `SELECT * REPLACE (ST_MakePolygon(ST_ExteriorRing(${quoteIdentifier(\n col,\n )}))${types[\"geom\"] ? `::${types[\"geom\"]}` : \"\"} AS \"geom\") FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function difference(\n simpleTable: SimpleTable,\n column1: string,\n column2: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"difference()\",\n parameters: { column1, column2, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n const expression = `ST_Difference(${quoteIdentifier(column1)}, ${quoteIdentifier(\n column2,\n )})::${types[column1]}`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function intersection(\n simpleTable: SimpleTable,\n column1: string,\n column2: string,\n newColumn: string,\n) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"intersection()\",\n parameters: { column1, column2, newColumn },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n const expression = `ST_Intersection(${quoteIdentifier(column1)}, ${quoteIdentifier(\n column2,\n )})::${types[column1]}`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function buffer(\n simpleTable: SimpleTable,\n newColumn: string,\n distance: number,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"buffer()\",\n parameters: { newColumn, distance, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"buffer()\", simpleTable.name);\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n const expression = `ST_Buffer(${quoteIdentifier(column)}, ${distance})::${types[column]}`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function perimeter(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { unit?: \"m\" | \"km\"; column?: string; decimals?: number } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"perimeter()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"perimeter()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"perimeter()\", simpleTable.name);\n let expression = `ST_Perimeter_Spheroid(${quoteIdentifier(column)}) ${\n options.unit === \"km\" ? \"/ 1000\" : \"\"\n }`;\n if (typeof options.decimals === \"number\") {\n expression = `ROUND(${expression}, ${options.decimals})`;\n }\n return `SELECT *, CAST(${expression} AS DOUBLE) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function length(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { unit?: \"m\" | \"km\"; column?: string; decimals?: number } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"length()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"length()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"length()\", simpleTable.name);\n let expression = `ST_Length_Spheroid(${quoteIdentifier(column)}) ${\n options.unit === \"km\" ? \"/ 1000\" : \"\"\n }`;\n if (typeof options.decimals === \"number\") {\n expression = `ROUND(${expression}, ${options.decimals})`;\n }\n return `SELECT *, CAST(${expression} AS DOUBLE) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function area(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { unit?: \"m2\" | \"km2\"; column?: string; decimals?: number } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"area()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"area()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"area()\", simpleTable.name);\n let expression = `ST_Area_Spheroid(${quoteIdentifier(column)}) ${\n options.unit === \"km2\" ? \"/ 1000000\" : \"\"\n }`;\n if (typeof options.decimals === \"number\") {\n expression = `ROUND(${expression}, ${options.decimals})`;\n }\n return `SELECT *, CAST(${expression} AS DOUBLE) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function reproject(\n simpleTable: SimpleTable,\n crs: string,\n options: { column?: string } = {},\n) {\n const targetGeoType = `GEOMETRY${crs !== \"null\" ? `(${parseValue(crs)})` : \"\"}`;\n\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"reproject()\",\n parameters: { crs, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"reproject()\", simpleTable.name);\n return `SELECT * REPLACE (ST_Transform(${quoteIdentifier(column)}, ${parseValue(\n crs,\n )})::${targetGeoType} AS ${quoteIdentifier(column)}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function reducePrecision(\n simpleTable: SimpleTable,\n decimals: number,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"reducePrecision()\",\n parameters: { decimals, options },\n needsSchema: true,\n needsSpatial: true,\n // The cast pins the geometry column back to its existing type, so the\n // schema is unchanged.\n preservesSchema: true,\n buildSelect: (input, types) => {\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"reducePrecision()\", simpleTable.name);\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n return `SELECT * REPLACE (ST_ReducePrecision(${quoteIdentifier(\n column,\n )}, ${1 / Math.pow(10, decimals)})::${types[column]} AS ${quoteIdentifier(\n column,\n )}) FROM ${input}`;\n },\n });\n}\n","import findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n// This is the mean Earth radius used by DuckDB's ST_Distance_Sphere().\nconst EARTH_RADIUS_METERS = 6_371_000;\n\nexport default function addGeoNoise(\n simpleTable: SimpleTable,\n maxDistance: number,\n options: {\n column?: string;\n unit?: \"m\" | \"km\";\n onlyDuplicates?: boolean;\n } = {},\n) {\n // This validation doesn't need the database, so it stays at call time.\n if (!Number.isFinite(maxDistance) || maxDistance < 0) {\n throw new Error(\n \"addGeoNoise() maxDistance must be a finite number greater than or equal to 0.\",\n );\n }\n if (options.unit !== undefined && options.unit !== \"m\" && options.unit !== \"km\") {\n throw new Error('addGeoNoise() options.unit must be \"m\" or \"km\".');\n }\n\n options = structuredClone(options);\n const maxDistanceMeters = options.unit === \"km\" ? maxDistance * 1_000 : maxDistance;\n if (maxDistanceMeters > Math.PI * EARTH_RADIUS_METERS) {\n throw new Error(\"addGeoNoise() maxDistance cannot exceed half the Earth's circumference.\");\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addGeoNoise()\",\n parameters: { maxDistance, options },\n needsSchema: true,\n needsSpatial: true,\n preservesSchema: true,\n buildSelect: (input, schema) => {\n const column =\n options.column ?? findGeoColumnFromSchema(schema, \"addGeoNoise()\", simpleTable.name);\n return addGeoNoiseSelect(\n input,\n schema,\n column,\n maxDistanceMeters,\n options.onlyDuplicates === true,\n );\n },\n });\n}\n\nfunction addGeoNoiseSelect(\n input: string,\n schema: TableSchema,\n column: string,\n maxDistanceMeters: number,\n onlyDuplicates: boolean,\n): string {\n const type = schema[column];\n if (type === undefined) {\n throw new Error(`addGeoNoise() could not find column ${quoteIdentifier(column)}.`);\n }\n if (type !== \"GEOMETRY('EPSG:4326')\") {\n throw new Error(\n `addGeoNoise() requires an EPSG:4326 geometry column, but ${quoteIdentifier(\n column,\n )} has type ${type}. Reproject it to EPSG:4326 first.`,\n );\n }\n\n const internalNames = makeInternalNames(schema, input);\n const quotedColumn = quoteIdentifier(column);\n const pointError = `error('addGeoNoise() requires POINT geometries in column ${column.replaceAll(\n \"'\",\n \"''\",\n )}.')`;\n const coordinateGuard = (coordinate: \"X\" | \"Y\") =>\n `CASE\n WHEN ${quotedColumn} IS NULL OR ST_IsEmpty(${quotedColumn}) THEN NULL\n WHEN CAST(ST_GeometryType(${quotedColumn}) AS VARCHAR) <> 'POINT'\n THEN ${pointError}\n ELSE radians(ST_${coordinate}(${quotedColumn}))\n END`;\n const duplicateCount = onlyDuplicates ? `COUNT(*) OVER (PARTITION BY ${quotedColumn})` : \"2\";\n const maxAngularDistance = maxDistanceMeters / EARTH_RADIUS_METERS;\n\n const latitudeExpression = `asin(\n sin(${quoteIdentifier(internalNames.latitude)}) * cos(${quoteIdentifier(\n internalNames.angularDistance,\n )}) +\n cos(${quoteIdentifier(internalNames.latitude)}) * sin(${quoteIdentifier(\n internalNames.angularDistance,\n )}) * cos(${quoteIdentifier(internalNames.bearing)})\n )`;\n const longitudeExpression = `${quoteIdentifier(internalNames.longitude)} + atan2(\n sin(${quoteIdentifier(internalNames.bearing)}) * sin(${quoteIdentifier(\n internalNames.angularDistance,\n )}) * cos(${quoteIdentifier(internalNames.latitude)}),\n cos(${quoteIdentifier(internalNames.angularDistance)}) -\n sin(${quoteIdentifier(internalNames.latitude)}) * sin(${quoteIdentifier(\n internalNames.destinationLatitude,\n )})\n )`;\n const replacement = `CASE\n WHEN ${quotedColumn} IS NULL OR ST_IsEmpty(${quotedColumn}) THEN ${quotedColumn}\n WHEN ${quoteIdentifier(internalNames.duplicateCount)} <= 1 THEN ${quotedColumn}\n ELSE ST_Point(\n degrees(atan2(\n sin(${quoteIdentifier(internalNames.destinationLongitude)}),\n cos(${quoteIdentifier(internalNames.destinationLongitude)})\n )),\n degrees(${quoteIdentifier(internalNames.destinationLatitude)})\n )::GEOMETRY('EPSG:4326')\n END AS ${quotedColumn}`;\n const outputColumns = Object.keys(schema)\n .map((outputColumn) => (outputColumn === column ? replacement : quoteIdentifier(outputColumn)))\n .join(\", \");\n\n return `WITH ${quoteIdentifier(internalNames.randomValues)} AS MATERIALIZED (\n SELECT *,\n random() AS ${quoteIdentifier(internalNames.distanceRandom)},\n random() AS ${quoteIdentifier(internalNames.bearingRandom)},\n ${duplicateCount} AS ${quoteIdentifier(internalNames.duplicateCount)}\n FROM ${input}\n ),\n ${quoteIdentifier(internalNames.start)} AS (\n SELECT *,\n ${coordinateGuard(\"Y\")} AS ${quoteIdentifier(internalNames.latitude)},\n ${coordinateGuard(\"X\")} AS ${quoteIdentifier(internalNames.longitude)},\n 2 * pi() * ${quoteIdentifier(internalNames.bearingRandom)} AS ${quoteIdentifier(\n internalNames.bearing,\n )},\n 2 * asin(\n sqrt(${quoteIdentifier(internalNames.distanceRandom)}) *\n sin(${maxAngularDistance} / 2)\n ) AS ${quoteIdentifier(internalNames.angularDistance)}\n FROM ${quoteIdentifier(internalNames.randomValues)}\n ),\n ${quoteIdentifier(internalNames.destinationLatitudeCte)} AS (\n SELECT *, ${latitudeExpression} AS ${quoteIdentifier(internalNames.destinationLatitude)}\n FROM ${quoteIdentifier(internalNames.start)}\n ),\n ${quoteIdentifier(internalNames.destination)} AS (\n SELECT *, ${longitudeExpression} AS ${quoteIdentifier(internalNames.destinationLongitude)}\n FROM ${quoteIdentifier(internalNames.destinationLatitudeCte)}\n )\n SELECT ${outputColumns}\n FROM ${quoteIdentifier(internalNames.destination)}`;\n}\n\nfunction makeInternalNames(schema: TableSchema, input: string) {\n const used = new Set(Object.keys(schema));\n if (input.startsWith('\"') && input.endsWith('\"')) {\n used.add(input.slice(1, -1).replaceAll('\"\"', '\"'));\n }\n const next = (base: string) => {\n let name = base;\n let suffix = 2;\n while (used.has(name)) {\n name = `${base}_${suffix++}`;\n }\n used.add(name);\n return name;\n };\n\n return {\n randomValues: next(\"__sda_add_geo_noise_random_values\"),\n start: next(\"__sda_add_geo_noise_start\"),\n destinationLatitudeCte: next(\"__sda_add_geo_noise_latitude_result\"),\n destination: next(\"__sda_add_geo_noise_result\"),\n distanceRandom: next(\"__sda_add_geo_noise_distance_random\"),\n bearingRandom: next(\"__sda_add_geo_noise_bearing_random\"),\n duplicateCount: next(\"__sda_add_geo_noise_duplicate_count\"),\n latitude: next(\"__sda_add_geo_noise_latitude\"),\n longitude: next(\"__sda_add_geo_noise_longitude\"),\n bearing: next(\"__sda_add_geo_noise_bearing\"),\n angularDistance: next(\"__sda_add_geo_noise_angular_distance\"),\n destinationLatitude: next(\"__sda_add_geo_noise_destination_latitude\"),\n destinationLongitude: next(\"__sda_add_geo_noise_destination_longitude\"),\n };\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function flipCoordinates(simpleTable: SimpleTable, column?: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"flipCoordinates()\",\n parameters: { column },\n needsSchema: true,\n needsSpatial: true,\n // The cast pins the geometry column back to its existing type, so the\n // schema is unchanged.\n preservesSchema: true,\n buildSelect: (input, types) => {\n const col = column ?? findGeoColumnFromSchema(types, \"flipCoordinates()\", simpleTable.name);\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n return `SELECT * REPLACE (ST_FlipCoordinates(${quoteIdentifier(col)})::${\n types[col]\n } AS ${quoteIdentifier(col)}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addGeoType(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addGeoType()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addGeoType()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"addGeoType()\", simpleTable.name);\n return `SELECT *, CAST(ST_GeometryType(${quoteIdentifier(\n column,\n )}) AS VARCHAR) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addGeoClosedStatus(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addGeoClosedStatus()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addGeoClosedStatus()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"addGeoClosedStatus()\", simpleTable.name);\n return `SELECT *, CAST(ST_IsClosed(${quoteIdentifier(\n column,\n )}) AS BOOLEAN) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function fixGeo(simpleTable: SimpleTable, column?: string) {\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"fixGeo()\",\n parameters: { column },\n needsSchema: true,\n needsSpatial: true,\n // The cast pins the geometry column back to its existing type, so the\n // schema is unchanged.\n preservesSchema: true,\n buildSelect: (input, types) => {\n const col = column ?? findGeoColumnFromSchema(types, \"fixGeo()\", simpleTable.name);\n // The schema type carries the projection (e.g. GEOMETRY('EPSG:4326')),\n // so the cast keeps it on the new geometries.\n return `SELECT * REPLACE (ST_MakeValid(${quoteIdentifier(col)})::${\n types[col]\n } AS ${quoteIdentifier(col)}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addVertexCount(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { column?: string } = {},\n) {\n options = { ...options };\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addVertexCount()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addVertexCount()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"addVertexCount()\", simpleTable.name);\n return `SELECT *, CAST(ST_NPoints(${quoteIdentifier(\n column,\n )}) AS BIGINT) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport findGeoColumnFromSchema from \"../helpers/findGeoColumnFromSchema.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addGeoValidity(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { column?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addGeoValidity()\",\n parameters: { newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addGeoValidity()\");\n const column =\n typeof options.column === \"string\"\n ? options.column\n : findGeoColumnFromSchema(types, \"addGeoValidity()\", simpleTable.name);\n return `SELECT *, CAST(ST_IsValid(${quoteIdentifier(\n column,\n )}) AS BOOLEAN) AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function createPoints(\n simpleTable: SimpleTable,\n latColumn: string,\n lonColumn: string,\n newColumn: string,\n options: { projection?: string } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"createPoints()\",\n parameters: { latColumn, lonColumn, newColumn, options },\n needsSchema: true,\n needsSpatial: true,\n outputSchema: (types) => ({\n ...types,\n [newColumn]: `GEOMETRY('${options.projection ?? \"EPSG:4326\"}')`,\n }),\n buildSelect: (input, types) => {\n const expression = `ST_Point(${quoteIdentifier(lonColumn)}, ${quoteIdentifier(\n latColumn,\n )})::GEOMETRY(${parseValue(options.projection ?? \"EPSG:4326\")})`;\n return Object.keys(types).includes(newColumn)\n ? `SELECT * REPLACE (${expression} AS ${quoteIdentifier(newColumn)}) FROM ${input}`\n : `SELECT *, ${expression} AS ${quoteIdentifier(newColumn)} FROM ${input}`;\n },\n });\n}\n","import cleanSQL from \"../helpers/cleanSQL.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport { makeConverter } from \"../helpers/runQuery.ts\";\nimport SDAError from \"../class/SDAError.ts\";\nimport flushAllTables from \"../helpers/flushAllTables.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport observeQuery from \"../helpers/observeQuery.ts\";\n\nexport default async function* stream(\n simpleTable: SimpleTable,\n options: {\n columns?: string | string[];\n conditions?: string;\n } = {},\n): AsyncGenerator<{ [key: string]: unknown }, void, undefined> {\n if (simpleTable.connection === undefined) {\n await simpleTable.sdb.start();\n simpleTable.db = simpleTable.sdb.db;\n simpleTable.connection = simpleTable.sdb.connection;\n }\n\n // stream() reads directly from the connection instead of going through\n // queryDB, so it must flush the pending chains itself before yielding.\n await flushAllTables(simpleTable.sdb);\n\n const columns = options.columns\n ? typeof options.columns === \"string\"\n ? [options.columns]\n : options.columns\n : undefined;\n const query = cleanSQL(\n `SELECT ${\n columns ? columns.map((d) => `${quoteIdentifier(d)}`).join(\", \") : \"*\"\n } FROM ${quoteIdentifier(simpleTable.name)}${\n options.conditions ? ` WHERE ${options.conditions}` : \"\"\n };`,\n simpleTable.sdb.expressionSyntax,\n );\n try {\n await observeQuery(simpleTable.connection, query, [], {\n logSQL: simpleTable.sdb.logSQL,\n explainSQL: simpleTable.sdb.explainSQL,\n });\n const result = await simpleTable.connection.stream(query);\n const columnNames = result.deduplicatedColumnNames();\n const columnTypes = result.columnTypes();\n if (columnTypes.some((type) => type.toString().toLowerCase().includes(\"geometry\"))) {\n throw new Error(\"The query returns geometry columns. Use getGeoData() instead.\");\n }\n const converters = columnTypes.map((type, i) =>\n makeConverter(type, columnNames[i], simpleTable.name),\n );\n const columnCount = columnNames.length;\n\n while (true) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) {\n break;\n }\n for (const rawRow of chunk.getRows()) {\n const row: { [key: string]: unknown } = {};\n for (let i = 0; i < columnCount; i++) {\n row[columnNames[i]] = converters[i](rawRow[i]);\n }\n yield row;\n }\n }\n } catch (error) {\n if (error instanceof SDAError) {\n throw error;\n }\n throw new SDAError({\n method: \"stream()\",\n parameters: { options },\n query,\n cause: error,\n });\n }\n}\n","import {\n DuckDBArrayValue,\n type DuckDBConnection,\n DuckDBDateValue,\n DuckDBListValue,\n DuckDBStructValue,\n DuckDBTimestampValue,\n type DuckDBType,\n type DuckDBValue,\n} from \"@duckdb/node-api\";\n\n/** Reads mutation values, optionally keeping a pagination cursor out of rows. */\nexport default async function readMutationRows(\n connection: DuckDBConnection,\n query: string,\n cursorColumn?: string,\n) {\n const result = await connection.run(query);\n const names = result.deduplicatedColumnNames();\n const types = result.columnTypes();\n const cursorIndex = cursorColumn === undefined ? -1 : names.indexOf(cursorColumn);\n let lastCursorValue: DuckDBValue | undefined;\n const dates = new WeakMap<Date, { millis: number; value: DuckDBValue }>();\n const convert = (value: DuckDBValue): unknown => {\n if (value instanceof DuckDBDateValue || value instanceof DuckDBTimestampValue) {\n const millis =\n value instanceof DuckDBDateValue\n ? value.days * 86400000\n : Number(value.micros >= 0n ? value.micros / 1000n : (value.micros - 999n) / 1000n);\n const date = new Date(millis);\n // Infinite/out-of-range dates retain their native representation.\n if (!Number.isFinite(date.getTime())) return value;\n dates.set(date, { millis, value });\n return date;\n }\n if (value instanceof DuckDBArrayValue || value instanceof DuckDBListValue) {\n return value.items.map(convert);\n }\n if (value instanceof DuckDBStructValue) {\n return Object.fromEntries(\n Object.entries(value.entries).map(([key, item]) => [key, convert(item)]),\n );\n }\n // In particular, decimals and high-resolution temporal values stay native.\n return value;\n };\n const rows: Record<string, unknown>[] = [];\n while (true) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const offset = rows.length;\n for (let i = 0; i < chunk.rowCount; i++) rows.push({});\n for (let i = 0; i < names.length; i++) {\n if (i === cursorIndex) {\n lastCursorValue = chunk.getColumnVector(i).getItem(chunk.rowCount - 1);\n continue;\n }\n chunk.visitColumnValues(i, (value, row) => {\n rows[offset + row][names[i]] = convert(value);\n });\n }\n }\n const toNative = (value: unknown, type: DuckDBType): DuckDBValue => {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) {\n const original = dates.get(value);\n if (\n original &&\n value.getTime() === original.millis &&\n type.toString() === (original.value instanceof DuckDBDateValue ? \"DATE\" : \"TIMESTAMP\")\n ) {\n return original.value;\n }\n if (type.toString() === \"DATE\") {\n if (value.getTime() % 86400000 !== 0) {\n throw new Error(\"DATE values must represent midnight UTC.\");\n }\n return new DuckDBDateValue(value.getTime() / 86400000);\n }\n return new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n);\n }\n if (Array.isArray(value) && \"valueType\" in type) {\n if (\"length\" in type && value.length !== type.length) {\n throw new Error(`Expected ${type.length} array elements for ${type.toString()}.`);\n }\n const items = value.map((item: unknown) => toNative(item, type.valueType));\n return \"length\" in type ? new DuckDBArrayValue(items) : new DuckDBListValue(items);\n }\n if (typeof value === \"object\" && \"entryNames\" in type && \"entryTypes\" in type) {\n return new DuckDBStructValue(\n Object.fromEntries(\n type.entryNames.map((name, i) => [\n name,\n toNative((value as Record<string, unknown>)[name], type.entryTypes[i]),\n ]),\n ),\n );\n }\n return value as DuckDBValue;\n };\n return {\n rows,\n types: new Map(names.flatMap((name, i) => (i === cursorIndex ? [] : [[name, types[i]]]))),\n lastCursorValue,\n toNative,\n };\n}\n","import prepareGeometry from \"../helpers/prepareGeometry.ts\";\nimport geometryFromJSON from \"../helpers/geometryFromJSON.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { retainRegisteredTables } from \"../helpers/tableRegistry.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport { prepareArray } from \"./loadArray.ts\";\nimport appendColumnBatches from \"../helpers/appendColumnBatches.ts\";\nimport readMutationRows from \"../helpers/readMutationRows.ts\";\nimport parseDuckDBType from \"../helpers/parseDuckDBType.ts\";\n\ntype Row = { [key: string]: unknown };\n\ntype DataModifier = (rows: Row[]) => Row[] | Promise<Row[]>;\n\ntype UpdateWithJSOptions = NonNullable<Parameters<SimpleTable[\"updateWithJS\"]>[1]>;\n\nexport default function updateWithJS(\n simpleTable: SimpleTable,\n dataModifier: DataModifier,\n options: UpdateWithJSOptions = {},\n): void {\n if (\n options.batchSize !== undefined &&\n (!Number.isInteger(options.batchSize) || options.batchSize < 1)\n ) {\n throw new Error(\"updateWithJS() batchSize must be a positive integer.\");\n }\n\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"updateWithJS()\",\n parameters: { options },\n execute: () => executeUpdateWithJS(simpleTable, dataModifier, options),\n });\n}\n\nasync function executeUpdateWithJS(\n simpleTable: SimpleTable,\n dataModifier: DataModifier,\n options: UpdateWithJSOptions,\n): Promise<void> {\n const types = await simpleTable.getTypes();\n const geometryColumns = Object.keys(types).filter((key) =>\n types[key].toUpperCase().startsWith(\"GEOMETRY\"),\n );\n for (const column of geometryColumns) {\n if (types[column].toUpperCase() !== \"GEOMETRY('EPSG:4326')\") {\n throw new Error(\n `Column ${JSON.stringify(column)} has CRS ${\n types[column]\n }. Call .reproject(\"EPSG:4326\", { column: ${JSON.stringify(\n column,\n )} }) before updateWithJS().`,\n );\n }\n const name = quoteIdentifier(column);\n // Compare the actual binary representation, including dimensions and double\n // precision, rather than assuming GeoJSON serialization is lossless.\n const result = await simpleTable.connection!.runAndReadAll(\n `SELECT count(*) AS invalid FROM ${quoteIdentifier(simpleTable.name)}\n WHERE ${name} IS NOT NULL AND\n ST_AsWKB(${name}) != ST_AsWKB(${geometryFromJSON(`ST_AsGeoJSON(${name})`)})`,\n );\n if (result.getRows()[0][0] !== 0n) {\n throw new Error(\n `Column ${JSON.stringify(\n column,\n )} contains geometry that cannot round-trip through GeoJSON without losing precision or dimensions; unsupported representations cannot be updated with updateWithJS().`,\n );\n }\n }\n for (const key of Object.keys(options.columnTypes ?? {})) {\n if (Object.keys(types).some((name) => name.toLowerCase() === key.toLowerCase())) {\n throw new Error(\n `updateWithJS() columnTypes may only declare new columns; ${JSON.stringify(\n key,\n )} already exists.`,\n );\n }\n }\n\n const batchSize = options.batchSize;\n const geometryBatch = batchSize !== undefined && geometryColumns.length > 0;\n if (batchSize !== undefined) {\n // DuckDB resolves identifiers case-insensitively, and a real rowid column\n // shadows its hidden row identifier used for pagination.\n const conflictingColumn = Object.keys(types).find((column) =>\n [\"rowid\", \"__sda_rowid\"].includes(column.toLowerCase()),\n );\n if (conflictingColumn !== undefined) {\n throw new Error(\n `The table has a column named \"${conflictingColumn}\", which conflicts with the internal column used by the batchSize option. Rename it or run updateWithJS without batchSize.`,\n );\n }\n }\n\n // Rows are pulled in batches by rowid, passed through the modifier, and\n // accumulated in a temporary table, so only one batch of rows is\n // materialized in JS memory at a time.\n const suffix = Math.random().toString(36).slice(2, 10);\n const scratch = simpleTable.sdb.newTable(`updateWithJS_scratch_${suffix}`);\n const accumulator = `updateWithJS_accumulator_${suffix}`;\n\n try {\n let first = true;\n let accumulatorSchema: string | undefined;\n let lastRowid: bigint | null = null;\n let sawRows = false;\n let outputOffset = 0;\n let inputOffset = 0;\n\n while (true) {\n const page = `${quoteIdentifier(simpleTable.name)}${\n lastRowid === null ? \"\" : ` WHERE rowid > ${lastRowid}`\n }${batchSize === undefined ? \"\" : ` ORDER BY rowid LIMIT ${batchSize}`}`;\n // Select the batch before serializing geometry. Otherwise DuckDB can\n // evaluate ST_AsGeoJSON on remaining rows before applying the LIMIT,\n // repeatedly converting polygons that belong to later batches.\n const from = geometryBatch\n ? `(SELECT *, rowid AS __sda_rowid FROM ${page}) AS __sda_batch ORDER BY __sda_rowid`\n : page;\n const source = await readMutationRows(\n simpleTable.connection!,\n `SELECT ${Object.keys(types)\n .map((key) =>\n geometryColumns.includes(key)\n ? `ST_AsGeoJSON(${quoteIdentifier(key)})::VARCHAR AS ${quoteIdentifier(key)}`\n : quoteIdentifier(key),\n )\n .join(\", \")}${\n batchSize === undefined ? \"\" : geometryBatch ? \", __sda_rowid\" : \", rowid AS __sda_rowid\"\n } FROM ${from}`,\n batchSize === undefined ? undefined : \"__sda_rowid\",\n );\n const batch = source.rows;\n const inputCount = batch.length;\n if (inputCount === 0 && sawRows) break;\n sawRows ||= inputCount > 0;\n if (batchSize !== undefined && batch.length > 0) {\n // Keep the cursor separate: adding and deleting it on every row also\n // makes ordinary callback operations such as object spread slower.\n lastRowid = source.lastCursorValue as bigint;\n }\n\n for (const [index, row] of batch.entries()) {\n for (const key of geometryColumns) {\n row[key] = row[key] === null ? null : JSON.parse(row[key] as string);\n prepareGeometry(row[key], key, inputOffset + index + 1);\n }\n }\n inputOffset += inputCount;\n const modified = await dataModifier(batch);\n if (modified.length === 0) {\n if (!sawRows) return;\n if (batchSize === undefined) break;\n continue;\n }\n const keys = Object.keys(modified[0]);\n for (const key of Object.keys(options.columnTypes ?? {})) {\n if (!keys.includes(key)) {\n throw new Error(`Unknown column ${JSON.stringify(key)} in updateWithJS columnTypes.`);\n }\n }\n const newKeys = keys.filter((key) => !source.types.has(key));\n const added =\n newKeys.length === 0\n ? undefined\n : prepareArray(\n modified.map((row) => Object.fromEntries(newKeys.map((key) => [key, row[key]]))),\n options.columnTypes,\n );\n const outputGeometry = keys.filter(\n (key) =>\n geometryColumns.includes(key) ||\n (added && added.types[newKeys.indexOf(key)] === \"GEOMETRY('EPSG:4326')\"),\n );\n const outputJSON = keys.filter(\n (key) => types[key] === \"JSON\" || (added && added.types[newKeys.indexOf(key)] === \"JSON\"),\n );\n if (outputGeometry.length && !simpleTable.sdb.spatialLoaded) {\n await simpleTable.sdb.customQuery(\n \"INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\",\n );\n simpleTable.sdb.spatialLoaded = true;\n }\n const geometryData = new Map(\n outputGeometry.map((key) => [\n key,\n geometryColumns.includes(key)\n ? modified.map((row, i) => prepareGeometry(row[key], key, outputOffset + i + 1))\n : added!.columnsData[newKeys.indexOf(key)],\n ]),\n );\n outputOffset += modified.length;\n const columnTypes = keys.map((key) =>\n outputGeometry.includes(key) || outputJSON.includes(key)\n ? parseDuckDBType(\"VARCHAR\")\n : (source.types.get(key) ?? parseDuckDBType(added!.types[newKeys.indexOf(key)])),\n );\n const schema = JSON.stringify(keys.map((key, i) => [key, columnTypes[i].toString()]));\n // Append matching native batches directly. SQL still handles conversion\n // and BY NAME alignment when a callback changes the batch schema.\n const direct =\n outputGeometry.length === 0 &&\n outputJSON.length === 0 &&\n (first || schema === accumulatorSchema);\n const destination = direct ? accumulator : scratch.name;\n if (!direct || first) {\n await simpleTable.sdb.customQuery(\n `CREATE OR REPLACE TABLE ${quoteIdentifier(destination)} (${keys\n .map((key, i) => `${quoteIdentifier(key)} ${columnTypes[i].toString()}`)\n .join(\", \")})`,\n );\n }\n await appendColumnBatches(\n simpleTable.connection!,\n destination,\n columnTypes,\n modified.length,\n (column, start, end) => {\n const key = keys[column];\n return outputGeometry.includes(key)\n ? geometryData.get(key)!.slice(start, end)\n : source.types.has(key)\n ? modified\n .slice(start, end)\n .map((row) => source.toNative(row[key], columnTypes[column]))\n : added!.columnsData[newKeys.indexOf(key)].slice(start, end);\n },\n );\n const projection = keys\n .map((key) =>\n outputGeometry.includes(key)\n ? `${geometryFromJSON(quoteIdentifier(key))} AS ${quoteIdentifier(key)}`\n : outputJSON.includes(key)\n ? `${quoteIdentifier(key)}::JSON AS ${quoteIdentifier(key)}`\n : quoteIdentifier(key),\n )\n .join(\", \");\n if (direct) {\n accumulatorSchema = schema;\n first = false;\n } else if (first) {\n await simpleTable.sdb.customQuery(\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n accumulator,\n )} AS SELECT ${projection} FROM ${quoteIdentifier(scratch.name)}`,\n );\n first = false;\n } else {\n await simpleTable.sdb.customQuery(\n `INSERT INTO ${quoteIdentifier(\n accumulator,\n )} BY NAME SELECT ${projection} FROM ${quoteIdentifier(scratch.name)}`,\n );\n }\n if (batchSize === undefined || inputCount === 0) break;\n }\n\n if (first) {\n throw new Error(\n \"The dataModifier returned no rows. updateWithJS can't infer the table schema from zero rows.\",\n );\n }\n\n // Publish the completed ordinary table without copying its rows again.\n // Qualify the creation namespace: a temporary table or a later search-path\n // schema can shadow the name without being the destination of replacement.\n const namespace = await simpleTable.connection!.runAndReadAll(\n \"SELECT current_database(), current_schema()\",\n );\n const prefix = namespace\n .getRows()[0]\n .map((name) => quoteIdentifier(String(name)))\n .join(\".\");\n await simpleTable.sdb.customQuery(\n `DROP TABLE IF EXISTS ${prefix}.${quoteIdentifier(simpleTable.name)};\nALTER TABLE ${prefix}.${quoteIdentifier(accumulator)} RENAME TO ${quoteIdentifier(\n simpleTable.name,\n )};`,\n );\n } finally {\n await simpleTable.sdb.customQuery(\n `DROP TABLE IF EXISTS ${quoteIdentifier(accumulator)};\nDROP TABLE IF EXISTS ${quoteIdentifier(scratch.name)};`,\n );\n retainRegisteredTables(simpleTable.sdb, (table) => table !== scratch);\n }\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default async function getSchema(simpleTable: SimpleTable) {\n return (await queryDB(\n simpleTable,\n `DESCRIBE ${quoteIdentifier(simpleTable.name)}`,\n mergeOptions(simpleTable, {\n returnData: true,\n rowsToLog: Infinity,\n table: simpleTable.name,\n method: \"getSchema()\",\n parameters: {},\n }),\n )) as {\n [key: string]: string | null;\n }[];\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function outliersIQR(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n) {\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"outliersIQR()\",\n parameters: { column, newColumn, options },\n needsSchema: false,\n buildSelect: (input) => outliersIQRSelect(input, column, newColumn, options),\n });\n}\n\nfunction outliersIQRSelect(\n input: string,\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n) {\n const by = options.by ? stringToArray(options.by).map((d) => `${quoteIdentifier(d)}`) : [];\n\n const partition = by.length > 0 ? `PARTITION BY ${by.join(\", \")}` : \"\";\n const quantile = (fraction: number) =>\n `IF(COUNT(${quoteIdentifier(column)}) OVER (${partition}) % 2 = 0,\n quantile_disc(${quoteIdentifier(column)}, ${fraction}) OVER (${partition}),\n quantile_cont(${quoteIdentifier(column)}, ${fraction}) OVER (${partition})\n )`;\n\n // q1/q3 are computed as window values (one pass) instead of a per-category\n // CTE joined back through a correlated subquery per row.\n return `SELECT * EXCLUDE (\"_sda_q1\", \"_sda_q3\"), CASE\n WHEN ${quoteIdentifier(column)} > \"_sda_q3\" + (\"_sda_q3\" - \"_sda_q1\") * 1.5\n OR ${quoteIdentifier(column)} < \"_sda_q1\" - (\"_sda_q3\" - \"_sda_q1\") * 1.5\n THEN TRUE\n ELSE FALSE\n END AS ${quoteIdentifier(newColumn)}\n FROM (\n SELECT *,\n ${quantile(0.25)} AS \"_sda_q1\",\n ${quantile(0.75)} AS \"_sda_q3\"\n FROM ${input}\n ) \"_sda\"`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function bins(\n simpleTable: SimpleTable,\n column: string,\n interval: number,\n startColumn: string,\n endColumn: string,\n options: {\n startValue?: number;\n } = {},\n) {\n // This validation does not need the database, so it stays at call time.\n if (!Number.isFinite(interval) || interval <= 0) {\n throw new Error(\"bins() interval must be a finite number greater than 0.\");\n }\n if (typeof startColumn !== \"string\" || typeof endColumn !== \"string\") {\n throw new Error(\"bins() requires start and end output column names.\");\n }\n if (startColumn.toLowerCase() === endColumn.toLowerCase()) {\n throw new Error(\"bins() start and end output column names must be distinct.\");\n }\n if (options.startValue !== undefined && !Number.isFinite(options.startValue)) {\n throw new Error(\"bins() startValue must be a finite number.\");\n }\n // The intervals depend on the minimum and maximum values of the data, so\n // bins can't be expressed as a single SELECT over its input: it executes\n // as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"bins()\",\n parameters: { column, interval, startColumn, endColumn, options },\n execute: async () => {\n await queryDB(\n simpleTable,\n await binsQuery(simpleTable, column, interval, startColumn, endColumn, options),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"bins()\",\n parameters: {\n column,\n interval,\n startColumn,\n endColumn,\n options,\n },\n }),\n );\n },\n });\n}\n\nasync function binsQuery(\n SimpleTable: SimpleTable,\n column: string,\n interval: number,\n startColumn: string,\n endColumn: string,\n options: {\n startValue?: number;\n } = {},\n) {\n // A SELECT *, expr AS col colliding with an existing column would be\n // silently renamed by DuckDB (col -> col_1) instead of erroring, unlike\n // the ALTER TABLE ADD this used to run.\n const types = await SimpleTable.getTypes();\n const existingColumns = Object.keys(types);\n assertNewColumns(\n types,\n [startColumn, endColumn].map(\n (column) =>\n existingColumns.find((existing) => existing.toLowerCase() === column.toLowerCase()) ??\n column,\n ),\n \"bins()\",\n );\n\n // The minimum and maximum are computed in one scan instead of one\n // getMin/getMax query each.\n const minMax = await queryDB(\n SimpleTable,\n `SELECT MIN(${quoteIdentifier(column)}) AS \"min\", MAX(${quoteIdentifier(\n column,\n )}) AS \"max\" FROM ${quoteIdentifier(SimpleTable.name)}`,\n mergeOptions(SimpleTable, {\n table: SimpleTable.name,\n method: \"bins()\",\n parameters: { column, interval, startColumn, endColumn, options },\n returnData: true,\n }),\n );\n const minValue = minMax?.[0]?.min;\n if (typeof minValue !== \"number\" || !Number.isFinite(minValue)) {\n throw new Error(`minValue of ${column} is not a finite number`);\n }\n\n let startValue: number;\n if (typeof options.startValue === \"number\") {\n if (options.startValue > minValue) {\n throw new Error(\n `startValue ${options.startValue} can't be greater than minValue ${minValue}`,\n );\n }\n startValue = options.startValue;\n } else {\n startValue = minValue;\n }\n\n const maxValue = minMax?.[0]?.max;\n if (typeof maxValue !== \"number\" || !Number.isFinite(maxValue)) {\n throw new Error(`maxValue of ${column} is not a finite number`);\n }\n const starts: string[] = [];\n const ends: string[] = [];\n // Include the bin beginning at the maximum, even if floating-point division\n // places an exact boundary slightly below its integer index.\n const lastBin = Math.ceil((maxValue - startValue) / interval);\n if (!Number.isSafeInteger(lastBin)) {\n throw new Error(\"bins() range contains too many intervals.\");\n }\n for (let i = 0; i <= lastBin; i++) {\n // Let SQL evaluate the boundaries from numeric literals, avoiding repeated\n // floating-point addition in JavaScript for fractional intervals.\n // Decimal indices also prevent integer-only expressions from overflowing\n // DuckDB's inferred INT32 type when an end exceeds that range.\n const start = `(${startValue} + ${i}.0 * ${interval})`;\n const end = `(${startValue} + ${i + 1}.0 * ${interval})`;\n const condition = `WHEN ${quoteIdentifier(column)} >= ${start} AND ${quoteIdentifier(\n column,\n )} < ${end}`;\n starts.push(`${condition} THEN ${start}`);\n ends.push(`${condition} THEN ${end}`);\n }\n\n // Keep both outputs numeric, including fractional boundaries. Null source\n // values match no interval and yield null in both output columns.\n const query = `CREATE OR REPLACE TABLE ${quoteIdentifier(SimpleTable.name)} AS\n SELECT *,\n CAST(CASE ${starts.join(\"\\n\")} END AS DOUBLE) AS ${quoteIdentifier(startColumn)},\n CAST(CASE ${ends.join(\"\\n\")} END AS DOUBLE) AS ${quoteIdentifier(endColumn)}\n FROM ${quoteIdentifier(SimpleTable.name)}`;\n\n return query;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function round(\n simpleTable: SimpleTable,\n columns: string | string[],\n options:\n | number\n | {\n decimals?: number;\n method?: \"round\" | \"ceiling\" | \"floor\";\n } = {},\n) {\n const optionsNormalized = typeof options === \"number\" ? { decimals: options } : options;\n const cols = stringToArray(columns);\n const method = optionsNormalized.method?.toUpperCase() ?? \"ROUND\";\n const decimals = optionsNormalized.decimals ?? 0;\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"round()\",\n parameters: { columns, options },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * REPLACE (${cols\n .map((c) =>\n method === \"ROUND\"\n ? `${method}(${quoteIdentifier(c)}, ${decimals}) AS ${quoteIdentifier(c)}`\n : `${method}(${quoteIdentifier(c)}) AS ${quoteIdentifier(c)}`,\n )\n .join(\", \")}) FROM ${input}`,\n });\n}\n","import assertColumnsExist from \"../helpers/assertColumnsExist.ts\";\nimport keepNumericalColumns from \"../helpers/keepNumericalColumns.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addNoise(\n simpleTable: SimpleTable,\n columns: string | string[],\n max: number,\n options: { onlyDuplicates?: boolean } = {},\n) {\n // This validation doesn't need the database, so it stays at call time.\n if (!Number.isFinite(max) || max < 0) {\n throw new Error(\"addNoise() max must be a finite number greater than or equal to 0.\");\n }\n\n const cols = stringToArray(columns);\n if (cols.length === 0) {\n throw new Error(\"addNoise() requires at least one column.\");\n }\n const duplicateColumns = cols.filter((column, index) => cols.indexOf(column) !== index);\n if (duplicateColumns.length > 0) {\n const duplicates = [...new Set(duplicateColumns)];\n throw new Error(\n `addNoise() received duplicate column${duplicates.length === 1 ? \"\" : \"s\"} ${duplicates\n .map(quoteIdentifier)\n .join(\", \")}. Include each column only once.`,\n );\n }\n\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addNoise()\",\n parameters: { columns: cols, max, options },\n needsSchema: true,\n outputSchema: (schema) => ({\n ...schema,\n ...Object.fromEntries(cols.map((column) => [column, \"DOUBLE\"])),\n }),\n buildSelect: (input, schema) =>\n addNoiseSelect(input, schema, cols, max, options.onlyDuplicates === true),\n });\n}\n\nfunction addNoiseSelect(\n input: string,\n schema: TableSchema,\n columns: string[],\n max: number,\n onlyDuplicates: boolean,\n): string {\n assertColumnsExist(schema, columns, \"addNoise()\");\n\n const numericalColumns = new Set(keepNumericalColumns(schema));\n const nonNumericalColumns = columns.filter((column) => !numericalColumns.has(column));\n if (nonNumericalColumns.length > 0) {\n throw new Error(\n `addNoise() requires numeric columns, but ${nonNumericalColumns\n .map((column) => `${quoteIdentifier(column)} has type ${schema[column]}`)\n .join(\", \")}. Convert ${\n nonNumericalColumns.length === 1 ? \"it\" : \"them\"\n } to a numeric type first.`,\n );\n }\n\n const replacements = columns\n .map((column) => {\n const quotedColumn = quoteIdentifier(column);\n const duplicateCondition = onlyDuplicates\n ? `COUNT(*) OVER (PARTITION BY ${quotedColumn}) > 1`\n : \"TRUE\";\n return `CASE\n WHEN ${quotedColumn} IS NULL THEN NULL\n WHEN ${duplicateCondition}\n THEN CAST(${quotedColumn} AS DOUBLE) + (random() * 2 - 1) * ${max}\n ELSE CAST(${quotedColumn} AS DOUBLE)\n END AS ${quotedColumn}`;\n })\n .join(\", \");\n\n return `SELECT * REPLACE (${replacements}) FROM ${input}`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function rowToText(simpleTable: SimpleTable, columns: string[], newColumn: string) {\n columns = [...columns];\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"rowToText()\",\n parameters: { columns, newColumn },\n needsSchema: true,\n values: columns.flatMap((col, i) => [`${i === 0 ? \"\" : \"\\n\\n\"}${col}:\\n`, \"Unknown\"]),\n buildSelect: (input, allTypes) => {\n assertNewColumns(allTypes, [newColumn], \"rowToText()\");\n for (const col of columns) {\n if (allTypes[col] !== \"VARCHAR\") {\n throw new Error(\n `The column ${col} is of type ${\n allTypes[col]\n }. The rowToText() method only works with string columns. Please convert the column to string first with the .convert() method.`,\n );\n }\n }\n\n const parts = columns.map((col) => `concat(?, COALESCE(${quoteIdentifier(col)}, ?))`);\n const concatenatedExpression = `concat(${parts.join(\", \")})`;\n\n return `SELECT *, CAST(${concatenatedExpression} AS VARCHAR) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport foldIdentifier from \"../helpers/foldIdentifier.ts\";\nimport { isNumericScalarType } from \"../helpers/prepareNumericFeatures.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\nexport default function rowToVector(\n table: SimpleTable,\n columns: string[],\n newColumn: string,\n options: { type?: \"float\" | \"double\" } = {},\n) {\n if (columns.length === 0) {\n throw new Error(\"rowToVector() requires at least one numeric scalar input column.\");\n }\n const duplicate = findDuplicate(columns);\n if (duplicate !== undefined) {\n throw new Error(\n `rowToVector() received duplicate input column ${quoteIdentifier(\n duplicate,\n )}. Each input column must be listed once.`,\n );\n }\n if (options.type !== undefined && ![\"float\", \"double\"].includes(options.type)) {\n throw new Error('rowToVector() options.type must be \"float\" or \"double\".');\n }\n\n columns = [...columns];\n options = structuredClone(options);\n queueOp(table, {\n kind: \"fusable\",\n method: \"rowToVector()\",\n parameters: { columns, newColumn, options },\n needsSchema: true,\n outputSchema: (schema) => ({\n ...schema,\n [newColumn]: `${resolveElementType(schema, columns, newColumn, options)}[${columns.length}]`,\n }),\n buildSelect: (input, schema) => {\n const elementType = resolveElementType(schema, columns, newColumn, options);\n const resolved = resolveColumns(schema, columns);\n return `SELECT *, [${resolved\n .map((column) => {\n const value = quoteIdentifier(column);\n // DuckDB does not implement a direct BIGNUM-to-FLOAT cast.\n const convertible =\n schema[column] === \"BIGNUM\" && elementType === \"FLOAT\" ? `${value}::VARCHAR` : value;\n return `${convertible}::${elementType}`;\n })\n .join(\", \")}]::${elementType}[${columns.length}] AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n\nfunction resolveElementType(\n schema: TableSchema,\n columns: string[],\n newColumn: string,\n options: { type?: \"float\" | \"double\" },\n): string {\n const existingOutput = Object.keys(schema).find(\n (column) => foldIdentifier(column) === foldIdentifier(newColumn),\n );\n if (existingOutput !== undefined) {\n throw new Error(\n `rowToVector() the column ${quoteIdentifier(\n newColumn,\n )} already exists. Remove it first or choose a different name for the new column.`,\n );\n }\n const resolved = resolveColumns(schema, columns);\n const nonNumeric = resolved.filter((column) => !isNumericScalarType(schema[column]));\n if (nonNumeric.length > 0) {\n throw new Error(\n `rowToVector() requires numeric scalar input columns. The following columns are not numeric: ${nonNumeric\n .map((column) => `${quoteIdentifier(column)} (${schema[column]})`)\n .join(\", \")}. Convert them to numeric types first.`,\n );\n }\n if (options.type !== undefined) return options.type.toUpperCase();\n\n const inputTypes = resolved.map((column) => schema[column]);\n if (new Set(inputTypes).size !== 1) {\n throw new Error(\n `rowToVector() cannot infer one vector element type from columns with different types: ${resolved\n .map((column) => `${quoteIdentifier(column)} (${schema[column]})`)\n .join(\", \")}. Set options.type to \"float\" or \"double\".`,\n );\n }\n return inputTypes[0];\n}\n\nfunction resolveColumns(schema: TableSchema, columns: string[]): string[] {\n const available = Object.keys(schema);\n const resolved = columns.map((requested) =>\n available.find((column) => foldIdentifier(column) === foldIdentifier(requested)),\n );\n const missing = columns.filter((_, index) => resolved[index] === undefined);\n if (missing.length > 0) {\n throw new Error(\n `rowToVector() the column${missing.length > 1 ? \"s\" : \"\"} ${missing\n .map(quoteIdentifier)\n .join(\", \")} ${\n missing.length > 1 ? \"do\" : \"does\"\n } not exist. Check for typos, or load the data first.`,\n );\n }\n return resolved as string[];\n}\n\nfunction findDuplicate(columns: string[]): string | undefined {\n const seen = new Set<string>();\n for (const column of columns) {\n const folded = foldIdentifier(column);\n if (seen.has(folded)) return column;\n seen.add(folded);\n }\n return undefined;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport foldIdentifier from \"../helpers/foldIdentifier.ts\";\nimport prepareNumericFeatures from \"../helpers/prepareNumericFeatures.ts\";\nimport publishPreparedColumns from \"../helpers/publishPreparedColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype Options = NonNullable<Parameters<SimpleTable[\"normalizeVector\"]>[2]>;\n\nexport default function normalizeVector(\n table: SimpleTable,\n column: string,\n newColumn: string,\n options: Options = {},\n): void {\n if (\n options.normalization !== undefined &&\n options.normalization !== \"dimensionMinMax\" &&\n options.normalization !== \"rowL2\"\n ) {\n throw new Error(\n 'normalizeVector() options.normalization must be \"dimensionMinMax\" or \"rowL2\".',\n );\n }\n const settings = structuredClone(options);\n queueOp(table, {\n kind: \"barrier\",\n method: \"normalizeVector()\",\n parameters: { column, newColumn, options: settings },\n execute: () => execute(table, column, newColumn, settings),\n });\n}\n\nasync function execute(\n table: SimpleTable,\n column: string,\n newColumn: string,\n options: Options,\n): Promise<void> {\n const normalization = options.normalization ?? \"dimensionMinMax\";\n const overwrite = foldIdentifier(column) === foldIdentifier(newColumn);\n if (!overwrite) {\n const sourceColumns = Object.keys(await table.getTypes());\n if (sourceColumns.some((name) => foldIdentifier(name) === foldIdentifier(newColumn))) {\n throw new Error(\n `normalizeVector() cannot create ${quoteIdentifier(\n newColumn,\n )} because that column already exists. Remove it first or choose a different name.`,\n );\n }\n }\n const prepared = await prepareNumericFeatures(\n table,\n { kind: \"vector\", column },\n { method: \"normalizeVector()\" },\n );\n const connection = table.connection!;\n const q = quoteIdentifier;\n const suffix = crypto.randomUUID().replaceAll(\"-\", \"\");\n const statsName = `__sda_normalize_vector_${suffix}_stats`;\n const resultName = `__sda_normalize_vector_${suffix}_result`;\n const dimension = q(`__sda_dimension_${suffix}`);\n const minimum = q(`__sda_min_${suffix}`);\n const maximum = q(`__sda_max_${suffix}`);\n const normalized = `__sda_normalized_${suffix}`;\n\n try {\n if (prepared.rowCount === 0) {\n throw new Error(\"normalizeVector() requires at least one row; the dataset is empty.\");\n }\n const sourceColumn = prepared.sourceColumns.find(\n (name) => foldIdentifier(name) === foldIdentifier(column),\n )!;\n if (normalization === \"rowL2\") {\n // Scale before squaring so extreme finite magnitudes do not overflow\n // or underflow the norm. A zero vector stays zero.\n await connection.run(\n `CREATE TEMP TABLE ${q(resultName)} AS\n WITH magnitudes AS (\n SELECT ${q(prepared.rowIdColumn)}, ${q(prepared.vectorColumn)} AS vec,\n list_max(list_transform(${q(prepared.vectorColumn)}, value -> abs(value))) AS magnitude\n FROM ${q(prepared.relation)}\n ), scaled AS (\n SELECT *, list_transform(vec, value -> value / nullif(magnitude, 0)) AS unit_scale\n FROM magnitudes\n ), norms AS (\n SELECT *, sqrt(list_sum(list_transform(unit_scale, value -> value * value))) AS norm\n FROM scaled\n )\n SELECT ${q(prepared.rowIdColumn)},\n (CASE WHEN magnitude = 0 THEN vec::DOUBLE[]\n ELSE list_transform(unit_scale, value -> value / norm)\n END)::DOUBLE[${prepared.dimensions}] AS ${q(normalized)}\n FROM norms`,\n );\n } else {\n await connection.run(\n `CREATE TEMP TABLE ${q(statsName)} AS\n SELECT ordinal::BIGINT AS ${dimension}, min(value)::DOUBLE AS ${minimum},\n max(value)::DOUBLE AS ${maximum}\n FROM ${q(prepared.relation)} p,\n UNNEST(p.${q(prepared.vectorColumn)}::DOUBLE[]) WITH ORDINALITY AS values(value, ordinal)\n GROUP BY ordinal`,\n );\n const invalidStats = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(*) FROM ${q(statsName)}\n WHERE NOT isfinite(${minimum}) OR NOT isfinite(${maximum})`,\n )\n ).getRowsJS()[0][0],\n );\n if (invalidStats > 0) {\n throw new Error(\n `normalizeVector() found ${invalidStats} dimension${\n invalidStats === 1 ? \"\" : \"s\"\n } with non-finite aggregate values after conversion to DOUBLE.`,\n );\n }\n const constantDimensions = (\n await connection.runAndReadAll(\n `SELECT ${dimension} FROM ${q(statsName)}\n WHERE ${minimum} = ${maximum} ORDER BY ${dimension}`,\n )\n )\n .getRowsJS()\n .map((row) => Number(row[0]));\n if (constantDimensions.length > 0) {\n throw new Error(\n `normalizeVector() cannot scale constant dimension${\n constantDimensions.length === 1 ? \"\" : \"s\"\n } ${constantDimensions.join(\", \")} in column ${q(\n sourceColumn,\n )} because the range is zero. Remove ${\n constantDimensions.length === 1 ? \"that dimension\" : \"those dimensions\"\n } before normalizing. Conversion to DOUBLE can also collapse distinct large integers or decimals at its precision limit.`,\n );\n }\n\n const value = `p.${q(prepared.vectorColumn)}[s.${dimension}]`;\n const min = `s.${minimum}`;\n const max = `s.${maximum}`;\n // Dividing both sides by the larger magnitude when a range crosses zero\n // avoids overflowing max - min for extreme finite DOUBLE values.\n const scaled = `CASE\n WHEN ${min} < 0 AND ${max} > 0 AND -${min} >= ${max}\n THEN ((${value} / -${min}) + 1.0) / ((${max} / -${min}) + 1.0)\n WHEN ${min} < 0 AND ${max} > 0\n THEN ((${value} / ${max}) + (-${min} / ${max})) /\n (1.0 + (-${min} / ${max}))\n ELSE (${value} - ${min}) / (${max} - ${min})\n END`;\n await connection.run(\n `CREATE TEMP TABLE ${q(resultName)} AS\n SELECT p.${q(prepared.rowIdColumn)},\n list(${scaled} ORDER BY s.${dimension})::DOUBLE[${prepared.dimensions}]\n AS ${q(normalized)}\n FROM ${q(prepared.relation)} p CROSS JOIN ${q(statsName)} s\n GROUP BY p.${q(prepared.rowIdColumn)}`,\n );\n }\n const invalidResults = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(*) FROM ${q(resultName)}\n WHERE ${q(normalized)} IS NULL\n OR list_count(${q(normalized)}) != ${prepared.dimensions}\n OR NOT list_bool_and(list_transform(${q(normalized)}, value -> isfinite(value)))\n OR list_min(${q(normalized)}) < ${normalization === \"rowL2\" ? -1 : 0}\n OR list_max(${q(normalized)}) > 1`,\n )\n ).getRowsJS()[0][0],\n );\n if (invalidResults > 0) {\n throw new Error(\n `normalizeVector() produced non-finite or out-of-range values for ${invalidResults} row${\n invalidResults === 1 ? \"\" : \"s\"\n }. Rescale the source values before normalizing.`,\n );\n }\n\n await publishPreparedColumns(table, prepared, {\n method: \"normalizeVector()\",\n parameters: { column, newColumn, options },\n result: {\n relation: resultName,\n rowIdColumn: prepared.rowIdColumn,\n },\n outputs: [\n {\n name: overwrite ? sourceColumn : newColumn,\n expression: `r.${q(normalized)}`,\n replace: overwrite ? sourceColumn : undefined,\n },\n ],\n });\n } finally {\n await connection.run(`DROP TABLE IF EXISTS ${q(resultName)}`);\n await connection.run(`DROP TABLE IF EXISTS ${q(statsName)}`);\n await prepared.cleanup();\n }\n}\n","export type CovarianceFactor = {\n dimensions: number;\n covariance: Float64Array;\n scales: Float64Array;\n cholesky: Float64Array;\n reciprocalCondition: number;\n};\n\nconst instabilityMultiplier = 64;\n\nfunction singularCovariance(reason: string): Error {\n return new Error(\n `Covariance is singular or numerically unstable (${reason}). Constant columns, linearly dependent features, or too few observations are common causes. Remove redundant features or provide more observations.`,\n );\n}\n\nfunction scaleCovarianceEntry(value: number, leftScale: number, rightScale: number): number {\n // Divide by the larger scale first. For a valid covariance, Cauchy-Schwarz\n // bounds |value| by their product, so this avoids intermediate overflow when\n // two otherwise equivalent features use radically different units.\n return leftScale >= rightScale ? value / leftScale / rightScale : value / rightScale / leftScale;\n}\n\nfunction solveCorrelation(\n cholesky: Float64Array,\n dimensions: number,\n rightHandSide: ArrayLike<number>,\n): Float64Array {\n const solution = new Float64Array(dimensions);\n for (let row = 0; row < dimensions; row++) {\n let value = rightHandSide[row];\n for (let column = 0; column < row; column++) {\n value -= cholesky[row * dimensions + column] * solution[column];\n }\n solution[row] = value / cholesky[row * dimensions + row];\n }\n for (let row = dimensions - 1; row >= 0; row--) {\n let value = solution[row];\n for (let column = row + 1; column < dimensions; column++) {\n value -= cholesky[column * dimensions + row] * solution[column];\n }\n solution[row] = value / cholesky[row * dimensions + row];\n }\n return solution;\n}\n\n// Hager's estimator avoids forming the inverse merely to decide whether the\n// correlation-scaled covariance is safe to solve. Scaling first makes this\n// rank decision invariant to a change of units in any feature.\nfunction estimateInverseOneNorm(cholesky: Float64Array, dimensions: number): number {\n let vector = new Float64Array(dimensions).fill(1 / dimensions);\n let estimate = 0;\n let previousIndex = -1;\n for (let iteration = 0; iteration < 8; iteration++) {\n const solved = solveCorrelation(cholesky, dimensions, vector);\n estimate = Math.max(\n estimate,\n solved.reduce((sum, value) => sum + Math.abs(value), 0),\n );\n const signs = solved.map((value) => (value < 0 ? -1 : 1));\n const dual = solveCorrelation(cholesky, dimensions, signs);\n let index = 0;\n for (let i = 1; i < dimensions; i++) {\n if (Math.abs(dual[i]) > Math.abs(dual[index])) index = i;\n }\n const directional = dual.reduce((sum, value, i) => sum + value * vector[i], 0);\n if (Math.abs(dual[index]) <= directional || index === previousIndex) break;\n vector = new Float64Array(dimensions);\n vector[index] = 1;\n previousIndex = index;\n }\n // The all-positive initial vector can be an eigenvector that causes Hager's\n // iteration to stop at the *smallest* inverse eigenvalue (for example an\n // equicorrelation matrix). Higham's alternating, increasing-magnitude probe\n // prevents that failure; normalize by its 1-norm to retain a lower estimate.\n // Reference: https://www.netlib.org/lapack/double/dlacon.f (final stage).\n const alternating = Float64Array.from(\n { length: dimensions },\n (_, i) => (i % 2 === 0 ? 1 : -1) * (1 + i / Math.max(1, dimensions - 1)),\n );\n const alternatingNorm = alternating.reduce((sum, value) => sum + Math.abs(value), 0);\n const solved = solveCorrelation(cholesky, dimensions, alternating);\n estimate = Math.max(\n estimate,\n solved.reduce((sum, value) => sum + Math.abs(value), 0) / alternatingNorm,\n );\n return estimate;\n}\n\n/** Factors a sample covariance matrix for stable repeated linear solves. */\nexport function factorCovariance(\n covarianceInput: ArrayLike<number>,\n dimensions: number,\n): CovarianceFactor {\n if (!Number.isSafeInteger(dimensions) || dimensions < 1) {\n throw new Error(\"Covariance dimensions must be a positive safe integer.\");\n }\n if (covarianceInput.length !== dimensions * dimensions) {\n throw new Error(\n `Expected ${dimensions * dimensions} covariance values, received ${covarianceInput.length}.`,\n );\n }\n\n const covariance = Float64Array.from(covarianceInput);\n const scales = new Float64Array(dimensions);\n for (let dimension = 0; dimension < dimensions; dimension++) {\n const variance = covariance[dimension * dimensions + dimension];\n if (!Number.isFinite(variance) || variance <= 0) {\n throw singularCovariance(\n `feature ${dimension + 1} has non-positive or non-finite sample variance`,\n );\n }\n scales[dimension] = Math.sqrt(variance);\n }\n\n const correlation = new Float64Array(dimensions * dimensions);\n let correlationOneNorm = 0;\n for (let column = 0; column < dimensions; column++) {\n let columnSum = 0;\n for (let row = 0; row < dimensions; row++) {\n const left = covariance[row * dimensions + column];\n const right = covariance[column * dimensions + row];\n if (!Number.isFinite(left) || !Number.isFinite(right)) {\n throw singularCovariance(\"the sample covariance contains non-finite values\");\n }\n const value =\n row === column\n ? 1\n : scaleCovarianceEntry(left, scales[row], scales[column]) / 2 +\n scaleCovarianceEntry(right, scales[row], scales[column]) / 2;\n if (!Number.isFinite(value)) {\n throw singularCovariance(\"correlation scaling produced a non-finite value\");\n }\n correlation[row * dimensions + column] = value;\n columnSum += Math.abs(value);\n }\n correlationOneNorm = Math.max(correlationOneNorm, columnSum);\n }\n\n const cholesky = new Float64Array(dimensions * dimensions);\n for (let row = 0; row < dimensions; row++) {\n for (let column = 0; column <= row; column++) {\n let value = correlation[row * dimensions + column];\n for (let k = 0; k < column; k++) {\n value -= cholesky[row * dimensions + k] * cholesky[column * dimensions + k];\n }\n if (row === column) {\n if (!Number.isFinite(value) || value <= 0) {\n throw singularCovariance(`correlation-scaled Cholesky pivot ${row + 1} is not positive`);\n }\n cholesky[row * dimensions + column] = Math.sqrt(value);\n } else {\n cholesky[row * dimensions + column] = value / cholesky[column * dimensions + column];\n }\n }\n }\n\n const inverseOneNorm = estimateInverseOneNorm(cholesky, dimensions);\n const reciprocalCondition = 1 / (correlationOneNorm * inverseOneNorm);\n // This is the usual dimension-scaled floating-point rank tolerance, with a\n // modest safety factor for covariance aggregation and subsequent row solves.\n const tolerance = instabilityMultiplier * dimensions * Number.EPSILON;\n if (!Number.isFinite(reciprocalCondition) || reciprocalCondition <= tolerance) {\n throw singularCovariance(\n `estimated reciprocal condition ${reciprocalCondition} is at or below ${tolerance}`,\n );\n }\n\n return {\n dimensions,\n covariance,\n scales,\n cholesky,\n reciprocalCondition,\n };\n}\n\n/** Solves covariance * x = rightHandSide through the scaled Cholesky factor. */\nexport function solveCovariance(\n factor: CovarianceFactor,\n rightHandSide: ArrayLike<number>,\n): Float64Array {\n const { dimensions, scales, cholesky } = factor;\n if (rightHandSide.length !== dimensions) {\n throw new Error(\n `Expected a right-hand side with ${dimensions} values, received ${rightHandSide.length}.`,\n );\n }\n const scaled = new Float64Array(dimensions);\n for (let i = 0; i < dimensions; i++) {\n if (!Number.isFinite(rightHandSide[i])) {\n throw new Error(\"The covariance solve requires finite values.\");\n }\n scaled[i] = rightHandSide[i] / scales[i];\n }\n const solution = solveCorrelation(cholesky, dimensions, scaled);\n for (let i = 0; i < dimensions; i++) {\n solution[i] /= scales[i];\n if (!Number.isFinite(solution[i])) {\n throw singularCovariance(\"the linear solve produced a non-finite value\");\n }\n }\n return solution;\n}\n\n/**\n * Returns the lower-triangular transform whose squared norm is Mahalanobis\n * squared distance. This inverts only the Cholesky factor, never covariance.\n */\nexport function covarianceWhitening(factor: CovarianceFactor): Float64Array {\n const { dimensions, scales, cholesky } = factor;\n const whitening = new Float64Array(dimensions * dimensions);\n // Invert the triangular correlation factor first, then apply feature units.\n // Keeping units out of the recurrence avoids repeated underflow/rounding of\n // the same coefficient, and visits only the nonzero triangle.\n for (let column = 0; column < dimensions; column++) {\n for (let row = column; row < dimensions; row++) {\n let value = row === column ? 1 : 0;\n for (let k = column; k < row; k++) {\n value -= cholesky[row * dimensions + k] * whitening[k * dimensions + column];\n }\n whitening[row * dimensions + column] = value / cholesky[row * dimensions + row];\n }\n for (let row = column; row < dimensions; row++) {\n const index = row * dimensions + column;\n whitening[index] /= scales[column];\n if (!Number.isFinite(whitening[index])) {\n throw singularCovariance(\"the whitening transform produced a non-finite value\");\n }\n }\n }\n return whitening;\n}\n","import type { DuckDBConnection } from \"@duckdb/node-api\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport { type CovarianceFactor, factorCovariance } from \"./factorCovariance.ts\";\n\nexport type CovarianceModel = CovarianceFactor & {\n means: Float64Array;\n origins: Float64Array;\n meanOffsets: Float64Array;\n observations: number;\n};\n\nexport default async function computeCovariance(\n connection: DuckDBConnection,\n input: {\n relation: string;\n rowIdColumn: string;\n vectorColumn: string;\n observations: number;\n dimensions: number;\n },\n): Promise<CovarianceModel> {\n const { observations, dimensions } = input;\n if (!Number.isSafeInteger(dimensions) || dimensions < 1) {\n throw new Error(\"Covariance requires at least one feature dimension.\");\n }\n if (!Number.isSafeInteger(observations) || observations <= dimensions) {\n throw new Error(\n `Covariance requires more observations than features (n > d), but received n=${observations} and d=${dimensions}. More observations are necessary, though constant or linearly dependent features can still make covariance singular.`,\n );\n }\n\n const relation = quoteIdentifier(input.relation);\n const rowId = quoteIdentifier(input.rowIdColumn);\n const vector = quoteIdentifier(input.vectorColumn);\n const expanded = `SELECT r.${rowId} AS observation,\n f.feature::INTEGER AS feature,\n array_extract(r.${vector}, f.feature)::DOUBLE AS value\n FROM ${relation} r CROSS JOIN range(1, ${dimensions + 1}) f(feature)`;\n const offsets = `SELECT observation, feature, value,\n first_value(value) OVER (PARTITION BY feature ORDER BY observation\n ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS origin\n FROM (${expanded})`;\n\n const meanRows = (\n await connection.runAndReadAll(\n `SELECT feature - 1 AS feature, first(origin) AS origin,\n avg(value - origin) AS mean_offset, max(abs(value - origin)) AS magnitude FROM (${offsets})\n GROUP BY feature ORDER BY feature`,\n )\n ).getRowsJS();\n if (meanRows.length !== dimensions) {\n throw new Error(\"Covariance aggregation returned an incomplete centroid.\");\n }\n const magnitudes = new Float64Array(dimensions);\n const means = new Float64Array(dimensions);\n const origins = new Float64Array(dimensions);\n const meanOffsets = new Float64Array(dimensions);\n for (const row of meanRows) {\n const feature = Number(row[0]);\n const origin = Number(row[1]);\n const meanOffset = Number(row[2]);\n if (\n !Number.isSafeInteger(feature) ||\n !Number.isFinite(origin) ||\n !Number.isFinite(meanOffset)\n ) {\n throw new Error(\n \"Covariance is numerically unstable because centroid aggregation produced a non-finite result. Rescale features or remove dimensions whose range cannot be represented as DOUBLE.\",\n );\n }\n const magnitude = Number(row[3]);\n if (!Number.isFinite(magnitude) || magnitude <= 0) {\n throw new Error(\n `Covariance is singular or numerically unstable (feature ${\n feature + 1\n } has constant values or an unrepresentable range). Constant columns, linearly dependent features, or too few observations are common causes. Remove redundant features or provide more observations.`,\n );\n }\n magnitudes[feature] = magnitude;\n origins[feature] = origin;\n meanOffsets[feature] = meanOffset;\n means[feature] = origin + meanOffset;\n }\n\n const covariance = new Float64Array(dimensions * dimensions);\n // covar_samp divides centered cross-products by n - 1. Subtracting a native\n // per-feature anchor first avoids cancellation in E[x*y] - E[x]E[y] and\n // retains small deviations when a feature has a large common offset.\n // Divide by each feature's observed magnitude before accumulating products.\n // Otherwise the n-1 cross-product sum can overflow even when the final sample\n // covariance is finite (e.g. [0, 1e154, 2e154], whose variance is 1e308).\n const result = await connection.stream(\n `WITH features AS MATERIALIZED (\n SELECT observation, feature, (value - origin) /\n array_extract([${magnitudes.join(\",\")}]::DOUBLE[${dimensions}], feature) AS value\n FROM (${offsets})\n )\n SELECT a.feature - 1 AS row, b.feature - 1 AS column,\n covar_samp(a.value, b.value) AS covariance\n FROM features a JOIN features b\n ON a.observation = b.observation AND a.feature <= b.feature\n GROUP BY a.feature, b.feature`,\n );\n let values = 0;\n while (true) {\n const chunk = await result.fetchChunk();\n if (!chunk || chunk.rowCount === 0) break;\n const rows = new Int32Array(chunk.rowCount);\n const columns = new Int32Array(chunk.rowCount);\n const entries = new Float64Array(chunk.rowCount);\n chunk.visitColumnValues(0, (value, row) => (rows[row] = Number(value)));\n chunk.visitColumnValues(1, (value, row) => (columns[row] = Number(value)));\n chunk.visitColumnValues(2, (value, row) => (entries[row] = Number(value)));\n for (let i = 0; i < chunk.rowCount; i++) {\n const row = rows[i];\n const column = columns[i];\n // Restore units using the larger magnitude first to avoid prematurely\n // underflowing a finite cross-covariance between very different units.\n const value =\n entries[i] *\n Math.max(magnitudes[row], magnitudes[column]) *\n Math.min(magnitudes[row], magnitudes[column]);\n covariance[row * dimensions + column] = value;\n covariance[column * dimensions + row] = value;\n values++;\n }\n }\n if (values !== (dimensions * (dimensions + 1)) / 2) {\n throw new Error(\"Covariance aggregation returned an incomplete matrix.\");\n }\n\n return {\n ...factorCovariance(covariance, dimensions),\n means,\n origins,\n meanOffsets,\n observations,\n };\n}\n","import { ARRAY, DOUBLE, type DuckDBConnection } from \"@duckdb/node-api\";\nimport type { CovarianceModel } from \"./computeCovariance.ts\";\nimport { covarianceWhitening } from \"./factorCovariance.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/** Evaluates bulk distances in DuckDB; the caller owns the returned scratch table. */\nexport default async function computeMahalanobisDistances(\n connection: DuckDBConnection,\n input: {\n relation: string;\n rowIdColumn: string;\n vectorColumn: string;\n },\n model: CovarianceModel,\n referencePoint?: number[],\n): Promise<{\n relation: string;\n rowIdColumn: string;\n distanceColumn: string;\n cleanup: () => Promise<void>;\n}> {\n const { dimensions, means, origins, meanOffsets } = model;\n if ([means, origins, meanOffsets].some((values) => values.length !== dimensions)) {\n throw new Error(\"The covariance centroid has the wrong dimensions.\");\n }\n const vectorLiteral = (values: Float64Array) => {\n if (values.some((value) => !Number.isFinite(value))) {\n throw new Error(\"Mahalanobis centering requires finite coefficients.\");\n }\n return `[${values.join(\",\")}]::DOUBLE[${dimensions}]`;\n };\n const originSql = vectorLiteral(origins);\n const offsetSql = vectorLiteral(meanOffsets);\n if (\n referencePoint !== undefined &&\n (referencePoint.length !== dimensions ||\n referencePoint.some((value) => !Number.isFinite(value)))\n ) {\n throw new Error(\"Mahalanobis reference point must contain one finite number per dimension.\");\n }\n // Direct subtraction retains exact matches and tiny reference offsets that\n // would be lost by subtracting the centroid from both points separately.\n const centeredValue =\n referencePoint === undefined\n ? `(value - array_extract(${originSql}, dimension)) - array_extract(${offsetSql}, dimension)`\n : `value - array_extract(${vectorLiteral(Float64Array.from(referencePoint))}, dimension)`;\n const whitening = covarianceWhitening(model);\n const suffix = crypto.randomUUID().replaceAll(\"-\", \"\");\n const relation = `__sda_mahalanobis_distances_${suffix}`;\n const weights = `__sda_mahalanobis_weights_${suffix}`;\n const rowIdColumn = \"row_id\";\n const distanceColumn = \"distance\";\n const cleanup = async () => {\n await connection.run(`DROP TABLE IF EXISTS ${quoteIdentifier(relation)}`);\n };\n try {\n await connection.run(`CREATE TEMP TABLE ${quoteIdentifier(weights)}\n (weight DOUBLE[${dimensions}])`);\n const appender = await connection.createAppender(weights);\n try {\n // Only O(d²) summary state crosses this boundary, one O(d) row at a time.\n // Binding a native table avoids parsing a matrix-sized SQL literal and\n // repeatedly evaluating it inside a per-observation lambda.\n for (let row = 0; row < dimensions; row++) {\n appender.appendArray(\n Array.from(whitening.subarray(row * dimensions, (row + 1) * dimensions)),\n ARRAY(DOUBLE, dimensions),\n );\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n // Center once per observation. The cross product is consumed by a grouped\n // aggregate: O(n d²) arithmetic, O(n d) centered storage, O(d²) coefficients,\n // and O(n) aggregate/output state. Source vectors never enter JavaScript.\n await connection.run(`CREATE TEMP TABLE ${quoteIdentifier(relation)} AS\n WITH centered AS MATERIALIZED (\n SELECT ${quoteIdentifier(input.rowIdColumn)} AS row_id,\n list_transform(${quoteIdentifier(input.vectorColumn)},\n (value, dimension) -> ${centeredValue})::DOUBLE[${dimensions}] AS vector\n FROM ${quoteIdentifier(input.relation)}\n ), components AS MATERIALIZED (\n SELECT row_id, abs(array_inner_product(weight, vector)) AS component\n FROM centered CROSS JOIN ${quoteIdentifier(weights)}\n ), magnitudes AS (\n SELECT row_id, max(component) AS magnitude FROM components GROUP BY row_id\n )\n SELECT row_id, CASE WHEN magnitude = 0 THEN 0::DOUBLE\n ELSE magnitude * sqrt(sum(pow(component / magnitude, 2))) END AS distance\n FROM components JOIN magnitudes USING (row_id)\n GROUP BY row_id, magnitude`);\n const invalid = Number(\n (\n await connection.runAndReadAll(\n `SELECT count(*) FROM ${quoteIdentifier(relation)}\n WHERE distance IS NULL OR NOT isfinite(distance)`,\n )\n ).getRowsJS()[0][0],\n );\n if (invalid > 0) {\n throw new Error(\n `Mahalanobis distance produced ${invalid} non-finite results. Rescale features or remove numerically unstable dimensions.`,\n );\n }\n return { relation, rowIdColumn, distanceColumn, cleanup };\n } catch (error) {\n await cleanup();\n throw error;\n } finally {\n await connection.run(`DROP TABLE IF EXISTS ${quoteIdentifier(weights)}`);\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport computeCovariance from \"../helpers/computeCovariance.ts\";\nimport computeMahalanobisDistances from \"../helpers/computeMahalanobisDistances.ts\";\nimport foldIdentifier from \"../helpers/foldIdentifier.ts\";\nimport prepareNumericFeatures from \"../helpers/prepareNumericFeatures.ts\";\nimport publishPreparedColumns from \"../helpers/publishPreparedColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype Options = NonNullable<Parameters<SimpleTable[\"similarityMahalanobis\"]>[3]>;\n\nexport default function similarityMahalanobis(\n table: SimpleTable,\n columns: string | string[],\n referencePoint: number[] | { [key: string]: unknown },\n newColumn: string,\n options: Options = {},\n): void {\n const selected = typeof columns === \"string\" ? columns : [...columns];\n if (\n !Array.isArray(referencePoint) &&\n referencePoint !== null &&\n typeof referencePoint === \"object\"\n ) {\n if (typeof selected === \"string\") {\n throw new Error(\n \"similarityMahalanobis() an object referencePoint requires an array of scalar feature column names; use a numeric array for a vector column.\",\n );\n }\n const referenceObject = referencePoint;\n referencePoint = selected.map((column) => {\n if (!Object.hasOwn(referenceObject, column)) {\n throw new Error(\n `similarityMahalanobis() referencePoint is missing its own value for feature ${quoteIdentifier(\n column,\n )}.`,\n );\n }\n const value = referenceObject[column];\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(\n `similarityMahalanobis() referencePoint feature ${quoteIdentifier(\n column,\n )} must be a finite number.`,\n );\n }\n return value;\n });\n }\n if (\n !Array.isArray(referencePoint) ||\n referencePoint.length === 0 ||\n Array.from(referencePoint).some((value) => typeof value !== \"number\" || !Number.isFinite(value))\n ) {\n throw new Error(\n \"similarityMahalanobis() referencePoint must be a nonempty array of finite numbers in feature-dimension order.\",\n );\n }\n const reference = [...referencePoint];\n const settings = { ...options };\n queueOp(table, {\n kind: \"barrier\",\n method: \"similarityMahalanobis()\",\n parameters: {\n columns: selected,\n referencePoint: reference,\n newColumn,\n options: settings,\n },\n execute: () => execute(table, selected, reference, newColumn, settings),\n });\n}\n\nasync function execute(\n table: SimpleTable,\n columns: string | string[],\n referencePoint: number[],\n newColumn: string,\n options: Options,\n): Promise<void> {\n const sourceColumns = Object.keys(await table.getTypes());\n const scoreColumn =\n options.similarityColumn === true\n ? \"similarity\"\n : options.similarityColumn === false\n ? undefined\n : options.similarityColumn;\n const outputNames = scoreColumn === undefined ? [newColumn] : [newColumn, scoreColumn];\n const seen = new Set<string>();\n for (const name of outputNames) {\n if (typeof name !== \"string\" || name.length === 0 || name.includes(\"\\0\")) {\n throw new Error(\n \"similarityMahalanobis() output column names must be nonempty strings without null characters.\",\n );\n }\n const folded = foldIdentifier(name);\n if (seen.has(folded)) {\n throw new Error(\n \"similarityMahalanobis() distance and similarity score columns must have different names (case-insensitive).\",\n );\n }\n seen.add(folded);\n if (sourceColumns.some((column) => foldIdentifier(column) === folded)) {\n throw new Error(\n `similarityMahalanobis() cannot create ${quoteIdentifier(\n name,\n )} because that column already exists. Remove it first or choose a different name.`,\n );\n }\n }\n\n const prepared = await prepareNumericFeatures(\n table,\n typeof columns === \"string\"\n ? { kind: \"vector\", column: columns }\n : { kind: \"scalars\", columns },\n { method: \"similarityMahalanobis()\" },\n );\n try {\n if (referencePoint.length !== prepared.dimensions) {\n throw new Error(\n `similarityMahalanobis() referencePoint must contain ${prepared.dimensions} values in feature-dimension order; received ${referencePoint.length}.`,\n );\n }\n const model = await computeCovariance(table.connection!, {\n relation: prepared.relation,\n rowIdColumn: prepared.rowIdColumn,\n vectorColumn: prepared.vectorColumn,\n observations: prepared.rowCount,\n dimensions: prepared.dimensions,\n });\n const distances = await computeMahalanobisDistances(\n table.connection!,\n {\n relation: prepared.relation,\n rowIdColumn: prepared.rowIdColumn,\n vectorColumn: prepared.vectorColumn,\n },\n model,\n referencePoint,\n );\n try {\n const distance = `r.${quoteIdentifier(distances.distanceColumn)}`;\n const outputs = [{ name: newColumn, expression: distance }];\n if (scoreColumn !== undefined) {\n outputs.push({\n name: scoreColumn,\n expression: `CASE WHEN max(${distance}) OVER () = 0 THEN 1::DOUBLE ELSE 1 - ${distance} / max(${distance}) OVER () END`,\n });\n }\n await publishPreparedColumns(table, prepared, {\n method: \"similarityMahalanobis()\",\n parameters: { columns, referencePoint, newColumn, options },\n result: {\n relation: distances.relation,\n rowIdColumn: distances.rowIdColumn,\n },\n outputs,\n });\n } finally {\n await distances.cleanup();\n }\n } finally {\n await prepared.cleanup();\n }\n}\n","import queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport toDuckDBValue from \"../helpers/toDuckDBValue.ts\";\n\nexport default function replaceNulls(\n simpleTable: SimpleTable,\n columns: string | string[],\n value: unknown,\n) {\n columns = Array.isArray(columns) ? [...columns] : columns;\n const capturedValue = value instanceof Date ? new Date(value.getTime()) : value;\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"replaceNulls()\",\n // The schema resolves \"all\" to the column list and gives each column's\n // type: v1 replaced nulls with an UPDATE, which assignment-casts the\n // value to the column's type (e.g. 0 into a VARCHAR column becomes '0').\n // COALESCE can't mix types, so the value is cast to the column's type to\n // reproduce that.\n needsSchema: true,\n preservesSchema: true,\n parameters: { columns, value: capturedValue },\n values: (schema) => {\n const columnList = columns === \"all\" ? Object.keys(schema) : stringToArray(columns);\n return columnList.map(() => toDuckDBValue(capturedValue));\n },\n buildSelect: (input, schema) => {\n const columnList = columns === \"all\" ? Object.keys(schema) : stringToArray(columns);\n return `SELECT * REPLACE (${columnList\n .map(\n (column) =>\n `COALESCE(${quoteIdentifier(column)}, CAST(? AS ${\n schema[column]\n })) AS ${quoteIdentifier(column)}`,\n )\n .join(\", \")}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function pad(\n simpleTable: SimpleTable,\n columns: string | string[],\n length: number,\n options: { side?: \"left\" | \"right\"; character?: string } = {},\n) {\n if (!Number.isFinite(length) || !Number.isInteger(length) || length < 0) {\n throw new Error(\"pad() length must be a finite integer greater than or equal to 0.\");\n }\n\n columns = Array.isArray(columns) ? [...columns] : columns;\n options = structuredClone(options);\n const columnList = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"pad()\",\n parameters: { columns, length, options },\n needsSchema: true,\n preservesSchema: true,\n values: padValues(columnList, length, options),\n buildSelect: (input, schema) => padSelect(input, schema, columnList, length, options),\n });\n}\n\nfunction padSelect(\n input: string,\n schema: TableSchema,\n columns: string[],\n length: number,\n options: { side?: \"left\" | \"right\"; character?: string },\n): string {\n for (const column of columns) {\n if (schema[column] !== \"VARCHAR\") {\n throw new Error(\n `The column ${quoteIdentifier(column)} is of type ${\n schema[column]\n }. The pad() method only works with string (VARCHAR) columns. Please convert the column to string first with the .convert() method.`,\n );\n }\n }\n\n const usedNames = new Set(Object.keys(schema));\n const overflowAliases = columns.map((_, index) => {\n let alias = `__sda_pad_overflow_${index}`;\n while (usedNames.has(alias)) {\n alias += \"_\";\n }\n usedNames.add(alias);\n return alias;\n });\n const func = options.side === \"right\" ? \"RPAD\" : \"LPAD\";\n const counts = columns\n .map(\n (column, index) =>\n `COUNT(*) FILTER (WHERE LENGTH(${quoteIdentifier(\n column,\n )}) > ${length}) OVER () AS ${quoteIdentifier(overflowAliases[index])}`,\n )\n .join(\", \");\n const replacements = columns\n .map((column, index) => {\n const alias = quoteIdentifier(overflowAliases[index]);\n return `CASE WHEN ${alias} > 0 THEN error(CONCAT(?, CAST(${alias} AS VARCHAR), ?)) ELSE ${func}(${quoteIdentifier(\n column,\n )}, ${length}, ?) END AS ${quoteIdentifier(column)}`;\n })\n .join(\", \");\n const excluded = overflowAliases.map(quoteIdentifier).join(\", \");\n return `SELECT * EXCLUDE (${excluded}) REPLACE (${replacements})\nFROM (\n SELECT *, ${counts} FROM ${input}\n) AS ${quoteIdentifier(\"__sda_pad_source\")}`;\n}\n\nfunction padValues(columns: string[], length: number, options: { character?: string }): string[] {\n const character = options.character ?? \"0\";\n return columns.flatMap((column) => [\n `The column ${quoteIdentifier(column)} has `,\n ` string(s) exceeding the target length of ${length}. The pad() method does not truncate. Shorten the strings first or use a larger target length.`,\n character,\n ]);\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function replace(\n simpleTable: SimpleTable,\n columns: string | string[],\n replacements: { [key: string]: string },\n options: {\n entireString?: boolean;\n regex?: boolean;\n } = {},\n) {\n columns = Array.isArray(columns) ? [...columns] : columns;\n replacements = { ...replacements };\n options = { ...options };\n options.entireString = options.entireString ?? false;\n options.regex = options.regex ?? false;\n const entries = Object.entries(replacements);\n const replacementEntries = options.entireString\n ? entries.map(([oldText]) => {\n let newText = oldText;\n for (const [candidate, replacement] of entries) {\n if (newText === candidate) {\n newText = replacement;\n }\n }\n return [oldText, newText] as const;\n })\n : entries;\n // This validation doesn't need the database, so it stays at call time.\n if (options.entireString === true && options.regex === true) {\n throw new Error(\n \"You can't have entireString to true and regex to true at the same time. Pick one.\",\n );\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"replace()\",\n parameters: { columns, replacements, options },\n // The schema is only needed to resolve \"all\" to the column list.\n needsSchema: columns === \"all\",\n values: (schema) => {\n const columnList = columns === \"all\" ? Object.keys(schema) : stringToArray(columns);\n return columnList.flatMap(() =>\n replacementEntries.flatMap(([oldText, newText]) => [oldText, newText]),\n );\n },\n buildSelect: (input, schema) => {\n const columnList = columns === \"all\" ? Object.keys(schema) : stringToArray(columns);\n return replaceSelect(input, columnList, replacementEntries.length, options);\n },\n });\n}\n\nfunction replaceSelect(\n input: string,\n columns: string[],\n replacementCount: number,\n options: { entireString?: boolean; regex?: boolean } = {},\n) {\n // The sequential UPDATEs become nested expressions: each replacement\n // applies to the result of the previous one.\n const replacements = columns.map((column) => {\n let expression = `${quoteIdentifier(column)}`;\n if (options.entireString) {\n const branches = Array.from({ length: replacementCount }, () => \"WHEN ? THEN ?\").join(\" \");\n return `CASE ${expression} ${branches} ELSE ${expression} END AS ${quoteIdentifier(column)}`;\n }\n for (let i = 0; i < replacementCount; i++) {\n if (options.regex) {\n expression = `REGEXP_REPLACE(${expression}, ?, ?, 'g')`;\n } else {\n expression = `REPLACE(${expression}, ?, ?)`;\n }\n }\n return `${expression} AS ${quoteIdentifier(column)}`;\n });\n\n return `SELECT * REPLACE (${replacements.join(\", \")}) FROM ${input}`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getIdenticalColumns from \"../helpers/getIdenticalColumns.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\n\nexport default function crossJoin(\n simpleTable: SimpleTable,\n rightTable: SimpleTable,\n options: {\n outputTable?: string | boolean;\n } = {},\n): SimpleTable {\n assertSameDatabase(simpleTable.sdb, [rightTable], \"crossJoin()\");\n options = structuredClone(options);\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n\n // The output table instance is created at call time so it can be returned\n // synchronously and chained on right away.\n const outputTable =\n typeof options.outputTable === \"string\"\n ? simpleTable.sdb.newTable(options.outputTable)\n : simpleTable;\n\n queueOp(outputTable, {\n kind: \"barrier\",\n method: \"crossJoin()\",\n parameters: { rightTable: rightTable.name, options },\n execute: () => executeCrossJoin(simpleTable, rightTable, outputTable),\n });\n\n return outputTable;\n}\n\nasync function executeCrossJoin(\n simpleTable: SimpleTable,\n rightTable: SimpleTable,\n outputTable: SimpleTable,\n): Promise<void> {\n const identicalColumns = getIdenticalColumns(\n await simpleTable.getColumns(),\n await rightTable.getColumns(),\n );\n if (identicalColumns.length > 0) {\n throw new Error(\n `The tables have columns with identical names. Rename or remove ${identicalColumns\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")} in one of the two tables before doing the cross join.`,\n );\n }\n\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable.name)} AS SELECT ${quoteIdentifier(\n simpleTable.name,\n )}.*, ${quoteIdentifier(rightTable.name)}.* FROM ${quoteIdentifier(\n simpleTable.name,\n )} CROSS JOIN ${quoteIdentifier(rightTable.name)};`,\n mergeOptions(simpleTable, {\n table: outputTable.name,\n method: \"crossJoin()\",\n parameters: { rightTable: rightTable.name },\n }),\n );\n}\n","import assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport foldIdentifier from \"../helpers/foldIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addId(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { prefix?: string } = {},\n) {\n if (typeof newColumn !== \"string\") {\n throw new TypeError(\"addId() newColumn must be a string.\");\n }\n if (options.prefix !== undefined && typeof options.prefix !== \"string\") {\n throw new TypeError(\"addId() options.prefix must be a string.\");\n }\n\n // Materialize preceding operations so IDs follow their resulting row order.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"addId()\",\n parameters: { newColumn, options },\n execute: async () => {\n const types = await simpleTable.getTypes();\n const existingColumn = Object.keys(types).find(\n (column) => foldIdentifier(column) === foldIdentifier(newColumn),\n );\n assertNewColumns(types, [existingColumn ?? newColumn], \"addId()\");\n\n // An empty window preserves scan order without referencing rowid, which\n // may be shadowed by a user column.\n const rowNumber = \"(ROW_NUMBER() OVER () - 1)\";\n const id =\n options.prefix === undefined ? rowNumber : `CONCAT(?, CAST(${rowNumber} AS VARCHAR))`;\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT *, ${id} AS ${quoteIdentifier(newColumn)} FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"addId()\",\n parameters: { newColumn, options },\n values: options.prefix === undefined ? undefined : [options.prefix],\n }),\n );\n },\n });\n}\n","export type GraphId = string | number | bigint;\n\nexport type PreparedGraphStarts = {\n family: \"string\" | \"numeric\";\n numericValues: bigint[];\n values: string[];\n};\n\n/** Validates and snapshots scalar-or-array graph starting IDs. */\nexport default function prepareGraphStarts(\n start: GraphId | GraphId[],\n method: string,\n argument = \"start\",\n scalar = false,\n): PreparedGraphStarts {\n const starts = Array.isArray(start) ? [...start] : [start];\n if (starts.length === 0) {\n throw new TypeError(`${method} ${argument} must not be an empty array.`);\n }\n\n let family: \"string\" | \"numeric\" | undefined;\n const values: string[] = [];\n const numericValues: bigint[] = [];\n const seen = new Set<string>();\n const duplicates: GraphId[] = [];\n\n for (const value of starts) {\n const valueFamily =\n typeof value === \"string\"\n ? \"string\"\n : typeof value === \"number\" || typeof value === \"bigint\"\n ? \"numeric\"\n : undefined;\n if (valueFamily === undefined) {\n throw new TypeError(\n scalar\n ? `${method} ${argument} must be a string or a whole number.`\n : `${method} ${argument} must be a string, a whole number, or an array of those values.`,\n );\n }\n if (family !== undefined && family !== valueFamily) {\n throw new TypeError(`${method} ${argument} must not mix string and numeric IDs.`);\n }\n family = valueFamily;\n\n let encoded: string;\n if (typeof value === \"number\") {\n if (!Number.isSafeInteger(value)) {\n throw new TypeError(\n `${method} ${argument} contains ${value}, which is not a safe whole number. Use a bigint for exact integer IDs outside JavaScript's safe integer range.`,\n );\n }\n encoded = BigInt(value).toString();\n numericValues.push(BigInt(value));\n } else if (typeof value === \"bigint\") {\n encoded = value.toString();\n numericValues.push(value);\n } else {\n encoded = value;\n }\n\n const key = `${valueFamily}:${encoded}`;\n if (seen.has(key)) {\n if (!duplicates.some((duplicate) => graphIdsEqual(duplicate, value))) {\n duplicates.push(value);\n }\n } else {\n seen.add(key);\n values.push(encoded);\n }\n }\n\n if (duplicates.length > 0) {\n throw new TypeError(\n `${method} ${argument} contains duplicate IDs: ${duplicates.map(formatGraphId).join(\", \")}.`,\n );\n }\n\n return { family: family!, numericValues, values };\n}\n\nfunction graphIdsEqual(left: GraphId, right: GraphId): boolean {\n if (typeof left === \"string\" || typeof right === \"string\") {\n return left === right;\n }\n return BigInt(left) === BigInt(right);\n}\n\nfunction formatGraphId(value: GraphId): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n return typeof value === \"bigint\" ? `${value}n` : String(value);\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\n\nexport type GraphEndpointColumns = {\n source: string;\n target: string;\n idType: string;\n family: \"string\" | \"numeric\";\n floating: boolean;\n};\n\ntype IntegerType = {\n signed: boolean;\n bits: 8 | 16 | 32 | 64 | 128;\n digits: number;\n};\n\nconst integerTypes: Record<string, IntegerType> = {\n TINYINT: { signed: true, bits: 8, digits: 3 },\n SMALLINT: { signed: true, bits: 16, digits: 5 },\n INTEGER: { signed: true, bits: 32, digits: 10 },\n BIGINT: { signed: true, bits: 64, digits: 19 },\n HUGEINT: { signed: true, bits: 128, digits: 39 },\n UTINYINT: { signed: false, bits: 8, digits: 3 },\n USMALLINT: { signed: false, bits: 16, digits: 5 },\n UINTEGER: { signed: false, bits: 32, digits: 10 },\n UBIGINT: { signed: false, bits: 64, digits: 20 },\n UHUGEINT: { signed: false, bits: 128, digits: 39 },\n};\n\n/** Resolves and validates a graph's endpoint columns from an existing schema. */\nexport default function getGraphEndpointColumns(\n schema: TableSchema,\n requestedSource: string,\n requestedTarget: string,\n method: string,\n): GraphEndpointColumns {\n const source = findColumn(schema, requestedSource);\n const target = findColumn(schema, requestedTarget);\n const missing = [\n source === undefined ? requestedSource : undefined,\n target === undefined ? requestedTarget : undefined,\n ].filter((column): column is string => column !== undefined);\n if (missing.length > 0) {\n const plural = missing.length > 1;\n throw new Error(\n `${method} the column${plural ? \"s\" : \"\"} ${missing.map(quoteIdentifier).join(\", \")} ${\n plural ? \"do\" : \"does\"\n } not exist. Check for typos, or load the data first.`,\n );\n }\n\n const sourceType = normalizeType(schema[source!]);\n const targetType = normalizeType(schema[target!]);\n const sourceKind = typeKind(sourceType);\n const targetKind = typeKind(targetType);\n if (sourceKind === undefined || targetKind === undefined) {\n const unsupported =\n sourceKind === undefined\n ? { column: source!, type: sourceType }\n : { column: target!, type: targetType };\n throw new TypeError(\n `${method} requires string or numeric endpoint IDs, but column ${quoteIdentifier(\n unsupported.column,\n )} has type ${unsupported.type}.`,\n );\n }\n if (sourceKind.family !== targetKind.family) {\n throw new TypeError(\n `${method} requires compatible source and target ID types, but ${quoteIdentifier(\n source!,\n )} has type ${sourceType} and ${quoteIdentifier(target!)} has type ${targetType}.`,\n );\n }\n\n if (sourceKind.family === \"string\") {\n return {\n source: source!,\n target: target!,\n idType: \"VARCHAR\",\n family: \"string\",\n floating: false,\n };\n }\n\n const idType = compatibleNumericType(sourceType, targetType);\n if (idType === undefined) {\n throw new TypeError(\n `${method} cannot combine endpoint types ${sourceType} and ${targetType} without losing ID precision. Convert both columns to one compatible exact numeric type first.`,\n );\n }\n return {\n source: source!,\n target: target!,\n idType,\n family: \"numeric\",\n floating: isFloating(sourceType) || isFloating(targetType),\n };\n}\n\nfunction findColumn(schema: TableSchema, requested: string): string | undefined {\n const folded = foldIdentifier(requested);\n return Object.keys(schema).find((column) => foldIdentifier(column) === folded);\n}\n\nfunction normalizeType(type: string): string {\n return type.toUpperCase().replace(/^REAL$/, \"FLOAT\");\n}\n\nfunction typeKind(type: string): { family: \"string\" } | { family: \"numeric\" } | undefined {\n if (type === \"VARCHAR\") return { family: \"string\" };\n if (\n integerTypes[type] !== undefined ||\n isDecimal(type) ||\n isFloating(type) ||\n type === \"BIGNUM\"\n ) {\n return { family: \"numeric\" };\n }\n return undefined;\n}\n\nfunction compatibleNumericType(left: string, right: string): string | undefined {\n if (left === right) return left;\n if (isFloating(left) || isFloating(right)) {\n return isFloating(left) && isFloating(right) ? \"DOUBLE\" : undefined;\n }\n if (left === \"BIGNUM\" || right === \"BIGNUM\") {\n const other = left === \"BIGNUM\" ? right : left;\n return integerTypes[other] !== undefined || decimalScale(other) === 0 ? \"BIGNUM\" : undefined;\n }\n\n const leftInteger = integerTypes[left];\n const rightInteger = integerTypes[right];\n if (leftInteger !== undefined && rightInteger !== undefined) {\n return commonIntegerType(leftInteger, rightInteger);\n }\n\n const leftDecimal = parseDecimal(left);\n const rightDecimal = parseDecimal(right);\n if (leftDecimal === undefined && rightDecimal === undefined) return undefined;\n const scale = Math.max(leftDecimal?.scale ?? 0, rightDecimal?.scale ?? 0);\n const integerDigits = Math.max(\n leftDecimal === undefined ? leftInteger!.digits : leftDecimal.precision - leftDecimal.scale,\n rightDecimal === undefined ? rightInteger!.digits : rightDecimal.precision - rightDecimal.scale,\n );\n const precision = integerDigits + scale;\n return precision <= 38 ? `DECIMAL(${precision},${scale})` : undefined;\n}\n\nfunction commonIntegerType(left: IntegerType, right: IntegerType): string | undefined {\n if (left.signed === right.signed) {\n const bits = Math.max(left.bits, right.bits);\n return integerTypeName(left.signed, bits);\n }\n const signed = left.signed ? left : right;\n const unsigned = left.signed ? right : left;\n const requiredBits = Math.max(signed.bits, nextBits(unsigned.bits));\n return requiredBits > 128 ? undefined : integerTypeName(true, requiredBits);\n}\n\nfunction nextBits(bits: number): number {\n if (bits <= 8) return 16;\n if (bits <= 16) return 32;\n if (bits <= 32) return 64;\n if (bits <= 64) return 128;\n return 256;\n}\n\nfunction integerTypeName(signed: boolean, bits: number): string | undefined {\n const names = signed\n ? {\n 8: \"TINYINT\",\n 16: \"SMALLINT\",\n 32: \"INTEGER\",\n 64: \"BIGINT\",\n 128: \"HUGEINT\",\n }\n : {\n 8: \"UTINYINT\",\n 16: \"USMALLINT\",\n 32: \"UINTEGER\",\n 64: \"UBIGINT\",\n 128: \"UHUGEINT\",\n };\n return names[bits as keyof typeof names];\n}\n\nfunction isFloating(type: string): boolean {\n return type === \"FLOAT\" || type === \"DOUBLE\";\n}\n\nfunction isDecimal(type: string): boolean {\n return /^DECIMAL\\(\\d+,\\d+\\)$/.test(type);\n}\n\nfunction parseDecimal(type: string): { precision: number; scale: number } | undefined {\n const match = /^DECIMAL\\((\\d+),(\\d+)\\)$/.exec(type);\n return match === null ? undefined : { precision: Number(match[1]), scale: Number(match[2]) };\n}\n\nfunction decimalScale(type: string): number | undefined {\n return parseDecimal(type)?.scale;\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport getGraphEndpointColumns, { type GraphEndpointColumns } from \"./getGraphEndpointColumns.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport type { PreparedGraphStarts } from \"./prepareGraphStarts.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type GraphDirection = \"outgoing\" | \"incoming\" | \"both\";\n\nexport type PreparedGraphTraversal = {\n edges: (direction: GraphDirection, selections?: string[]) => string;\n endpoints: GraphEndpointColumns;\n key: (expression: string) => string;\n relationNames: (names: string[]) => Record<string, string>;\n startValues: string;\n};\n\nexport type PreparedGraphSql = Omit<PreparedGraphTraversal, \"startValues\">;\n\n/** Prepares exact-ID SQL shared by graph traversal methods. */\nexport default function prepareGraphTraversal(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n method: string,\n argument = \"start\",\n): PreparedGraphTraversal {\n const endpoints = validateGraphStarts(schema, source, target, starts, method, argument);\n return {\n ...prepareGraphSqlFromEndpoints(input, endpoints),\n startValues: starts.values.map(() => `(TRY_CAST(? AS ${endpoints.idType}))`).join(\", \"),\n };\n}\n\n/** Prepares exact-ID edge SQL for graph methods without starting nodes. */\nexport function prepareGraphSql(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n method: string,\n): PreparedGraphSql {\n return prepareGraphSqlFromEndpoints(\n input,\n getGraphEndpointColumns(schema, source, target, method),\n );\n}\n\nfunction prepareGraphSqlFromEndpoints(\n input: string,\n endpoints: GraphEndpointColumns,\n): PreparedGraphSql {\n const sourceColumn = quoteIdentifier(endpoints.source);\n const targetColumn = quoteIdentifier(endpoints.target);\n const idType = endpoints.idType;\n const cast = (expression: string) => `CAST(${expression} AS ${idType})`;\n const key =\n endpoints.family === \"string\" ? (expression: string) => `ENCODE(${cast(expression)})` : cast;\n const edge = (from: string, to: string, selections: string[]) =>\n `SELECT ${cast(from)} AS ${quoteIdentifier(\"__from\")},\n ${cast(to)} AS ${quoteIdentifier(\"__to\")},\n ${key(from)} AS ${quoteIdentifier(\"__from_key\")},\n ${key(to)} AS ${quoteIdentifier(\"__to_key\")}${\n selections.length === 0 ? \"\" : `,\\n ${selections.join(\",\\n \")}`\n }\n FROM ${input} AS ${quoteIdentifier(\"edges\")}`;\n const sourceReference = `${quoteIdentifier(\"edges\")}.${sourceColumn}`;\n const targetReference = `${quoteIdentifier(\"edges\")}.${targetColumn}`;\n return {\n endpoints,\n key,\n edges: (direction, selections = []) =>\n direction === \"outgoing\"\n ? edge(sourceReference, targetReference, selections)\n : direction === \"incoming\"\n ? edge(targetReference, sourceReference, selections)\n : `${edge(sourceReference, targetReference, selections)}\\nUNION ALL\\n${edge(\n targetReference,\n sourceReference,\n selections,\n )}`,\n relationNames: (names) => uniqueRelationNames(input, names),\n };\n}\n\n/** Validates supplied starts against resolved endpoint ID types. */\nexport function validateGraphStarts(\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n method: string,\n argument = \"start\",\n): GraphEndpointColumns {\n const endpoints = getGraphEndpointColumns(schema, source, target, method);\n const verb = argument === \"start\" ? \"contains\" : \"contain\";\n if (endpoints.family !== starts.family) {\n throw new TypeError(\n `${method} ${argument} ${verb} ${starts.family} IDs, but endpoint columns ${quoteIdentifier(\n endpoints.source,\n )} and ${quoteIdentifier(endpoints.target)} contain ${endpoints.family} IDs.`,\n );\n }\n if (endpoints.floating) {\n for (const value of starts.numericValues) {\n const converted = endpoints.idType === \"FLOAT\" ? Math.fround(Number(value)) : Number(value);\n if (!Number.isFinite(converted) || BigInt(converted) !== value) {\n throw new TypeError(\n `${method} ${argument} ${verb} ${value}n, which ${endpoints.idType} cannot represent exactly.`,\n );\n }\n }\n }\n return endpoints;\n}\n\nfunction uniqueRelationNames(input: string, requestedNames: string[]): Record<string, string> {\n const used = new Set([foldIdentifier(input)]);\n const names: Record<string, string> = {};\n for (const requested of requestedNames) {\n let candidate = requested;\n let suffix = 1;\n while (used.has(foldIdentifier(quoteIdentifier(candidate)))) {\n candidate = `${requested}_${suffix}`;\n suffix++;\n }\n const quoted = quoteIdentifier(candidate);\n used.add(foldIdentifier(quoted));\n names[requested] = quoted;\n }\n return names;\n}\n","import type { DuckDBValue } from \"@duckdb/node-api\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport queueOp from \"./queueOp.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport resolveOutputTable from \"./resolveOutputTable.ts\";\n\ntype GraphResult = {\n buildSelect: (input: string, schema: TableSchema) => string;\n method: string;\n outputSchema: (schema: TableSchema) => TableSchema;\n outputTable?: string | boolean;\n parameters: { [key: string]: unknown };\n preflight?: (input: SimpleTable) => Promise<void>;\n values: (schema: TableSchema) => DuckDBValue[];\n};\n\n/** Queues a graph SELECT for overwrite or a source-preserving output table. */\nexport default function queueGraphResult(\n simpleTable: SimpleTable,\n result: GraphResult,\n): SimpleTable {\n const resolvedOutput = resolveOutputTable(simpleTable, result.outputTable);\n const outputTable =\n typeof resolvedOutput === \"string\" ? simpleTable.sdb.newTable(resolvedOutput) : simpleTable;\n\n if (outputTable !== simpleTable) {\n queueOp(outputTable, {\n kind: \"source\",\n method: result.method,\n parameters: result.parameters,\n rawSQL: [quoteIdentifier(simpleTable.name)],\n buildSelect: () => `SELECT * FROM ${quoteIdentifier(simpleTable.name)}`,\n });\n }\n\n // A separate barrier keeps invalid-event checks observable after LIMIT 0.\n const preflight = result.preflight;\n if (preflight !== undefined) {\n queueOp(outputTable, {\n kind: \"barrier\",\n method: result.method,\n parameters: result.parameters,\n execute: () => preflight(outputTable),\n });\n }\n\n queueOp(outputTable, {\n kind: \"fusable\",\n method: result.method,\n parameters: result.parameters,\n needsSchema: true,\n values: result.values,\n buildSelect: result.buildSelect,\n outputSchema: result.outputSchema,\n });\n return outputTable;\n}\n","import prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTraversal, {\n type GraphDirection,\n validateGraphStarts,\n} from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\n\ntype NeighborsOptions = {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n outputTable?: string | boolean;\n};\n\nexport default function neighbors(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n startNodes: GraphId | GraphId[],\n options: NeighborsOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"neighbors() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"neighbors() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"neighbors() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError('neighbors() options.direction must be \"outgoing\", \"incoming\", or \"both\".');\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"neighbors() options.outputTable must be a string or boolean.\");\n }\n\n const preparedStarts = prepareGraphStarts(startNodes, \"neighbors()\", \"startNodes\");\n options = structuredClone(options);\n const direction = options.direction ?? \"outgoing\";\n const parameters = {\n sourceColumn,\n targetColumn,\n startNodes: structuredClone(startNodes),\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"neighbors()\",\n parameters,\n outputTable: options.outputTable,\n values: (schema) => {\n validateStarts(schema, sourceColumn, targetColumn, preparedStarts);\n return preparedStarts.values;\n },\n buildSelect: (input, schema) =>\n neighborsSelect(input, schema, sourceColumn, targetColumn, preparedStarts, direction),\n outputSchema: (schema) => {\n const endpoints = validateStarts(schema, sourceColumn, targetColumn, preparedStarts);\n return { start: endpoints.idType, node: endpoints.idType };\n },\n });\n}\n\nfunction validateStarts(\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n) {\n return validateGraphStarts(schema, source, target, starts, \"neighbors()\", \"startNodes\");\n}\n\nfunction neighborsSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n direction: GraphDirection,\n): string {\n const prepared = prepareGraphTraversal(\n input,\n schema,\n source,\n target,\n starts,\n \"neighbors()\",\n \"startNodes\",\n );\n const relations = prepared.relationNames([\"graph_starts\", \"graph_edges\", \"neighbor_matches\"]);\n const startsRelation = relations.graph_starts;\n const edgesRelation = relations.graph_edges;\n const matchesRelation = relations.neighbor_matches;\n\n return `WITH ${startsRelation}(${quoteIdentifier(\"start\")}) AS (\n VALUES ${prepared.startValues}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction)}\n ), ${matchesRelation} AS (\n SELECT ${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"start\")},\n ${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to\")} AS ${quoteIdentifier(\"node\")},\n ${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__from_key\")} AS ${quoteIdentifier(\n \"__start_key\",\n )},\n ${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to_key\")} AS ${quoteIdentifier(\n \"__node_key\",\n )}\n FROM ${edgesRelation} AS ${quoteIdentifier(\"edges\")}\n INNER JOIN ${startsRelation} AS ${quoteIdentifier(\"starts\")}\n ON ${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__from_key\")} =\n ${prepared.key(`${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"start\")}`)}\n )\n SELECT ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\"node\")}\n FROM (\n SELECT DISTINCT ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\n \"node\",\n )}, ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")}\n FROM ${matchesRelation}\n ) AS ${quoteIdentifier(\"distinct_neighbors\")}\n ORDER BY ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")}`;\n}\n","import type { PreparedGraphTemporalSql } from \"./prepareGraphTemporalSql.ts\";\nimport type { GraphDirection, PreparedGraphSql } from \"./prepareGraphTraversal.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type GraphTemporalReachabilitySql = {\n edgesRelation: string;\n reachableRelation: string;\n withClause: string;\n};\n\n/**\n * Builds reusable chronological reachability CTEs from a start relation.\n * A callback may derive all-node starts from the materialized valid edges.\n */\nexport default function buildGraphTemporalReachabilitySql(\n prepared: PreparedGraphSql,\n startsSelect: string | ((validEdgesRelation: string) => string),\n direction: Exclude<GraphDirection, \"both\">,\n temporal: PreparedGraphTemporalSql,\n): GraphTemporalReachabilitySql {\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_starts\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_reachable_states\",\n ]);\n const startsRelation = relations.graph_starts;\n const settingsRelation = relations.graph_temporal_settings;\n const eventRowsRelation = relations.graph_event_rows;\n const edgesRelation = relations.graph_edges;\n const reachableRelation = relations.graph_reachable_states;\n const start = `${q(\"starts\")}.${q(\"start\")}`;\n const startKey = `${q(\"starts\")}.${q(\"__key\")}`;\n const reachedStart = `${q(\"reached\")}.${q(\"start\")}`;\n const reachedStartKey = `${q(\"reached\")}.${q(\"__start_key\")}`;\n const reachedNodeKey = `${q(\"reached\")}.${q(\"__node_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const eventId = `${q(\"edges\")}.${q(\"__event_id\")}`;\n const eventStart = `${q(\"edges\")}.${q(\"__event_start\")}`;\n const eventEnd = `${q(\"edges\")}.${q(\"__event_end\")}`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const resolvedStartsSelect =\n typeof startsSelect === \"string\" ? startsSelect : startsSelect(edgesRelation);\n\n // Materialized event IDs stay fixed; UNION bounds states to starts × events,\n // including equal-time cycles, because the last event determines all next steps.\n return {\n edgesRelation,\n reachableRelation,\n withClause: `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (\n SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}\n ), ${eventRowsRelation} AS MATERIALIZED (\n ${prepared.edges(direction, temporal.eventSelections(\"edges\"))}\n ), ${edgesRelation} AS MATERIALIZED (\n SELECT *\n FROM ${eventRowsRelation} AS ${q(\"events\")}\n WHERE ${temporal.eventValidity(\"events\")}\n ), ${startsRelation} AS MATERIALIZED (\n ${resolvedStartsSelect}\n ), ${reachableRelation}(\n ${q(\"start\")}, ${q(\"node\")},\n ${q(\"__start_key\")}, ${q(\"__node_key\")},\n ${q(\"__event_id\")}, ${q(\"__event_start\")}, ${q(\"__event_end\")}\n ) AS (\n SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}\n FROM ${startsRelation} AS ${q(\"starts\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${startKey} = ${edgeFromKey}\n UNION\n SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}\n FROM ${reachableRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${reachedNodeKey} = ${edgeFromKey}\n CROSS JOIN ${settingsRelation} AS ${q(\"settings\")}\n WHERE ${temporal.transition(\"reached\", \"edges\", direction, gap)}\n )`,\n };\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport type { GraphDirection } from \"./prepareGraphTraversal.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type GraphTemporalOptions = {\n endTimeColumn?: string;\n minGapMs?: number;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n};\n\nexport type PreparedGraphTemporalOptions = {\n endTimeColumn?: string;\n gapMicroseconds: bigint;\n startTimeColumn?: string;\n strictOrdering: boolean;\n};\n\nexport type PreparedGraphTemporalSql = {\n endTimeColumn?: string;\n eventSelections: (tableAlias?: string) => string[];\n eventValidity: (tableAlias?: string) => string;\n gapParameter: string;\n gapUnit: \"microsecond\" | \"nanosecond\";\n journeyAnchor: (alias: string, direction: Exclude<GraphDirection, \"both\">) => string;\n journeyElapsed: (\n alias: string,\n anchor: string,\n direction: Exclude<GraphDirection, \"both\">,\n ) => string;\n elapsedMilliseconds: (elapsed: string) => string;\n startTimeColumn?: string;\n transition: (\n currentAlias: string,\n candidateAlias: string,\n direction: Exclude<GraphDirection, \"both\">,\n gapExpression: string,\n ) => string;\n};\n\nconst temporalTypes = new Set([\n \"DATE\",\n \"TIMESTAMP\",\n \"TIMESTAMP_S\",\n \"TIMESTAMP_MS\",\n \"TIMESTAMP_NS\",\n \"TIMESTAMP WITH TIME ZONE\",\n]);\n\n/** Validates chronological options before a graph operation is queued. */\nexport function prepareGraphTemporalOptions(\n options: GraphTemporalOptions,\n direction: GraphDirection | undefined,\n method: string,\n): PreparedGraphTemporalOptions | undefined {\n const startTimeColumn = options.startTimeColumn;\n const endTimeColumn = options.endTimeColumn;\n if (startTimeColumn !== undefined && typeof startTimeColumn !== \"string\") {\n throw new TypeError(`${method} options.startTimeColumn must be a string.`);\n }\n if (endTimeColumn !== undefined && typeof endTimeColumn !== \"string\") {\n throw new TypeError(`${method} options.endTimeColumn must be a string.`);\n }\n if (options.strictOrdering !== undefined && typeof options.strictOrdering !== \"boolean\") {\n throw new TypeError(`${method} options.strictOrdering must be a boolean.`);\n }\n if (options.minGapMs !== undefined && typeof options.minGapMs !== \"number\") {\n throw new TypeError(`${method} options.minGapMs must be a number.`);\n }\n\n const hasTimeColumn = startTimeColumn !== undefined || endTimeColumn !== undefined;\n const hasTemporalSetting = options.minGapMs !== undefined || options.strictOrdering !== undefined;\n if (!hasTimeColumn) {\n if (hasTemporalSetting) {\n throw new TypeError(\n `${method} options.minGapMs and options.strictOrdering require options.startTimeColumn or options.endTimeColumn.`,\n );\n }\n return undefined;\n }\n if (direction === \"both\") {\n throw new TypeError(\n `${method} options.direction cannot be \"both\" when chronological options are supplied.`,\n );\n }\n\n const minGapMs = options.minGapMs ?? 0;\n if (!Number.isFinite(minGapMs) || minGapMs < 0 || !Number.isInteger(minGapMs)) {\n throw new TypeError(`${method} options.minGapMs must be a finite, non-negative integer.`);\n }\n if (minGapMs > Number.MAX_SAFE_INTEGER) {\n throw new TypeError(`${method} options.minGapMs must not exceed Number.MAX_SAFE_INTEGER.`);\n }\n const gapMicroseconds = BigInt(minGapMs) * 1000n;\n\n return {\n endTimeColumn,\n gapMicroseconds,\n startTimeColumn,\n strictOrdering: options.strictOrdering ?? true,\n };\n}\n\n/** Prepares native-precision event and transition SQL from a queued schema. */\nexport default function prepareGraphTemporalSql(\n schema: TableSchema,\n options: PreparedGraphTemporalOptions,\n method: string,\n): PreparedGraphTemporalSql {\n const start =\n options.startTimeColumn === undefined\n ? undefined\n : getTemporalColumn(schema, options.startTimeColumn, method);\n const end =\n options.endTimeColumn === undefined\n ? undefined\n : getTemporalColumn(schema, options.endTimeColumn, method);\n if (start?.zoned !== undefined && end?.zoned !== undefined) {\n if (start.zoned !== end.zoned) {\n throw new TypeError(\n `${method} cannot mix time-zone-aware and time-zone-naive chronological columns. Convert both columns to the same timestamp domain first.`,\n );\n }\n }\n\n const startColumn = start?.column ?? end!.column;\n const endColumn = end?.column ?? start!.column;\n const startType = start?.type ?? end!.type;\n const endType = end?.type ?? start!.type;\n const gapUnit =\n start?.type === \"TIMESTAMP_NS\" || end?.type === \"TIMESTAMP_NS\" ? \"nanosecond\" : \"microsecond\";\n const gap = gapUnit === \"nanosecond\" ? options.gapMicroseconds * 1000n : options.gapMicroseconds;\n const q = quoteIdentifier;\n const reference = (alias: string | undefined, column: string) =>\n `${alias === undefined ? \"\" : `${q(alias)}.`}${q(column)}`;\n const eventReference = (alias: string | undefined, name: string) =>\n `${alias === undefined ? \"\" : `${q(alias)}.`}${q(name)}`;\n\n return {\n startTimeColumn: start?.column,\n endTimeColumn: end?.column,\n gapParameter: gap.toString(),\n gapUnit,\n journeyAnchor: (alias, direction) =>\n direction === \"outgoing\"\n ? temporalUnits(eventReference(alias, \"__event_start\"), startType, gapUnit)\n : temporalUnits(eventReference(alias, \"__event_end\"), endType, gapUnit),\n journeyElapsed: (alias, anchor, direction) =>\n direction === \"outgoing\"\n ? `(${temporalUnits(eventReference(alias, \"__event_end\"), endType, gapUnit)} - (${anchor}))`\n : `((${anchor}) - ${temporalUnits(\n eventReference(alias, \"__event_start\"),\n startType,\n gapUnit,\n )})`,\n elapsedMilliseconds: (elapsed) =>\n `(CAST(${elapsed} AS DOUBLE) / ${gapUnit === \"nanosecond\" ? 1000000 : 1000})`,\n eventSelections: (alias) => [\n `row_number() OVER () AS ${q(\"__event_id\")}`,\n `${reference(alias, startColumn)} AS ${q(\"__event_start\")}`,\n `${reference(alias, endColumn)} AS ${q(\"__event_end\")}`,\n ],\n eventValidity: (alias) => {\n const eventStart = eventReference(alias, \"__event_start\");\n const eventEnd = eventReference(alias, \"__event_end\");\n return `CASE\n WHEN ${eventStart} IS NULL OR ${eventEnd} IS NULL THEN false\n WHEN NOT isfinite(${eventStart}) OR NOT isfinite(${eventEnd}) THEN false\n ELSE ${temporalUnits(eventEnd, endType, gapUnit)} >= ${temporalUnits(\n eventStart,\n startType,\n gapUnit,\n )}\n END`;\n },\n transition: (currentAlias, candidateAlias, direction, gapExpression) => {\n const currentStart = eventReference(currentAlias, \"__event_start\");\n const currentEnd = eventReference(currentAlias, \"__event_end\");\n const candidateStart = eventReference(candidateAlias, \"__event_start\");\n const candidateEnd = eventReference(candidateAlias, \"__event_end\");\n const earlierEnd = direction === \"outgoing\" ? currentEnd : candidateEnd;\n const laterStart = direction === \"outgoing\" ? candidateStart : currentStart;\n const elapsed = `${temporalUnits(laterStart, startType, gapUnit)} - ${temporalUnits(\n earlierEnd,\n endType,\n gapUnit,\n )}`;\n const ordering = options.strictOrdering\n ? `\n AND ${elapsed} > 0`\n : \"\";\n return `${elapsed} >= ${gapExpression}${ordering}`;\n },\n };\n}\n\nfunction temporalUnits(\n expression: string,\n type: string,\n unit: \"microsecond\" | \"nanosecond\",\n): string {\n // Widen before scaling/subtraction to preserve precision and the DATE range.\n const scale = unit === \"nanosecond\" ? 1000n : 1n;\n if (type === \"DATE\") {\n return `(CAST(date_diff('day', DATE '1970-01-01', ${expression}) AS HUGEINT) * ${\n 86_400_000_000n * scale\n })`;\n }\n if (type === \"TIMESTAMP_NS\") {\n return `CAST(epoch_ns(${expression}) AS HUGEINT)`;\n }\n return `(CAST(epoch_us(${expression}) AS HUGEINT) * ${scale})`;\n}\n\nfunction getTemporalColumn(\n schema: TableSchema,\n requested: string,\n method: string,\n): { column: string; type: string; zoned: boolean } {\n const folded = foldIdentifier(requested);\n const column = Object.keys(schema).find((name) => foldIdentifier(name) === folded);\n if (column === undefined) {\n throw new Error(\n `${method} the column ${quoteIdentifier(\n requested,\n )} does not exist. Check for typos, or load the data first.`,\n );\n }\n const type = normalizeTemporalType(schema[column]);\n if (!temporalTypes.has(type)) {\n throw new TypeError(\n `${method} requires DATE or TIMESTAMP chronological columns, but column ${quoteIdentifier(\n column,\n )} has type ${schema[column].toUpperCase()}.`,\n );\n }\n return {\n column,\n type,\n zoned: type === \"TIMESTAMP WITH TIME ZONE\",\n };\n}\n\nfunction normalizeTemporalType(type: string): string {\n const normalized = type.toUpperCase();\n if (normalized === \"TIMESTAMPTZ\") return \"TIMESTAMP WITH TIME ZONE\";\n if (normalized === \"TIMESTAMP WITHOUT TIME ZONE\") return \"TIMESTAMP\";\n return normalized;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport prepareGraphTemporalSql, {\n type PreparedGraphTemporalOptions,\n} from \"./prepareGraphTemporalSql.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/** Rejects invalid selected timestamps before a chronological graph runs. */\nexport default async function validateGraphTemporalEvents(\n simpleTable: SimpleTable,\n options: PreparedGraphTemporalOptions,\n method: string,\n parameters: { [key: string]: unknown },\n): Promise<void> {\n const schema = await simpleTable.getTypes();\n const temporal = prepareGraphTemporalSql(schema, options, method);\n const q = quoteIdentifier;\n const eventsName = \"__graph_temporal_events\";\n const events = q(eventsName);\n const eventStart = `${events}.${q(\"__event_start\")}`;\n const eventEnd = `${events}.${q(\"__event_end\")}`;\n const rows = await queryDB(\n simpleTable,\n `SELECT CASE\n WHEN ${eventStart} IS NULL THEN 1\n WHEN ${eventEnd} IS NULL THEN 2\n WHEN NOT isfinite(${eventStart}) THEN 3\n WHEN NOT isfinite(${eventEnd}) THEN 4\n ELSE 5\n END AS ${q(\"reason\")}\n FROM (\n SELECT ${temporal.eventSelections().join(\", \")}\n FROM ${q(simpleTable.name)}\n ) AS ${events}\n WHERE (${temporal.eventValidity(eventsName)}) IS NOT TRUE\n LIMIT 1`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method,\n parameters,\n returnData: true,\n }),\n );\n const reason = rows?.[0]?.reason;\n if (reason === undefined) return;\n\n const startColumn = temporal.startTimeColumn ?? temporal.endTimeColumn!;\n const endColumn = temporal.endTimeColumn ?? temporal.startTimeColumn!;\n const message =\n reason === 1\n ? `selected start-time column ${q(startColumn)} contains a null timestamp.`\n : reason === 2\n ? `selected end-time column ${q(endColumn)} contains a null timestamp.`\n : reason === 3\n ? `selected start-time column ${q(startColumn)} contains an infinite timestamp.`\n : reason === 4\n ? `selected end-time column ${q(endColumn)} contains an infinite timestamp.`\n : `selected end-time column ${q(\n endColumn,\n )} contains a timestamp before its start in ${q(startColumn)}.`;\n throw new TypeError(`${method} ${message}`);\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport buildGraphTemporalReachabilitySql from \"../helpers/buildGraphTemporalReachabilitySql.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTraversal, {\n type GraphDirection,\n validateGraphStarts,\n} from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\n\ntype ReachableOptions = GraphTemporalOptions & {\n direction?: GraphDirection;\n outputTable?: string | boolean;\n};\n\nexport default function reachable(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n startNodes: GraphId | GraphId[],\n options: ReachableOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"reachable() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"reachable() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"reachable() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError('reachable() options.direction must be \"outgoing\", \"incoming\", or \"both\".');\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"reachable() options.outputTable must be a string or boolean.\");\n }\n\n const preparedStarts = prepareGraphStarts(startNodes, \"reachable()\", \"startNodes\");\n const direction = options.direction ?? \"outgoing\";\n const temporalOptions = prepareGraphTemporalOptions(options, direction, \"reachable()\");\n options = structuredClone(options);\n const parameters = {\n sourceColumn,\n targetColumn,\n startNodes: structuredClone(startNodes),\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"reachable()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) => validateGraphTemporalEvents(input, temporalOptions, \"reachable()\", parameters),\n values: (schema) => {\n const { temporal } = validateInputs(\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n temporalOptions,\n );\n return temporal === undefined\n ? preparedStarts.values\n : [temporal.gapParameter, ...preparedStarts.values];\n },\n buildSelect: (input, schema) =>\n reachableSelect(\n input,\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n direction,\n temporalOptions,\n ),\n outputSchema: (schema) => {\n const { endpoints } = validateInputs(\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n temporalOptions,\n );\n return {\n start: endpoints.idType,\n node: endpoints.idType,\n };\n },\n });\n}\n\nfunction validateInputs(\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n) {\n const endpoints = validateGraphStarts(\n schema,\n source,\n target,\n starts,\n \"reachable()\",\n \"startNodes\",\n );\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"reachable()\");\n return { endpoints, temporal };\n}\n\nfunction reachableSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n direction: GraphDirection,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n): string {\n const prepared = prepareGraphTraversal(\n input,\n schema,\n source,\n target,\n starts,\n \"reachable()\",\n \"startNodes\",\n );\n if (temporalOptions !== undefined) {\n const temporal = prepareGraphTemporalSql(schema, temporalOptions, \"reachable()\");\n return temporalReachableSelect(\n prepared,\n direction as Exclude<GraphDirection, \"both\">,\n temporal,\n );\n }\n const relations = prepared.relationNames([\n \"graph_start_values\",\n \"graph_starts\",\n \"graph_edges\",\n \"graph_reachable\",\n ]);\n const startValuesRelation = relations.graph_start_values;\n const startsRelation = relations.graph_starts;\n const edgesRelation = relations.graph_edges;\n const reachableRelation = relations.graph_reachable;\n const start = `${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"start\")}`;\n const startKey = `${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"__key\")}`;\n const reachedStart = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"start\")}`;\n const reachedStartKey = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"__start_key\")}`;\n const edgeTo = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to\")}`;\n const edgeToKey = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to_key\")}`;\n const edgeFromKey = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__from_key\")}`;\n const reachedNodeKey = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"__node_key\")}`;\n\n return `WITH RECURSIVE ${startValuesRelation}(${quoteIdentifier(\"start\")}) AS (\n VALUES ${prepared.startValues}\n ), ${startsRelation} AS (\n SELECT ${quoteIdentifier(\"start\")},\n ${prepared.key(quoteIdentifier(\"start\"))} AS ${quoteIdentifier(\"__key\")}\n FROM ${startValuesRelation}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction)}\n ), ${reachableRelation}(\n ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\"node\")},\n ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")}\n ) AS (\n SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey}\n FROM ${startsRelation} AS ${quoteIdentifier(\"starts\")}\n INNER JOIN ${edgesRelation} AS ${quoteIdentifier(\"edges\")}\n ON ${startKey} = ${edgeFromKey}\n UNION\n SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey}\n FROM ${reachableRelation} AS ${quoteIdentifier(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${quoteIdentifier(\"edges\")}\n ON ${reachedNodeKey} = ${edgeFromKey}\n )\n SELECT ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\"node\")}\n FROM ${reachableRelation}\n ORDER BY ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")}`;\n}\n\nfunction temporalReachableSelect(\n prepared: ReturnType<typeof prepareGraphTraversal>,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n): string {\n const q = quoteIdentifier;\n const startsSelect = `SELECT ${q(\"start\")},\n ${prepared.key(q(\"start\"))} AS ${q(\"__key\")}\n FROM (VALUES ${prepared.startValues}) AS ${q(\"start_values\")}(${q(\"start\")})`;\n const reachability = buildGraphTemporalReachabilitySql(\n prepared,\n startsSelect,\n direction,\n temporal,\n );\n return `${reachability.withClause}\n SELECT ${q(\"start\")}, ${q(\"node\")}\n FROM (\n SELECT DISTINCT ${q(\"start\")}, ${q(\"node\")},\n ${q(\"__start_key\")}, ${q(\"__node_key\")}\n FROM ${reachability.reachableRelation}\n ) AS ${q(\"reachable_nodes\")}\n ORDER BY ${q(\"__start_key\")}, ${q(\"__node_key\")}`;\n}\n","import type { PreparedGraphTemporalSql } from \"./prepareGraphTemporalSql.ts\";\nimport type { GraphDirection, PreparedGraphSql } from \"./prepareGraphTraversal.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type GraphTemporalCostStateSql = {\n costRelation: string;\n edgesRelation: string;\n settingsRelation: string;\n startsRelation: string;\n withClause: string;\n};\n\n/** Builds keyed best-cost chronological states from an arbitrary start relation. */\nexport default function buildGraphTemporalCostStateSql(\n prepared: PreparedGraphSql,\n startsSelect: string | ((validEdgesRelation: string) => string),\n direction: Exclude<GraphDirection, \"both\">,\n temporal: PreparedGraphTemporalSql,\n distanceType: string,\n edgeWeight: string,\n eventSelections: string[] = [],\n minimize: \"weight\" | \"steps\" = \"weight\",\n): GraphTemporalCostStateSql {\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_starts\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_cost_states\",\n ]);\n const startsRelation = relations.graph_starts;\n const settingsRelation = relations.graph_temporal_settings;\n const eventRowsRelation = relations.graph_event_rows;\n const edgesRelation = relations.graph_edges;\n const costRelation = relations.graph_cost_states;\n const start = `${q(\"starts\")}.${q(\"start\")}`;\n const startKey = `${q(\"starts\")}.${q(\"__key\")}`;\n const reachedStart = `${q(\"reached\")}.${q(\"start\")}`;\n const reachedStartKey = `${q(\"reached\")}.${q(\"__start_key\")}`;\n const reachedNodeKey = `${q(\"reached\")}.${q(\"__node_key\")}`;\n const reachedDistance = `${q(\"reached\")}.${q(\"distance\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const eventId = `${q(\"edges\")}.${q(\"__event_id\")}`;\n const eventStart = `${q(\"edges\")}.${q(\"__event_start\")}`;\n const eventEnd = `${q(\"edges\")}.${q(\"__event_end\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const bestDistance = `${q(\"best\")}.${q(\"distance\")}`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const candidateSteps = `${q(\"reached\")}.${q(\"steps\")} + 1`;\n // A steps-only bound must not sum reported weights: discarded routes can\n // overflow even when every optimal route's reported total is representable.\n const firstDistance = minimize === \"steps\" ? \"CAST(1 AS BIGINT)\" : edgeCost;\n const candidateDistance =\n minimize === \"steps\"\n ? candidateSteps\n : `CAST(${reachedDistance} + ${edgeCost} AS ${distanceType})`;\n const bestSteps = `${q(\"best\")}.${q(\"steps\")}`;\n const order = (distance: string, steps: string) =>\n minimize === \"steps\" ? `ROW(${steps}, ${distance})` : `ROW(${distance}, ${steps})`;\n const candidateOrder = order(candidateDistance, candidateSteps);\n const selectedDistance = `arg_min(${candidateDistance}, ${candidateOrder})`;\n const selectedSteps = `arg_min(${candidateSteps}, ${candidateOrder})`;\n const resolvedStartsSelect =\n typeof startsSelect === \"string\" ? startsSelect : startsSelect(edgesRelation);\n\n // Only states for the same start and physical event can dominate each other.\n // Weight optimization orders by cost then steps; step optimization counts\n // only connections. Strict improvements terminate even zero-cost cycles.\n return {\n costRelation,\n edgesRelation,\n settingsRelation,\n startsRelation,\n withClause: `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (\n SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}\n ), ${eventRowsRelation} AS MATERIALIZED (\n ${prepared.edges(direction, [\n `${edgeWeight} AS ${q(\"__weight\")}`,\n ...eventSelections,\n ...temporal.eventSelections(\"edges\"),\n ])}\n ), ${edgesRelation} AS MATERIALIZED (\n SELECT *\n FROM ${eventRowsRelation} AS ${q(\"events\")}\n WHERE ${temporal.eventValidity(\"events\")}\n ), ${startsRelation} AS MATERIALIZED (\n ${resolvedStartsSelect}\n ), ${costRelation}(\n ${q(\"start\")}, ${q(\"node\")},\n ${q(\"__start_key\")}, ${q(\"__node_key\")},\n ${q(\"__event_id\")}, ${q(\"__event_start\")}, ${q(\"__event_end\")},\n ${q(\"distance\")}, ${q(\"steps\")}\n ) USING KEY(${q(\"__start_key\")}, ${q(\"__event_id\")}) AS (\n SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}, ${firstDistance}, CAST(1 AS BIGINT)\n FROM ${startsRelation} AS ${q(\"starts\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${startKey} = ${edgeFromKey}\n UNION\n SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd},\n ${selectedDistance} AS ${q(\"distance\")}, ${selectedSteps} AS ${q(\"steps\")}\n FROM ${costRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${reachedNodeKey} = ${edgeFromKey}\n CROSS JOIN ${settingsRelation} AS ${q(\"settings\")}\n LEFT JOIN recurring.${costRelation} AS ${q(\"best\")}\n ON ${reachedStartKey} = ${q(\"best\")}.${q(\"__start_key\")}\n AND ${eventId} = ${q(\"best\")}.${q(\"__event_id\")}\n WHERE ${temporal.transition(\"reached\", \"edges\", direction, gap)}\n GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}, ${bestDistance}, ${bestSteps}\n HAVING ${bestDistance} IS NULL OR\n ${order(selectedDistance, selectedSteps)} < ${order(bestDistance, bestSteps)}\n )`,\n };\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\ntype GraphWeightColumn = {\n column: string;\n distanceType: string;\n type: string;\n};\n\nconst integerTypes = new Set([\n \"TINYINT\",\n \"SMALLINT\",\n \"INTEGER\",\n \"BIGINT\",\n \"UTINYINT\",\n \"USMALLINT\",\n \"UINTEGER\",\n \"UBIGINT\",\n]);\nconst wideIntegerTypes = new Set([\"HUGEINT\", \"UHUGEINT\", \"BIGNUM\"]);\n\n/** Resolves a numeric graph weight and a precision-preserving sum type. */\nexport default function getGraphWeightColumn(\n schema: TableSchema,\n requestedWeight: string,\n method: string,\n): GraphWeightColumn {\n const folded = foldIdentifier(requestedWeight);\n const column = Object.keys(schema).find((name) => foldIdentifier(name) === folded);\n if (column === undefined) {\n throw new Error(\n `${method} the column ${quoteIdentifier(\n requestedWeight,\n )} does not exist. Check for typos, or load the data first.`,\n );\n }\n\n const type = schema[column].toUpperCase().replace(/^REAL$/, \"FLOAT\");\n if (integerTypes.has(type)) {\n return { column, type, distanceType: \"HUGEINT\" };\n }\n if (wideIntegerTypes.has(type)) {\n return { column, type, distanceType: \"BIGNUM\" };\n }\n if (type === \"FLOAT\" || type === \"DOUBLE\") {\n return { column, type, distanceType: type };\n }\n\n const decimal = /^DECIMAL\\((\\d+),(\\d+)\\)$/.exec(type);\n if (decimal !== null) {\n return {\n column,\n type,\n distanceType: `DECIMAL(38,${Number(decimal[2])})`,\n };\n }\n\n throw new TypeError(\n `${method} requires a numeric weight column, but column ${quoteIdentifier(\n column,\n )} has type ${type}.`,\n );\n}\n","export type GraphMetricOptions = {\n elapsedTime?: boolean;\n minimize?: \"steps\" | \"weight\" | \"elapsedTime\";\n weight?: string;\n startTimeColumn?: string;\n endTimeColumn?: string;\n};\n\nexport type PreparedGraphMetricOptions = {\n elapsedTime: boolean;\n minimize: \"steps\" | \"weight\" | \"elapsedTime\";\n};\n\n/** Resolves graph cost selection separately from optional elapsed-time reporting. */\nexport default function prepareGraphMetricOptions(\n options: GraphMetricOptions,\n method: string,\n optimize: boolean,\n): PreparedGraphMetricOptions {\n if (options.elapsedTime !== undefined && typeof options.elapsedTime !== \"boolean\") {\n throw new TypeError(`${method} options.elapsedTime must be a boolean.`);\n }\n const elapsedTime = options.elapsedTime === true;\n if (\n elapsedTime &&\n (options.startTimeColumn === undefined || options.endTimeColumn === undefined)\n ) {\n throw new TypeError(\n `${method} options.elapsedTime requires both options.startTimeColumn and options.endTimeColumn.`,\n );\n }\n if (options.minimize !== undefined) {\n if (!optimize) {\n throw new TypeError(\n `${method} options.minimize is not supported because this method returns all routes.`,\n );\n }\n if (\n options.minimize !== \"steps\" &&\n options.minimize !== \"weight\" &&\n options.minimize !== \"elapsedTime\"\n ) {\n throw new TypeError(\n `${method} options.minimize must be \"steps\", \"weight\", or \"elapsedTime\".`,\n );\n }\n if (options.minimize === \"weight\" && options.weight === undefined) {\n throw new TypeError(`${method} options.minimize: \"weight\" requires options.weight.`);\n }\n if (options.minimize === \"elapsedTime\" && !elapsedTime) {\n throw new TypeError(\n `${method} options.minimize: \"elapsedTime\" requires options.elapsedTime: true.`,\n );\n }\n }\n if (optimize && elapsedTime && options.weight !== undefined && options.minimize === undefined) {\n throw new TypeError(\n `${method} when weight and elapsedTime are both enabled, specify options.minimize: \"steps\", \"weight\", or \"elapsedTime\".`,\n );\n }\n return {\n elapsedTime,\n minimize:\n options.minimize ??\n (options.weight !== undefined ? \"weight\" : elapsedTime ? \"elapsedTime\" : \"steps\"),\n };\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport buildGraphTemporalCostStateSql from \"../helpers/buildGraphTemporalCostStateSql.ts\";\nimport getGraphWeightColumn from \"../helpers/getGraphWeightColumn.ts\";\nimport prepareGraphMetricOptions, {\n type PreparedGraphMetricOptions,\n} from \"../helpers/prepareGraphMetricOptions.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTraversal, {\n type GraphDirection,\n validateGraphStarts,\n} from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\n\ntype DistancesOptions = GraphTemporalOptions & {\n direction?: GraphDirection;\n outputTable?: string | boolean;\n weight?: string;\n elapsedTime?: boolean;\n minimize?: \"steps\" | \"weight\" | \"elapsedTime\";\n};\n\nexport default function distances(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n startNodes: GraphId | GraphId[],\n options: DistancesOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"distances() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"distances() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"distances() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError('distances() options.direction must be \"outgoing\", \"incoming\", or \"both\".');\n }\n if (options.weight !== undefined && typeof options.weight !== \"string\") {\n throw new TypeError(\"distances() options.weight must be a string.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"distances() options.outputTable must be a string or boolean.\");\n }\n\n const metrics = prepareGraphMetricOptions(options, \"distances()\", true);\n const preparedStarts = prepareGraphStarts(startNodes, \"distances()\", \"startNodes\");\n const direction = options.direction ?? \"outgoing\";\n const temporalOptions = prepareGraphTemporalOptions(options, direction, \"distances()\");\n options = structuredClone(options);\n const parameters = {\n sourceColumn,\n targetColumn,\n startNodes: structuredClone(startNodes),\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"distances()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) => validateGraphTemporalEvents(input, temporalOptions, \"distances()\", parameters),\n values: (schema) => {\n const { temporal } = validateDistanceInputs(\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n options.weight,\n temporalOptions,\n );\n return temporal === undefined\n ? preparedStarts.values\n : [temporal.gapParameter, ...preparedStarts.values];\n },\n buildSelect: (input, schema) =>\n distancesSelect(\n input,\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n direction,\n options.weight,\n temporalOptions,\n metrics,\n ),\n outputSchema: (schema) => {\n const validated = validateDistanceInputs(\n schema,\n sourceColumn,\n targetColumn,\n preparedStarts,\n options.weight,\n temporalOptions,\n );\n return {\n start: validated.idType,\n node: validated.idType,\n steps: \"BIGINT\",\n ...(options.weight === undefined ? {} : { total: validated.distanceType }),\n ...(metrics.elapsedTime ? { elapsedTimeMs: \"DOUBLE\" } : {}),\n };\n },\n });\n}\n\nfunction validateDistanceInputs(\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n weight: string | undefined,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n) {\n const endpoints = validateGraphStarts(\n schema,\n source,\n target,\n starts,\n \"distances()\",\n \"startNodes\",\n );\n const distanceType =\n weight === undefined\n ? \"BIGINT\"\n : getGraphWeightColumn(schema, weight, \"distances()\").distanceType;\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"distances()\");\n return { idType: endpoints.idType, distanceType, temporal };\n}\n\nfunction distancesSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n starts: PreparedGraphStarts,\n direction: GraphDirection,\n weight: string | undefined,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n metrics: PreparedGraphMetricOptions,\n): string {\n const prepared = prepareGraphTraversal(\n input,\n schema,\n source,\n target,\n starts,\n \"distances()\",\n \"startNodes\",\n );\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, \"distances()\");\n const distanceType = weightColumn?.distanceType ?? \"BIGINT\";\n const edgeWeight =\n weightColumn === undefined\n ? `CAST(1 AS ${distanceType})`\n : `CAST(${quoteIdentifier(\"edges\")}.${quoteIdentifier(\n weightColumn.column,\n )} AS ${distanceType})`;\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"distances()\");\n if (weight !== undefined || metrics.elapsedTime) {\n return summaryDistancesSelect(\n prepared,\n direction,\n temporal,\n distanceType,\n edgeWeight,\n metrics,\n weight !== undefined,\n weightColumn?.type === \"FLOAT\" || weightColumn?.type === \"DOUBLE\",\n );\n }\n if (temporal !== undefined) {\n return temporalDistancesSelect(\n prepared,\n direction as Exclude<GraphDirection, \"both\">,\n temporal,\n distanceType,\n edgeWeight,\n \"steps\",\n false,\n );\n }\n const relations = prepared.relationNames([\n \"graph_start_values\",\n \"graph_starts\",\n \"graph_edges\",\n \"graph_distances\",\n ]);\n const startValuesRelation = relations.graph_start_values;\n const startsRelation = relations.graph_starts;\n const edgesRelation = relations.graph_edges;\n const distancesRelation = relations.graph_distances;\n const start = `${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"start\")}`;\n const startKey = `${quoteIdentifier(\"starts\")}.${quoteIdentifier(\"__key\")}`;\n const reachedStart = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"start\")}`;\n const reachedStartKey = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"__start_key\")}`;\n const reachedNodeKey = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"__node_key\")}`;\n const reachedDistance = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"distance\")}`;\n const edgeTo = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to\")}`;\n const edgeToKey = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__to_key\")}`;\n const edgeFromKey = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__from_key\")}`;\n const edgeCost = `${quoteIdentifier(\"edges\")}.${quoteIdentifier(\"__weight\")}`;\n const bestDistance = `${quoteIdentifier(\"best\")}.${quoteIdentifier(\"distance\")}`;\n const candidateDistance = `CAST(${reachedDistance} + ${edgeCost} AS ${distanceType})`;\n\n const candidateSteps = `${quoteIdentifier(\"reached\")}.${quoteIdentifier(\"steps\")} + 1`;\n const bestSteps = `${quoteIdentifier(\"best\")}.${quoteIdentifier(\"steps\")}`;\n const order = (distance: string, steps: string) =>\n metrics.minimize === \"steps\" ? `ROW(${steps}, ${distance})` : `ROW(${distance}, ${steps})`;\n const candidateOrder = order(candidateDistance, candidateSteps);\n const selectedDistance = `arg_min(${candidateDistance}, ${candidateOrder})`;\n const selectedSteps = `arg_min(${candidateSteps}, ${candidateOrder})`;\n\n return `WITH RECURSIVE ${startValuesRelation}(${quoteIdentifier(\"start\")}) AS (\n VALUES ${prepared.startValues}\n ), ${startsRelation} AS (\n SELECT ${quoteIdentifier(\"start\")},\n ${prepared.key(quoteIdentifier(\"start\"))} AS ${quoteIdentifier(\"__key\")}\n FROM ${startValuesRelation}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction, [`${edgeWeight} AS ${quoteIdentifier(\"__weight\")}`])}\n ), ${distancesRelation}(\n ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\"node\")},\n ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")},\n ${quoteIdentifier(\"distance\")}, ${quoteIdentifier(\"steps\")}\n ) USING KEY(\n ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\"__node_key\")}\n ) AS (\n SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},\n MIN(${edgeCost}) AS ${quoteIdentifier(\"distance\")}, CAST(1 AS BIGINT)\n FROM ${startsRelation} AS ${quoteIdentifier(\"starts\")}\n INNER JOIN ${edgesRelation} AS ${quoteIdentifier(\"edges\")}\n ON ${startKey} = ${edgeFromKey}\n GROUP BY ${start}, ${edgeTo}, ${startKey}, ${edgeToKey}\n UNION\n SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${selectedDistance} AS ${quoteIdentifier(\"distance\")},\n ${selectedSteps} AS ${quoteIdentifier(\"steps\")}\n FROM ${distancesRelation} AS ${quoteIdentifier(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${quoteIdentifier(\"edges\")}\n ON ${reachedNodeKey} = ${edgeFromKey}\n LEFT JOIN recurring.${distancesRelation} AS ${quoteIdentifier(\"best\")}\n ON ${reachedStartKey} = ${quoteIdentifier(\"best\")}.${quoteIdentifier(\"__start_key\")}\n AND ${edgeToKey} = ${quoteIdentifier(\"best\")}.${quoteIdentifier(\"__node_key\")}\n GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${bestDistance}, ${bestSteps}\n HAVING ${bestDistance} IS NULL OR\n ${order(selectedDistance, selectedSteps)} < ${order(bestDistance, bestSteps)}\n )\n SELECT ${quoteIdentifier(\"start\")}, ${quoteIdentifier(\"node\")},\n ${quoteIdentifier(\"steps\")}${\n weight === undefined\n ? \"\"\n : `, ${quoteIdentifier(\"distance\")} AS ${quoteIdentifier(\"total\")}`\n }\n FROM ${distancesRelation}\n ORDER BY ${quoteIdentifier(\"__start_key\")}, ${quoteIdentifier(\n metrics.minimize === \"steps\" ? \"steps\" : \"distance\",\n )}, ${quoteIdentifier(\"__node_key\")}`;\n}\n\nfunction temporalDistancesSelect(\n prepared: ReturnType<typeof prepareGraphTraversal>,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n distanceType: string,\n edgeWeight: string,\n minimize: \"steps\" | \"weight\",\n includeTotal: boolean,\n): string {\n const q = quoteIdentifier;\n const startsSelect = `SELECT ${q(\"start\")},\n ${prepared.key(q(\"start\"))} AS ${q(\"__key\")}\n FROM (VALUES ${prepared.startValues}) AS ${q(\"start_values\")}(${q(\"start\")})`;\n const costStates = buildGraphTemporalCostStateSql(\n prepared,\n startsSelect,\n direction,\n temporal,\n distanceType,\n edgeWeight,\n [],\n minimize,\n );\n const order =\n minimize === \"steps\" ? `${q(\"steps\")}, ${q(\"distance\")}` : `${q(\"distance\")}, ${q(\"steps\")}`;\n return `${costStates.withClause}\n SELECT ${q(\"start\")}, ${q(\"node\")}, ${q(\"steps\")}${\n includeTotal ? `, ${q(\"distance\")} AS ${q(\"total\")}` : \"\"\n }\n FROM ${costStates.costRelation}\n QUALIFY row_number() OVER (\n PARTITION BY ${q(\"__start_key\")}, ${q(\"__node_key\")}\n ORDER BY ${order}\n ) = 1\n ORDER BY ${q(\"__start_key\")}, ${q(\n minimize === \"steps\" ? \"steps\" : \"distance\",\n )}, ${q(\"__node_key\")}`;\n}\n\n// Distinct visited sets, metrics, and temporal boundaries are enough to extend\n// summaries. No edge IDs or full connection sequences are needed. Keeping the\n// visited set is necessary: equal summaries can have different legal extensions.\nfunction summaryDistancesSelect(\n prepared: ReturnType<typeof prepareGraphTraversal>,\n direction: GraphDirection,\n temporal: ReturnType<typeof prepareGraphTemporalSql> | undefined,\n distanceType: string,\n edgeWeight: string,\n metrics: PreparedGraphMetricOptions,\n includeTotal: boolean,\n floatingWeight: boolean,\n): string {\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_starts\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_summaries\",\n \"graph_metric_results\",\n \"graph_tied_summaries\",\n \"graph_best_metrics\",\n \"graph_metric_bounds\",\n ]);\n const starts = relations.graph_starts;\n const settings = relations.graph_temporal_settings;\n const events = relations.graph_event_rows;\n const edges = relations.graph_edges;\n const summaries = relations.graph_summaries;\n const results = relations.graph_metric_results;\n const tied = relations.graph_tied_summaries;\n const ref = (alias: string, column: string) => `${q(alias)}.${q(column)}`;\n const searchDirection = direction as Exclude<GraphDirection, \"both\">;\n const firstAnchor = temporal?.journeyAnchor(\"edges\", searchDirection);\n const sum = `CAST(${ref(\"reached\", \"distance\")} + ${ref(\n \"edges\",\n \"__weight\",\n )} AS ${distanceType})`;\n // Reported costs must not reject routes before the primary objective has\n // selected its results. NULL marks overflow and propagates through sums;\n // non-negative weights cannot bring an overflowing total back into range.\n const nextDistance = metrics.minimize === \"weight\" ? sum : `TRY(${sum})`;\n const temporalColumns =\n temporal === undefined ? \"\" : `, ${q(\"__event_start\")}, ${q(\"__event_end\")}`;\n const eventValues =\n temporal === undefined\n ? \"\"\n : `, ${ref(\"edges\", \"__event_start\")}, ${ref(\"edges\", \"__event_end\")}`;\n const metric =\n metrics.minimize === \"steps\"\n ? q(\"steps\")\n : metrics.minimize === \"weight\"\n ? q(\"distance\")\n : q(\"__elapsed\");\n // Use native time precision for selection. Collapse equal reported values\n // after conversion to milliseconds, since these are summary rows.\n const reportedElapsed = metrics.elapsedTime\n ? `, ${temporal!.elapsedMilliseconds(q(\"__elapsed\"))} AS ${q(\"elapsedTimeMs\")}`\n : \"\";\n const order =\n metrics.minimize === \"steps\"\n ? [\n q(\"steps\"),\n q(\"__node_key\"),\n ...(includeTotal ? [q(\"total\")] : []),\n ...(metrics.elapsedTime ? [q(\"elapsedTimeMs\")] : []),\n ]\n : metrics.minimize === \"weight\"\n ? [\n q(\"total\"),\n q(\"__node_key\"),\n q(\"steps\"),\n ...(metrics.elapsedTime ? [q(\"elapsedTimeMs\")] : []),\n ]\n : [q(\"elapsedTimeMs\"), q(\"__node_key\"), q(\"steps\"), ...(includeTotal ? [q(\"total\")] : [])];\n\n const bounds = summaryBoundsSql(\n relations.graph_best_metrics,\n relations.graph_metric_bounds,\n starts,\n edges,\n settings,\n temporal,\n searchDirection,\n metrics.minimize,\n distanceType,\n floatingWeight,\n );\n\n return `WITH RECURSIVE ${settings} AS (\n ${\n temporal === undefined\n ? `SELECT 0 AS ${q(\"__gap\")}`\n : `SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}`\n }\n ), ${events} AS MATERIALIZED (\n ${prepared.edges(direction, [\n `${edgeWeight} AS ${q(\"__weight\")}`,\n ...(temporal?.eventSelections(\"edges\") ?? []),\n ])}\n ), ${edges} AS MATERIALIZED (\n SELECT DISTINCT ${q(\"__from\")}, ${q(\"__to\")}, ${q(\"__from_key\")},\n ${q(\"__to_key\")}, ${q(\"__weight\")}${temporalColumns}\n FROM ${events} AS ${q(\"events\")}\n ${temporal === undefined ? \"\" : `WHERE ${temporal.eventValidity(\"events\")}`}\n ), ${starts} AS (\n SELECT ${q(\"start\")}, ${prepared.key(q(\"start\"))} AS ${q(\"__key\")}\n FROM (VALUES ${prepared.startValues}) AS ${q(\"start_values\")}(${q(\"start\")})\n ), ${bounds.ctes}, ${summaries}(\n ${q(\"start\")}, ${q(\"node\")}, ${q(\"__start_key\")}, ${q(\"__node_key\")},\n ${q(\"__visited\")}, ${q(\"steps\")}, ${q(\"distance\")}${temporalColumns}${\n metrics.elapsedTime ? `, ${q(\"__anchor\")}` : \"\"\n }\n ) AS (\n SELECT ${ref(\"starts\", \"start\")}, ${ref(\"edges\", \"__to\")},\n ${ref(\"starts\", \"__key\")}, ${ref(\"edges\", \"__to_key\")},\n list_sort(list_distinct([${ref(\"starts\", \"__key\")}, ${ref(\"edges\", \"__to_key\")}])),\n CAST(1 AS BIGINT), ${ref(\"edges\", \"__weight\")}${eventValues}${\n metrics.elapsedTime ? `, ${firstAnchor}` : \"\"\n }\n FROM ${starts} AS ${q(\"starts\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${ref(\"starts\", \"__key\")} = ${ref(\"edges\", \"__from_key\")}\n ${bounds.join(ref(\"starts\", \"__key\"))}\n WHERE ${bounds.test(\"CAST(1 AS BIGINT)\", ref(\"edges\", \"__weight\"), firstAnchor)}\n UNION\n SELECT ${ref(\"reached\", \"start\")}, ${ref(\"edges\", \"__to\")},\n ${ref(\"reached\", \"__start_key\")}, ${ref(\"edges\", \"__to_key\")},\n list_sort(list_distinct(list_append(${ref(\"reached\", \"__visited\")}, ${ref(\n \"edges\",\n \"__to_key\",\n )}))),\n ${ref(\"reached\", \"steps\")} + 1, ${nextDistance}${eventValues}${\n metrics.elapsedTime ? `, ${ref(\"reached\", \"__anchor\")}` : \"\"\n }\n FROM ${summaries} AS ${q(\"reached\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${ref(\"reached\", \"__node_key\")} = ${ref(\"edges\", \"__from_key\")}\n CROSS JOIN ${settings} AS ${q(\"settings\")}\n ${bounds.join(ref(\"reached\", \"__start_key\"))}\n WHERE ${bounds.test(\n `${ref(\"reached\", \"steps\")} + 1`,\n nextDistance,\n ref(\"reached\", \"__anchor\"),\n )}\n AND ${ref(\"reached\", \"__node_key\")} <> ${ref(\"reached\", \"__start_key\")}\n AND (NOT list_contains(${ref(\"reached\", \"__visited\")}, ${ref(\"edges\", \"__to_key\")})\n OR ${ref(\"edges\", \"__to_key\")} = ${ref(\"reached\", \"__start_key\")})\n ${\n temporal === undefined\n ? \"\"\n : `AND ${temporal.transition(\n \"reached\",\n \"edges\",\n searchDirection,\n ref(\"settings\", \"__gap\"),\n )}`\n }\n ), ${results} AS (\n SELECT *${\n metrics.elapsedTime\n ? `, ${temporal!.journeyElapsed(\n \"summaries\",\n ref(\"summaries\", \"__anchor\"),\n searchDirection,\n )} AS ${q(\"__elapsed\")}`\n : \"\"\n }\n FROM ${summaries} AS ${q(\"summaries\")}\n ), ${tied} AS MATERIALIZED (\n SELECT DISTINCT ${q(\"start\")}, ${q(\"node\")}, ${q(\"__start_key\")}, ${q(\"__node_key\")},\n ${q(\"steps\")}${includeTotal ? `, ${q(\"distance\")} AS ${q(\"total\")}` : \"\"}${reportedElapsed}\n FROM ${results}\n QUALIFY ${metric} = MIN(${metric}) OVER (\n PARTITION BY ${q(\"__start_key\")}, ${q(\"__node_key\")}\n )\n )\n SELECT ${q(\"start\")}, ${q(\"node\")}, ${q(\"steps\")}${\n includeTotal\n ? `, CASE WHEN ${q(\"total\")} IS NULL\n THEN error('distances() total exceeds the supported ${distanceType} range for an optimal route.')\n ELSE ${q(\"total\")} END AS ${q(\"total\")}`\n : \"\"\n }${metrics.elapsedTime ? `, ${q(\"elapsedTimeMs\")}` : \"\"}\n FROM ${tied}\n ORDER BY ${q(\"__start_key\")}, ${order.join(\", \")}`;\n}\n\n// Compute primary optima without enumerating visited sets. Exact additive\n// objectives have optimal prefixes (at the same event boundary in temporal\n// traversal). Floating addition can erase prefix differences, and elapsed\n// optima can depend on a later departure, so those use a per-start upper bound.\nfunction summaryBoundsSql(\n best: string,\n limits: string,\n starts: string,\n edges: string,\n settings: string,\n temporal: ReturnType<typeof prepareGraphTemporalSql> | undefined,\n direction: Exclude<GraphDirection, \"both\">,\n minimize: PreparedGraphMetricOptions[\"minimize\"],\n distanceType: string,\n floatingWeight: boolean,\n) {\n const q = quoteIdentifier;\n const ref = (alias: string, column: string) => `${q(alias)}.${q(column)}`;\n const elapsed = minimize === \"elapsedTime\";\n const globalBound = elapsed || (minimize === \"weight\" && floatingWeight);\n const boundaries = temporal === undefined ? [] : [\"__event_start\", \"__event_end\"];\n const keys = [\"__start_key\", \"__node_key\", ...boundaries, ...(elapsed ? [\"__anchor\"] : [])];\n const firstAnchor = elapsed ? temporal!.journeyAnchor(\"edges\", direction) : undefined;\n const firstKeys = [\n ref(\"starts\", \"__key\"),\n ref(\"edges\", \"__to_key\"),\n ...boundaries.map((key) => ref(\"edges\", key)),\n ...(elapsed ? [firstAnchor!] : []),\n ];\n const nextKeys = [\n ref(\"reached\", \"__start_key\"),\n ref(\"edges\", \"__to_key\"),\n ...boundaries.map((key) => ref(\"edges\", key)),\n ...(elapsed ? [ref(\"reached\", \"__anchor\")] : []),\n ];\n const firstMetric =\n minimize === \"steps\"\n ? \"CAST(1 AS BIGINT)\"\n : elapsed\n ? temporal!.journeyElapsed(\"edges\", firstAnchor!, direction)\n : ref(\"edges\", \"__weight\");\n const nextMetric =\n minimize === \"steps\"\n ? `${ref(\"reached\", \"__metric\")} + 1`\n : elapsed\n ? temporal!.journeyElapsed(\"edges\", ref(\"reached\", \"__anchor\"), direction)\n : `CAST(${ref(\"reached\", \"__metric\")} + ${ref(\"edges\", \"__weight\")} AS ${distanceType})`;\n const minimum = `MIN(${nextMetric})`;\n const bestMetric = ref(\"best\", \"__metric\");\n const ctes = `${best}(${keys.map(q).join(\", \")}, ${q(\"__metric\")})\n USING KEY(${keys.map(q).join(\", \")}) AS (\n SELECT ${firstKeys.join(\", \")}, MIN(${firstMetric})\n FROM ${starts} AS ${q(\"starts\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${ref(\"starts\", \"__key\")} = ${ref(\"edges\", \"__from_key\")}\n GROUP BY ${firstKeys.join(\", \")}\n UNION\n SELECT ${nextKeys.join(\", \")}, ${minimum}\n FROM ${best} AS ${q(\"reached\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${ref(\"reached\", \"__node_key\")} = ${ref(\"edges\", \"__from_key\")}\n CROSS JOIN ${settings} AS ${q(\"settings\")}\n LEFT JOIN recurring.${best} AS ${q(\"best\")}\n ON ${keys.map((key, i) => `${ref(\"best\", key)} = ${nextKeys[i]}`).join(\" AND \")}\n WHERE ${ref(\"reached\", \"__node_key\")} <> ${ref(\"reached\", \"__start_key\")}\n ${\n temporal === undefined\n ? \"\"\n : `AND ${temporal.transition(\"reached\", \"edges\", direction, ref(\"settings\", \"__gap\"))}`\n }\n GROUP BY ${nextKeys.join(\", \")}, ${bestMetric}\n HAVING ${bestMetric} IS NULL OR ${minimum} < ${bestMetric}\n )${\n globalBound\n ? `, ${limits} AS (\n SELECT ${q(\"__start_key\")}, MAX(${q(\"__minimum\")}) AS ${q(\"__metric\")}\n FROM (\n SELECT ${q(\"__start_key\")}, ${q(\"__node_key\")}, MIN(${q(\"__metric\")}) AS ${q(\"__minimum\")}\n FROM ${best}\n GROUP BY ${q(\"__start_key\")}, ${q(\"__node_key\")}\n ) AS ${q(\"minima\")}\n GROUP BY ${q(\"__start_key\")}\n )`\n : \"\"\n }`;\n return {\n ctes,\n join: (startKey: string) =>\n `INNER JOIN ${globalBound ? limits : best} AS ${q(\"bounds\")}\n ON ${ref(\"bounds\", \"__start_key\")} = ${startKey}\n ${\n globalBound\n ? \"\"\n : `AND ${ref(\"bounds\", \"__node_key\")} = ${ref(\"edges\", \"__to_key\")}\n ${boundaries.map((key) => `AND ${ref(\"bounds\", key)} = ${ref(\"edges\", key)}`).join(\" \")}`\n }`,\n test: (steps: string, distance: string, anchor: string | undefined) => {\n const metric =\n minimize === \"steps\"\n ? steps\n : elapsed\n ? temporal!.journeyElapsed(\"edges\", anchor!, direction)\n : distance;\n return `${metric} ${globalBound ? \"<=\" : \"=\"} ${ref(\"bounds\", \"__metric\")}`;\n },\n };\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport getGraphEndpointColumns from \"./getGraphEndpointColumns.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type GraphEdgeIdColumn = {\n column: string;\n family: \"string\" | \"numeric\";\n idType: string;\n};\n\n/** Resolves a route edge-ID column and its exact comparison type. */\nexport default function getGraphEdgeIdColumn(\n schema: TableSchema,\n requestedEdgeId: string,\n method: string,\n): GraphEdgeIdColumn {\n const folded = foldIdentifier(requestedEdgeId);\n const column = Object.keys(schema).find((name) => foldIdentifier(name) === folded);\n if (column === undefined) {\n throw new Error(\n `${method} the column ${quoteIdentifier(\n requestedEdgeId,\n )} does not exist. Check for typos, or load the data first.`,\n );\n }\n\n try {\n const resolved = getGraphEndpointColumns({ [column]: schema[column] }, column, column, method);\n return {\n column,\n family: resolved.family,\n idType: resolved.idType,\n };\n } catch (error) {\n if (error instanceof TypeError) {\n throw new TypeError(\n `${method} requires string or whole-number edge IDs, but column ${quoteIdentifier(\n column,\n )} has type ${schema[column]}.`,\n );\n }\n throw error;\n }\n}\n","import foldIdentifier from \"./foldIdentifier.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nconst resultColumns = [\"pathId\", \"step\", \"weight\", \"total\"] as const;\n\n/** Validates that route result columns do not replace original input columns. */\nexport default function validateGraphRouteResultSchema(\n schema: TableSchema,\n method: string,\n additionalResultColumns: readonly string[] = [],\n includeTotal = true,\n): void {\n for (const resultColumn of [...resultColumns, ...additionalResultColumns]) {\n if (resultColumn === \"total\" && !includeTotal) continue;\n const folded = foldIdentifier(resultColumn);\n const inputColumn = Object.keys(schema).find((column) => foldIdentifier(column) === folded);\n if (inputColumn !== undefined) {\n throw new Error(\n `${method} cannot add ${quoteIdentifier(\n resultColumn,\n )} because input column ${quoteIdentifier(\n inputColumn,\n )} conflicts with that result column. Rename ${quoteIdentifier(\n inputColumn,\n )} with renameColumns() before calculating the graph.`,\n );\n }\n }\n}\n","import getGraphEdgeIdColumn from \"./getGraphEdgeIdColumn.ts\";\nimport getGraphWeightColumn from \"./getGraphWeightColumn.ts\";\nimport type { TableSchema } from \"./pendingOps.ts\";\nimport validateGraphRouteResultSchema from \"./validateGraphRouteResultSchema.ts\";\nimport prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"./prepareGraphStarts.ts\";\nimport prepareGraphTraversal, { validateGraphStarts } from \"./prepareGraphTraversal.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport type PreparedGraphRouteEndpoints = {\n end: PreparedGraphStarts;\n start: PreparedGraphStarts;\n values: PreparedGraphStarts;\n};\n\n/** Prepares and validates the two scalar endpoints shared by route methods. */\nexport function prepareGraphRouteEndpoints(\n start: GraphId,\n end: GraphId,\n method: string,\n): PreparedGraphRouteEndpoints {\n if (Array.isArray(start)) {\n throw new TypeError(`${method} start must be one node ID.`);\n }\n if (Array.isArray(end)) {\n throw new TypeError(`${method} end must be one node ID.`);\n }\n const preparedStart = prepareGraphStarts(start, method);\n const preparedEnd = prepareGraphStarts(end, method);\n if (preparedStart.family !== preparedEnd.family) {\n throw new TypeError(`${method} start and end must both be string IDs or both be numeric IDs.`);\n }\n if (preparedStart.values[0] === preparedEnd.values[0]) {\n throw new TypeError(\n `${method} start and end must be different. Use distances() to measure return routes or findCycles() to find loops.`,\n );\n }\n return {\n start: preparedStart,\n end: preparedEnd,\n values: {\n family: preparedStart.family,\n numericValues: [...preparedStart.numericValues, ...preparedEnd.numericValues],\n values: [preparedStart.values[0], preparedEnd.values[0]],\n },\n };\n}\n\n/** Validates the columns shared by edge-route methods from queued schema data. */\nexport function validateGraphRouteInputs(\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n endpoints: PreparedGraphRouteEndpoints,\n weight: string | undefined,\n method: string,\n includeTotal = true,\n) {\n const nodes = validateGraphStarts(schema, source, target, endpoints.values, method);\n const edges = getGraphEdgeIdColumn(schema, edgeId, method);\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, method);\n validateGraphRouteResultSchema(schema, method, [], includeTotal);\n return {\n distanceType: weightColumn?.distanceType ?? \"BIGINT\",\n edgeIdType: edges.idType,\n nodeIdType: nodes.idType,\n };\n}\n\n/** Prepares the typed SQL expressions shared by edge-route enumeration. */\nexport function prepareGraphRouteSql(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n endpoints: PreparedGraphRouteEndpoints,\n weight: string | undefined,\n method: string,\n includeTotal = true,\n) {\n validateGraphRouteResultSchema(schema, method, [], includeTotal);\n const traversal = prepareGraphTraversal(input, schema, source, target, endpoints.values, method);\n const edgeIdColumn = getGraphEdgeIdColumn(schema, edgeId, method);\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, method);\n const distanceType = weightColumn?.distanceType ?? \"BIGINT\";\n const q = quoteIdentifier;\n const edgeIdReference = `${q(\"edges\")}.${q(edgeIdColumn.column)}`;\n const typedEdgeId = `CAST(${edgeIdReference} AS ${edgeIdColumn.idType})`;\n const edgeKey = edgeIdColumn.family === \"string\" ? `ENCODE(${typedEdgeId})` : typedEdgeId;\n const edgeWeight =\n weightColumn === undefined\n ? `CAST(1 AS ${distanceType})`\n : `CAST(${q(\"edges\")}.${q(weightColumn.column)} AS ${distanceType})`;\n const keyType = edgeIdColumn.family === \"string\" ? \"BLOB\" : edgeIdColumn.idType;\n const stepType = `STRUCT(${q(\"edgeId\")} ${edgeIdColumn.idType}, ${q(\n \"source\",\n )} ${traversal.endpoints.idType}, ${q(\n \"target\",\n )} ${traversal.endpoints.idType}, ${q(\"weight\")} ${distanceType}, ${q(\n \"distance\",\n )} ${distanceType})`;\n\n return {\n distanceType,\n edgeIdColumn,\n edgeKey,\n edgeWeight,\n endpointValue: `TRY_CAST(? AS ${traversal.endpoints.idType})`,\n keyType,\n stepType,\n input,\n schema,\n traversal,\n typedEdgeId,\n weightType: weightColumn?.type,\n };\n}\n","import type { TableSchema } from \"./pendingOps.ts\";\nimport validateGraphRouteResultSchema from \"./validateGraphRouteResultSchema.ts\";\n\n/** Derives the route result schema while preserving input columns and types. */\nexport default function graphRouteResultSchema(\n schema: TableSchema,\n distanceType: string,\n method: string,\n elapsedTime = false,\n includeTotal = true,\n): TableSchema {\n validateGraphRouteResultSchema(\n schema,\n method,\n elapsedTime ? [\"elapsedTimeMs\"] : [],\n includeTotal,\n );\n return {\n pathId: \"BIGINT\",\n step: \"BIGINT\",\n weight: distanceType,\n ...(includeTotal ? { total: distanceType } : {}),\n ...(elapsedTime ? { elapsedTimeMs: \"DOUBLE\" } : {}),\n ...schema,\n };\n}\n","import type { GraphEdgeIdColumn } from \"./getGraphEdgeIdColumn.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/** Joins ranked route steps to their original input rows for final output. */\nexport default function graphRouteResultSelect(\n rankedRelation: string,\n input: string,\n edgeIdColumn: GraphEdgeIdColumn,\n includeStart = false,\n elapsedTime = false,\n includeTotal = true,\n): string {\n const q = quoteIdentifier;\n const routeStep = `${q(\"unnested\")}.${q(\"route_step\")}`;\n const originalEdgeId = `${q(\"original\")}.${q(edgeIdColumn.column)}`;\n const edgeMatch =\n edgeIdColumn.family === \"string\"\n ? `ENCODE(CAST(${originalEdgeId} AS VARCHAR)) =\n ENCODE(${routeStep}.${q(\"edgeId\")})`\n : `CAST(${originalEdgeId} AS ${edgeIdColumn.idType}) =\n ${routeStep}.${q(\"edgeId\")}`;\n return `SELECT ${\n includeStart ? `${q(\"ranked\")}.${q(\"start\")},\\n ` : \"\"\n }${q(\"ranked\")}.${q(\"pathId\")},\n CAST(${q(\"unnested\")}.${q(\"step\")} AS BIGINT) AS ${q(\"step\")},\n ${routeStep}.${q(\"weight\")} AS ${q(\"weight\")},\n ${includeTotal ? `${routeStep}.${q(\"distance\")} AS ${q(\"total\")},` : \"\"}\n ${elapsedTime ? `${routeStep}.${q(\"elapsedTimeMs\")} AS ${q(\"elapsedTimeMs\")},` : \"\"}\n ${q(\"original\")}.*\n FROM ${rankedRelation} AS ${q(\"ranked\")},\n UNNEST(${q(\"ranked\")}.${q(\"steps\")}) WITH ORDINALITY AS ${q(\n \"unnested\",\n )}(${q(\"route_step\")}, ${q(\"step\")})\n INNER JOIN ${input} AS ${q(\"original\")}\n ON ${edgeMatch}\n ORDER BY ${includeStart ? `${q(\"ranked\")}.${q(\"__start_key\")}, ` : \"\"}${q(\n \"ranked\",\n )}.${q(\"pathId\")}, ${q(\"unnested\")}.${q(\"step\")}`;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport buildGraphTemporalCostStateSql from \"../helpers/buildGraphTemporalCostStateSql.ts\";\nimport prepareGraphMetricOptions, {\n type PreparedGraphMetricOptions,\n} from \"../helpers/prepareGraphMetricOptions.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport type { GraphId } from \"../helpers/prepareGraphStarts.ts\";\nimport {\n type PreparedGraphRouteEndpoints,\n prepareGraphRouteEndpoints,\n prepareGraphRouteSql,\n validateGraphRouteInputs,\n} from \"../helpers/prepareGraphRouteSql.ts\";\nimport graphRouteResultSchema from \"../helpers/graphRouteResultSchema.ts\";\nimport graphRouteResultSelect from \"../helpers/graphRouteResultSelect.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport type { GraphDirection } from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\n\ntype ShortestPathOptions = GraphTemporalOptions & {\n direction?: GraphDirection;\n outputTable?: string | boolean;\n weight?: string;\n elapsedTime?: boolean;\n minimize?: \"steps\" | \"weight\" | \"elapsedTime\";\n};\n\nexport default function shortestPath(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n start: GraphId,\n end: GraphId,\n options: ShortestPathOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"shortestPath() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"shortestPath() targetColumn must be a string.\");\n }\n if (typeof edgeId !== \"string\") {\n throw new TypeError(\"shortestPath() edgeId must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"shortestPath() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError(\n 'shortestPath() options.direction must be \"outgoing\", \"incoming\", or \"both\".',\n );\n }\n if (options.weight !== undefined && typeof options.weight !== \"string\") {\n throw new TypeError(\"shortestPath() options.weight must be a string.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"shortestPath() options.outputTable must be a string or boolean.\");\n }\n\n const metrics = prepareGraphMetricOptions(options, \"shortestPath()\", true);\n const endpoints = prepareGraphRouteEndpoints(start, end, \"shortestPath()\");\n const direction = options.direction ?? \"outgoing\";\n const temporalOptions = prepareGraphTemporalOptions(options, direction, \"shortestPath()\");\n options = structuredClone(options);\n const parameters = {\n sourceColumn,\n targetColumn,\n edgeId,\n start,\n end,\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"shortestPath()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) =>\n validateGraphTemporalEvents(input, temporalOptions, \"shortestPath()\", parameters),\n values: (schema) => {\n validateGraphRouteInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n options.weight,\n \"shortestPath()\",\n options.weight !== undefined,\n );\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"shortestPath()\");\n return temporal === undefined\n ? endpoints.values.values\n : [temporal.gapParameter, ...endpoints.values.values];\n },\n buildSelect: (input, schema) =>\n shortestPathSelect(\n input,\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n direction,\n options.weight,\n temporalOptions,\n metrics,\n ),\n outputSchema: (schema) => {\n const validated = validateGraphRouteInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n options.weight,\n \"shortestPath()\",\n options.weight !== undefined,\n );\n if (temporalOptions !== undefined) {\n prepareGraphTemporalSql(schema, temporalOptions, \"shortestPath()\");\n }\n return graphRouteResultSchema(\n schema,\n validated.distanceType,\n \"shortestPath()\",\n metrics.elapsedTime,\n options.weight !== undefined,\n );\n },\n });\n}\n\nfunction shortestPathSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n routeEndpoints: PreparedGraphRouteEndpoints,\n direction: GraphDirection,\n weight: string | undefined,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n metrics: PreparedGraphMetricOptions,\n): string {\n const route = prepareGraphRouteSql(\n input,\n schema,\n source,\n target,\n edgeId,\n routeEndpoints,\n weight,\n \"shortestPath()\",\n weight !== undefined,\n );\n const prepared = route.traversal;\n if (temporalOptions !== undefined) {\n const temporal = prepareGraphTemporalSql(schema, temporalOptions, \"shortestPath()\");\n return temporalShortestPathSelect(\n route,\n direction as Exclude<GraphDirection, \"both\">,\n temporal,\n metrics,\n weight !== undefined,\n );\n }\n const distanceType = route.distanceType;\n // Exact shortest routes have optimal prefixes. Floating addition can erase\n // a prefix-cost difference later, so retain all simple prefixes up to the\n // best complete cost before selecting the full-route ties.\n const floating =\n metrics.minimize === \"weight\" &&\n (route.weightType === \"FLOAT\" || route.weightType === \"DOUBLE\");\n const metricType = metrics.minimize === \"steps\" ? \"BIGINT\" : distanceType;\n\n const relations = prepared.relationNames([\n \"graph_route_endpoints\",\n \"graph_edges\",\n \"graph_nodes\",\n \"graph_to_end\",\n \"graph_distances\",\n \"graph_best_total\",\n \"graph_routes\",\n \"graph_shortest_routes\",\n \"graph_ranked_routes\",\n ]);\n const endpointRelation = relations.graph_route_endpoints;\n const edgesRelation = relations.graph_edges;\n const nodesRelation = relations.graph_nodes;\n const toEndRelation = relations.graph_to_end;\n const distancesRelation = relations.graph_distances;\n const bestTotalRelation = relations.graph_best_total;\n const routesRelation = relations.graph_routes;\n const shortestRelation = relations.graph_shortest_routes;\n const rankedRelation = relations.graph_ranked_routes;\n\n const q = quoteIdentifier;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const edgeMetric = metrics.minimize === \"steps\" ? \"CAST(1 AS BIGINT)\" : edgeCost;\n const routeDistance = `${q(\"routes\")}.${q(\"distance\")}`;\n const candidateDistance = `CAST(${routeDistance} + ${edgeCost} AS ${distanceType})`;\n const routeMetric =\n metrics.minimize === \"steps\" ? `len(${q(\"routes\")}.${q(\"steps\")})` : routeDistance;\n const candidateMetric = metrics.minimize === \"steps\" ? `${routeMetric} + 1` : candidateDistance;\n return `WITH RECURSIVE ${endpointRelation}(\n ${q(\"start\")}, ${q(\"end\")}, ${q(\"__start_key\")}, ${q(\"__end_key\")}\n ) AS (\n SELECT ${q(\"start\")}, ${q(\"end\")},\n ${prepared.key(q(\"start\"))}, ${prepared.key(q(\"end\"))}\n FROM (SELECT ${route.endpointValue} AS ${q(\"start\")},\n ${route.endpointValue} AS ${q(\"end\")}) AS ${q(\"values\")}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction, [\n `${route.typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${route.edgeKey} AS ${q(\"__edge_key\")}`,\n `${route.edgeWeight} AS ${q(\"__weight\")}`,\n ])}\n ), ${nodesRelation} AS (\n SELECT ${q(\"__from_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n UNION\n SELECT ${q(\"__to_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n ), ${toEndRelation}(${q(\"__key\")}) AS (\n SELECT ${q(\"__end_key\")}\n FROM ${endpointRelation}\n INNER JOIN ${nodesRelation}\n ON ${q(\"__end_key\")} = ${q(\"__key\")}\n UNION\n SELECT ${edgeFromKey}\n FROM ${toEndRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__key\")} = ${edgeToKey}\n ), ${distancesRelation}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"distance\")}\n ) USING KEY(${q(\"__node_key\")}) AS (\n SELECT ${q(\"start\")}, ${q(\"__start_key\")},\n CAST(0 AS ${metricType})\n FROM ${endpointRelation}\n INNER JOIN ${toEndRelation}\n ON ${q(\"__start_key\")} = ${q(\"__key\")}\n UNION\n SELECT ${edgeTo}, ${edgeToKey},\n MIN(CAST(${q(\"reached\")}.${q(\"distance\")} + ${edgeMetric} AS ${metricType}))\n FROM ${distancesRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__node_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n LEFT JOIN recurring.${distancesRelation} AS ${q(\"best\")}\n ON ${edgeToKey} = ${q(\"best\")}.${q(\"__node_key\")}\n GROUP BY ${edgeTo}, ${edgeToKey}, ${q(\"best\")}.${q(\"distance\")}\n HAVING ${q(\"best\")}.${q(\"distance\")} IS NULL\n OR MIN(CAST(${q(\"reached\")}.${q(\n \"distance\",\n )} + ${edgeMetric} AS ${metricType})) < ${q(\"best\")}.${q(\"distance\")}\n ), ${bestTotalRelation} AS (\n SELECT ${q(\"distances\")}.${q(\"distance\")}\n FROM ${distancesRelation} AS ${q(\"distances\")}\n INNER JOIN ${endpointRelation}\n ON ${q(\"distances\")}.${q(\"__node_key\")} = ${q(\"__end_key\")}\n ), ${routesRelation}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"__visited\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}, ${q(\"distance\")}\n ) AS (\n SELECT ${q(\"start\")}, ${q(\"__start_key\")},\n [${q(\"__start_key\")}], CAST([] AS ${route.keyType}[]),\n CAST([] AS ${route.stepType}[]), CAST(0 AS ${distanceType})\n FROM ${endpointRelation}\n INNER JOIN ${bestTotalRelation} ON TRUE\n UNION ALL\n SELECT ${edgeTo}, ${edgeToKey},\n list_append(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"routes\")}.${q(\"__edge_keys\")}, ${q(\"edges\")}.${q(\"__edge_key\")}),\n list_append(${q(\"routes\")}.${q(\"steps\")}, struct_pack(\n ${q(\"edgeId\")} := ${q(\"edges\")}.${q(\"__edge_id\")},\n ${q(\"source\")} := ${q(\"edges\")}.${q(\"__from\")},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${candidateDistance}\n )), ${candidateDistance}\n FROM ${routesRelation} AS ${q(\"routes\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"routes\")}.${q(\"__node_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n INNER JOIN ${bestTotalRelation} AS ${q(\"best_total\")}\n ON TRUE\n ${\n floating\n ? \"\"\n : `INNER JOIN ${distancesRelation} AS ${q(\"best_prefix\")}\n ON ${edgeToKey} = ${q(\"best_prefix\")}.${q(\"__node_key\")}`\n }\n CROSS JOIN ${endpointRelation}\n WHERE ${q(\"routes\")}.${q(\"__node_key\")} <> ${q(\"__end_key\")}\n AND NOT list_contains(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey})\n AND ${\n floating\n ? `${candidateMetric} <= ${q(\"best_total\")}.${q(\"distance\")}`\n : `${candidateMetric} = ${q(\"best_prefix\")}.${q(\"distance\")}`\n }\n ), ${shortestRelation} AS (\n SELECT ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${routesRelation} AS ${q(\"routes\")}\n CROSS JOIN ${endpointRelation}\n CROSS JOIN ${bestTotalRelation} AS ${q(\"best_total\")}\n WHERE ${q(\"__node_key\")} = ${q(\"__end_key\")}\n AND ${routeMetric} = ${q(\"best_total\")}.${q(\"distance\")}\n ), ${rankedRelation} AS (\n SELECT CAST(row_number() OVER (ORDER BY ${q(\"__edge_keys\")}) - 1 AS BIGINT) AS ${q(\"pathId\")},\n ${q(\"steps\")}\n FROM ${shortestRelation}\n )\n ${graphRouteResultSelect(\n rankedRelation,\n route.input,\n route.edgeIdColumn,\n false,\n false,\n weight !== undefined,\n )}`;\n}\n\nfunction temporalShortestPathSelect(\n route: ReturnType<typeof prepareGraphRouteSql>,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n metrics: PreparedGraphMetricOptions,\n includeTotal: boolean,\n): string {\n const prepared = route.traversal;\n const q = quoteIdentifier;\n const startsSelect = `SELECT ${q(\"start\")},\n ${prepared.key(q(\"start\"))} AS ${q(\"__key\")}\n FROM (SELECT ${route.endpointValue} AS ${q(\"start\")}) AS ${q(\"values\")}`;\n // Non-negative weights and no maximum gap let cycles be removed from walks.\n // Their optimum bounds simple routes; retain separate histories for all ties.\n const costs =\n metrics.minimize === \"elapsedTime\"\n ? buildElapsedShortestPathCostSql(route, startsSelect, direction, temporal)\n : buildGraphTemporalCostStateSql(\n prepared,\n startsSelect,\n direction,\n temporal,\n route.distanceType,\n route.edgeWeight,\n [`${route.typedEdgeId} AS ${q(\"__edge_id\")}`, `${route.edgeKey} AS ${q(\"__edge_key\")}`],\n metrics.minimize === \"steps\" ? \"steps\" : \"weight\",\n );\n const relations = prepared.relationNames([\n \"graph_route_endpoints\",\n \"graph_nodes\",\n \"graph_to_end\",\n \"graph_best_total\",\n \"graph_routes\",\n \"graph_shortest_routes\",\n \"graph_ranked_routes\",\n ]);\n const endpointRelation = relations.graph_route_endpoints;\n const nodesRelation = relations.graph_nodes;\n const toEndRelation = relations.graph_to_end;\n const bestTotalRelation = relations.graph_best_total;\n const routesRelation = relations.graph_routes;\n const shortestRelation = relations.graph_shortest_routes;\n const rankedRelation = relations.graph_ranked_routes;\n const edgesRelation = costs.edgesRelation;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const edgeKey = `${q(\"edges\")}.${q(\"__edge_key\")}`;\n const routeDistance = `${q(\"routes\")}.${q(\"distance\")}`;\n const candidateDistance = `CAST(${routeDistance} + ${edgeCost} AS ${route.distanceType})`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const firstAnchor = temporal.journeyAnchor(\"edges\", direction);\n const routeAnchor = `${q(\"routes\")}.${q(\"__journey_anchor\")}`;\n const firstElapsed = temporal.journeyElapsed(\"edges\", firstAnchor, direction);\n const candidateElapsed = temporal.journeyElapsed(\"edges\", routeAnchor, direction);\n const firstMetric =\n metrics.minimize === \"steps\"\n ? \"1\"\n : metrics.minimize === \"elapsedTime\"\n ? firstElapsed\n : edgeCost;\n const routeMetric =\n metrics.minimize === \"steps\"\n ? `len(${q(\"routes\")}.${q(\"steps\")})`\n : metrics.minimize === \"elapsedTime\"\n ? `${q(\"routes\")}.${q(\"__elapsed\")}`\n : routeDistance;\n const candidateMetric =\n metrics.minimize === \"steps\"\n ? `${routeMetric} + 1`\n : metrics.minimize === \"elapsedTime\"\n ? candidateElapsed\n : candidateDistance;\n const step = (distance: string, elapsed: string) =>\n `struct_pack(\n ${q(\"edgeId\")} := ${q(\"edges\")}.${q(\"__edge_id\")},\n ${q(\"source\")} := ${q(\"edges\")}.${q(\"__from\")},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${distance}${\n metrics.elapsedTime\n ? `, ${q(\"elapsedTimeMs\")} := ${temporal.elapsedMilliseconds(elapsed)}`\n : \"\"\n }\n )`;\n\n return `${costs.withClause}, ${endpointRelation}(\n ${q(\"start\")}, ${q(\"end\")}, ${q(\"__start_key\")}, ${q(\"__end_key\")}\n ) AS (\n SELECT ${q(\"starts\")}.${q(\"start\")}, ${q(\"values\")}.${q(\"end\")},\n ${q(\"starts\")}.${q(\"__key\")},\n ${prepared.key(`${q(\"values\")}.${q(\"end\")}`)}\n FROM ${costs.startsRelation} AS ${q(\"starts\")}\n CROSS JOIN (SELECT ${route.endpointValue} AS ${q(\"end\")}) AS ${q(\"values\")}\n ), ${nodesRelation} AS (\n SELECT ${q(\"__from_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n UNION\n SELECT ${q(\"__to_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n ), ${toEndRelation}(${q(\"__key\")}) AS (\n SELECT ${q(\"__end_key\")}\n FROM ${endpointRelation}\n INNER JOIN ${nodesRelation}\n ON ${q(\"__end_key\")} = ${q(\"__key\")}\n UNION\n SELECT ${edgeFromKey}\n FROM ${toEndRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__key\")} = ${edgeToKey}\n ), ${bestTotalRelation} AS (\n SELECT MIN(${q(\"costs\")}.${q(\n metrics.minimize === \"steps\" ? \"steps\" : \"distance\",\n )}) AS ${q(\"distance\")}\n FROM ${costs.costRelation} AS ${q(\"costs\")}\n INNER JOIN ${endpointRelation}\n ON ${q(\"costs\")}.${q(\"__node_key\")} = ${q(\"__end_key\")}\n ), ${routesRelation}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"__visited\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}, ${q(\"distance\")},\n ${q(\"__event_id\")}, ${q(\"__event_start\")}, ${q(\"__event_end\")}${\n metrics.elapsedTime ? `, ${q(\"__journey_anchor\")}, ${q(\"__elapsed\")}` : \"\"\n }\n ) AS (\n SELECT ${edgeTo}, ${edgeToKey},\n [${q(\"__start_key\")}, ${edgeToKey}], [${edgeKey}],\n [${step(edgeCost, firstElapsed)}], ${edgeCost},\n ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${\n metrics.elapsedTime ? `, ${firstAnchor}, ${firstElapsed}` : \"\"\n }\n FROM ${endpointRelation}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"__start_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n INNER JOIN ${bestTotalRelation} AS ${q(\"best_total\")}\n ON ${firstMetric} <= ${q(\"best_total\")}.${q(\"distance\")}\n WHERE ${q(\"__start_key\")} <> ${edgeToKey}\n UNION ALL\n SELECT ${edgeTo}, ${edgeToKey},\n list_append(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"routes\")}.${q(\"__edge_keys\")}, ${edgeKey}),\n list_append(${q(\"routes\")}.${q(\"steps\")}, ${step(candidateDistance, candidateElapsed)}),\n ${candidateDistance}, ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${\n metrics.elapsedTime ? `, ${routeAnchor}, ${candidateElapsed}` : \"\"\n }\n FROM ${routesRelation} AS ${q(\"routes\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"routes\")}.${q(\"__node_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n INNER JOIN ${bestTotalRelation} AS ${q(\"best_total\")}\n ON ${candidateMetric} <= ${q(\"best_total\")}.${q(\"distance\")}\n CROSS JOIN ${endpointRelation}\n CROSS JOIN ${costs.settingsRelation} AS ${q(\"settings\")}\n WHERE ${q(\"routes\")}.${q(\"__node_key\")} <> ${q(\"__end_key\")}\n AND NOT list_contains(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey})\n AND ${temporal.transition(\"routes\", \"edges\", direction, gap)}\n ), ${shortestRelation} AS (\n SELECT ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${routesRelation} AS ${q(\"routes\")}\n CROSS JOIN ${endpointRelation}\n CROSS JOIN ${bestTotalRelation} AS ${q(\"best_total\")}\n WHERE ${q(\"__node_key\")} = ${q(\"__end_key\")}\n AND ${routeMetric} = ${q(\"best_total\")}.${q(\"distance\")}\n ), ${rankedRelation} AS (\n SELECT CAST(row_number() OVER (ORDER BY ${q(\"__edge_keys\")}) - 1 AS BIGINT)\n AS ${q(\"pathId\")}, ${q(\"steps\")}\n FROM ${shortestRelation}\n )\n ${graphRouteResultSelect(\n rankedRelation,\n route.input,\n route.edgeIdColumn,\n false,\n metrics.elapsedTime,\n includeTotal,\n )}`;\n}\n\n// At the same physical event a later departure (or earlier incoming arrival)\n// dominates every future elapsed duration. Keyed improvements find the optimum\n// without enumerating route histories; reconstruction still retains all ties.\nfunction buildElapsedShortestPathCostSql(\n route: ReturnType<typeof prepareGraphRouteSql>,\n startsSelect: string,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n): ReturnType<typeof buildGraphTemporalCostStateSql> {\n const prepared = route.traversal;\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_starts\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_cost_states\",\n ]);\n const startsRelation = relations.graph_starts;\n const settingsRelation = relations.graph_temporal_settings;\n const eventRowsRelation = relations.graph_event_rows;\n const edgesRelation = relations.graph_edges;\n const costRelation = relations.graph_cost_states;\n const start = `${q(\"starts\")}.${q(\"start\")}`;\n const startKey = `${q(\"starts\")}.${q(\"__key\")}`;\n const reachedStart = `${q(\"reached\")}.${q(\"start\")}`;\n const reachedStartKey = `${q(\"reached\")}.${q(\"__start_key\")}`;\n const reachedNodeKey = `${q(\"reached\")}.${q(\"__node_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const eventId = `${q(\"edges\")}.${q(\"__event_id\")}`;\n const eventStart = `${q(\"edges\")}.${q(\"__event_start\")}`;\n const eventEnd = `${q(\"edges\")}.${q(\"__event_end\")}`;\n const bestDistance = `${q(\"best\")}.${q(\"distance\")}`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const firstAnchor = temporal.journeyAnchor(\"edges\", direction);\n const reachedAnchor = `${q(\"reached\")}.${q(\"__journey_anchor\")}`;\n const firstElapsed = temporal.journeyElapsed(\"edges\", firstAnchor, direction);\n const candidateDistance = temporal.journeyElapsed(\"edges\", reachedAnchor, direction);\n const bestAnchor = `${direction === \"outgoing\" ? \"MAX\" : \"MIN\"}(${reachedAnchor})`;\n\n return {\n costRelation,\n edgesRelation,\n settingsRelation,\n startsRelation,\n withClause: `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (\n SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}\n ), ${eventRowsRelation} AS MATERIALIZED (\n ${prepared.edges(direction, [\n `${route.edgeWeight} AS ${q(\"__weight\")}`,\n `${route.typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${route.edgeKey} AS ${q(\"__edge_key\")}`,\n ...temporal.eventSelections(\"edges\"),\n ])}\n ), ${edgesRelation} AS MATERIALIZED (\n SELECT *\n FROM ${eventRowsRelation} AS ${q(\"events\")}\n WHERE ${temporal.eventValidity(\"events\")}\n ), ${startsRelation} AS MATERIALIZED (\n ${startsSelect}\n ), ${costRelation}(\n ${q(\"start\")}, ${q(\"node\")},\n ${q(\"__start_key\")}, ${q(\"__node_key\")},\n ${q(\"__event_id\")}, ${q(\"__event_start\")}, ${q(\"__event_end\")},\n ${q(\"distance\")}, ${q(\"__journey_anchor\")}\n ) USING KEY(${q(\"__start_key\")}, ${q(\"__event_id\")}) AS (\n SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}, ${firstElapsed}, ${firstAnchor}\n FROM ${startsRelation} AS ${q(\"starts\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${startKey} = ${edgeFromKey}\n UNION\n SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd},\n MIN(${candidateDistance}) AS ${q(\"distance\")}, ${bestAnchor}\n FROM ${costRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${reachedNodeKey} = ${edgeFromKey}\n CROSS JOIN ${settingsRelation} AS ${q(\"settings\")}\n LEFT JOIN recurring.${costRelation} AS ${q(\"best\")}\n ON ${reachedStartKey} = ${q(\"best\")}.${q(\"__start_key\")}\n AND ${eventId} = ${q(\"best\")}.${q(\"__event_id\")}\n WHERE ${temporal.transition(\"reached\", \"edges\", direction, gap)}\n GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},\n ${eventId}, ${eventStart}, ${eventEnd}, ${bestDistance}\n HAVING ${bestDistance} IS NULL OR\n MIN(${candidateDistance}) < ${bestDistance}\n )`,\n };\n}\n","import prepareGraphMetricOptions from \"../helpers/prepareGraphMetricOptions.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport {\n type PreparedGraphRouteEndpoints,\n prepareGraphRouteEndpoints,\n prepareGraphRouteSql,\n validateGraphRouteInputs,\n} from \"../helpers/prepareGraphRouteSql.ts\";\nimport graphRouteResultSchema from \"../helpers/graphRouteResultSchema.ts\";\nimport graphRouteResultSelect from \"../helpers/graphRouteResultSelect.ts\";\nimport type { GraphId } from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport type { GraphDirection } from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\n\ntype PathsOptions = GraphTemporalOptions & {\n elapsedTime?: boolean;\n direction?: GraphDirection;\n outputTable?: string | boolean;\n weight?: string;\n};\n\nexport default function paths(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n start: GraphId,\n end: GraphId,\n options: PathsOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"paths() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"paths() targetColumn must be a string.\");\n }\n if (typeof edgeId !== \"string\") {\n throw new TypeError(\"paths() edgeId must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"paths() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError('paths() options.direction must be \"outgoing\", \"incoming\", or \"both\".');\n }\n if (options.weight !== undefined && typeof options.weight !== \"string\") {\n throw new TypeError(\"paths() options.weight must be a string.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"paths() options.outputTable must be a string or boolean.\");\n }\n\n const metric = prepareGraphMetricOptions(options, \"paths()\", false);\n const endpoints = prepareGraphRouteEndpoints(start, end, \"paths()\");\n const direction = options.direction ?? \"outgoing\";\n const temporalOptions = prepareGraphTemporalOptions(options, direction, \"paths()\");\n options = structuredClone(options);\n const parameters = {\n sourceColumn,\n targetColumn,\n edgeId,\n start,\n end,\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"paths()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) => validateGraphTemporalEvents(input, temporalOptions, \"paths()\", parameters),\n values: (schema) => {\n const validated = validateGraphRouteInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n options.weight,\n \"paths()\",\n );\n graphRouteResultSchema(schema, validated.distanceType, \"paths()\", metric.elapsedTime);\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"paths()\");\n return temporal === undefined\n ? endpoints.values.values\n : [temporal.gapParameter, ...endpoints.values.values];\n },\n buildSelect: (input, schema) =>\n pathsSelect(\n input,\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n direction,\n options.weight,\n temporalOptions,\n metric.elapsedTime,\n ),\n outputSchema: (schema) => {\n const validated = validateGraphRouteInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n endpoints,\n options.weight,\n \"paths()\",\n );\n if (temporalOptions !== undefined) {\n prepareGraphTemporalSql(schema, temporalOptions, \"paths()\");\n }\n return graphRouteResultSchema(schema, validated.distanceType, \"paths()\", metric.elapsedTime);\n },\n });\n}\n\nfunction pathsSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n routeEndpoints: PreparedGraphRouteEndpoints,\n direction: GraphDirection,\n weight: string | undefined,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n elapsedTime: boolean,\n): string {\n const route = prepareGraphRouteSql(\n input,\n schema,\n source,\n target,\n edgeId,\n routeEndpoints,\n weight,\n \"paths()\",\n );\n const prepared = route.traversal;\n if (temporalOptions !== undefined) {\n const temporal = prepareGraphTemporalSql(schema, temporalOptions, \"paths()\");\n return temporalPathsSelect(\n route,\n direction as Exclude<GraphDirection, \"both\">,\n temporal,\n elapsedTime,\n );\n }\n const distanceType = route.distanceType;\n const q = quoteIdentifier;\n\n const relations = prepared.relationNames([\n \"graph_route_endpoints\",\n \"graph_edges\",\n \"graph_nodes\",\n \"graph_to_end\",\n \"graph_routes\",\n \"graph_complete_routes\",\n \"graph_ranked_routes\",\n ]);\n const endpointRelation = relations.graph_route_endpoints;\n const edgesRelation = relations.graph_edges;\n const nodesRelation = relations.graph_nodes;\n const toEndRelation = relations.graph_to_end;\n const routesRelation = relations.graph_routes;\n const completeRelation = relations.graph_complete_routes;\n const rankedRelation = relations.graph_ranked_routes;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const candidateDistance = `CAST(${q(\"routes\")}.${q(\n \"distance\",\n )} + ${edgeCost} AS ${distanceType})`;\n\n return `WITH RECURSIVE ${endpointRelation}(\n ${q(\"start\")}, ${q(\"end\")}, ${q(\"__start_key\")}, ${q(\"__end_key\")}\n ) AS (\n SELECT ${q(\"start\")}, ${q(\"end\")},\n ${prepared.key(q(\"start\"))}, ${prepared.key(q(\"end\"))}\n FROM (SELECT ${route.endpointValue} AS ${q(\"start\")},\n ${route.endpointValue} AS ${q(\"end\")}) AS ${q(\"values\")}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction, [\n `${route.typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${route.edgeKey} AS ${q(\"__edge_key\")}`,\n `${route.edgeWeight} AS ${q(\"__weight\")}`,\n ])}\n ), ${nodesRelation} AS (\n SELECT ${q(\"__from_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n UNION\n SELECT ${q(\"__to_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n ), ${toEndRelation}(${q(\"__key\")}) AS (\n SELECT ${q(\"__end_key\")}\n FROM ${endpointRelation}\n INNER JOIN ${nodesRelation}\n ON ${q(\"__end_key\")} = ${q(\"__key\")}\n UNION\n SELECT ${edgeFromKey}\n FROM ${toEndRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__key\")} = ${edgeToKey}\n ), ${routesRelation}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"__visited\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}, ${q(\"distance\")}\n ) AS (\n SELECT ${q(\"start\")}, ${q(\"__start_key\")},\n [${q(\"__start_key\")}], CAST([] AS ${route.keyType}[]),\n CAST([] AS ${route.stepType}[]), CAST(0 AS ${distanceType})\n FROM ${endpointRelation}\n INNER JOIN ${toEndRelation}\n ON ${q(\"__start_key\")} = ${q(\"__key\")}\n UNION ALL\n SELECT ${edgeTo}, ${edgeToKey},\n list_append(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"routes\")}.${q(\"__edge_keys\")}, ${q(\"edges\")}.${q(\"__edge_key\")}),\n list_append(${q(\"routes\")}.${q(\"steps\")}, struct_pack(\n ${q(\"edgeId\")} := ${q(\"edges\")}.${q(\"__edge_id\")},\n ${q(\"source\")} := ${q(\"edges\")}.${q(\"__from\")},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${candidateDistance}\n )), ${candidateDistance}\n FROM ${routesRelation} AS ${q(\"routes\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"routes\")}.${q(\"__node_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n CROSS JOIN ${endpointRelation}\n WHERE ${q(\"routes\")}.${q(\"__node_key\")} <> ${q(\"__end_key\")}\n AND NOT list_contains(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey})\n ), ${completeRelation} AS (\n SELECT ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${routesRelation}\n CROSS JOIN ${endpointRelation}\n WHERE ${q(\"__node_key\")} = ${q(\"__end_key\")}\n ), ${rankedRelation} AS (\n SELECT CAST(row_number() OVER (ORDER BY ${q(\"__edge_keys\")}) - 1 AS BIGINT) AS ${q(\"pathId\")},\n ${q(\"steps\")}\n FROM ${completeRelation}\n )\n ${graphRouteResultSelect(rankedRelation, route.input, route.edgeIdColumn)}`;\n}\n\nfunction temporalPathsSelect(\n route: ReturnType<typeof prepareGraphRouteSql>,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n elapsedTime: boolean,\n): string {\n const prepared = route.traversal;\n const distanceType = route.distanceType;\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_route_endpoints\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_nodes\",\n \"graph_to_end\",\n \"graph_routes\",\n \"graph_complete_routes\",\n \"graph_ranked_routes\",\n ]);\n const endpointRelation = relations.graph_route_endpoints;\n const settingsRelation = relations.graph_temporal_settings;\n const eventRowsRelation = relations.graph_event_rows;\n const edgesRelation = relations.graph_edges;\n const nodesRelation = relations.graph_nodes;\n const toEndRelation = relations.graph_to_end;\n const routesRelation = relations.graph_routes;\n const completeRelation = relations.graph_complete_routes;\n const rankedRelation = relations.graph_ranked_routes;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const edgeKey = `${q(\"edges\")}.${q(\"__edge_key\")}`;\n const candidateDistance = `CAST(${q(\"routes\")}.${q(\n \"distance\",\n )} + ${edgeCost} AS ${distanceType})`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const firstAnchor = temporal.journeyAnchor(\"edges\", direction);\n const anchor = `${q(\"routes\")}.${q(\"__journey_anchor\")}`;\n const step = (distance: string, journeyAnchor: string) =>\n `struct_pack(\n ${q(\"edgeId\")} := ${q(\"edges\")}.${q(\"__edge_id\")},\n ${q(\"source\")} := ${q(\"edges\")}.${q(\"__from\")},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${distance}${\n elapsedTime\n ? `, ${q(\"elapsedTimeMs\")} := ${temporal.elapsedMilliseconds(\n temporal.journeyElapsed(\"edges\", journeyAnchor, direction),\n )}`\n : \"\"\n }\n )`;\n\n return `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (\n SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}\n ), ${endpointRelation}(\n ${q(\"start\")}, ${q(\"end\")}, ${q(\"__start_key\")}, ${q(\"__end_key\")}\n ) AS (\n SELECT ${q(\"start\")}, ${q(\"end\")},\n ${prepared.key(q(\"start\"))}, ${prepared.key(q(\"end\"))}\n FROM (SELECT ${route.endpointValue} AS ${q(\"start\")},\n ${route.endpointValue} AS ${q(\"end\")}) AS ${q(\"values\")}\n ), ${eventRowsRelation} AS MATERIALIZED (\n ${prepared.edges(direction, [\n `${route.typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${route.edgeKey} AS ${q(\"__edge_key\")}`,\n `${route.edgeWeight} AS ${q(\"__weight\")}`,\n ...temporal.eventSelections(\"edges\"),\n ])}\n ), ${edgesRelation} AS MATERIALIZED (\n SELECT *\n FROM ${eventRowsRelation} AS ${q(\"events\")}\n WHERE ${temporal.eventValidity(\"events\")}\n ), ${nodesRelation} AS (\n SELECT ${q(\"__from_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n UNION\n SELECT ${q(\"__to_key\")} AS ${q(\"__key\")} FROM ${edgesRelation}\n ), ${toEndRelation}(${q(\"__key\")}) AS (\n SELECT ${q(\"__end_key\")}\n FROM ${endpointRelation}\n INNER JOIN ${nodesRelation}\n ON ${q(\"__end_key\")} = ${q(\"__key\")}\n UNION\n SELECT ${edgeFromKey}\n FROM ${toEndRelation} AS ${q(\"reached\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__key\")} = ${edgeToKey}\n ), ${routesRelation}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"__visited\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}, ${q(\"distance\")},\n ${q(\"__event_id\")}, ${q(\"__event_start\")}, ${q(\"__event_end\")}${\n elapsedTime ? `, ${q(\"__journey_anchor\")}` : \"\"\n }\n ) AS (\n SELECT ${edgeTo}, ${edgeToKey},\n [${q(\"__start_key\")}, ${edgeToKey}], [${edgeKey}],\n [${step(edgeCost, firstAnchor)}], ${edgeCost},\n ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${elapsedTime ? `, ${firstAnchor}` : \"\"}\n FROM ${endpointRelation}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"__start_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n WHERE ${q(\"__start_key\")} <> ${edgeToKey}\n UNION ALL\n SELECT ${edgeTo}, ${edgeToKey},\n list_append(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"routes\")}.${q(\"__edge_keys\")}, ${edgeKey}),\n list_append(${q(\"routes\")}.${q(\"steps\")}, ${step(candidateDistance, anchor)}),\n ${candidateDistance}, ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${elapsedTime ? `, ${anchor}` : \"\"}\n FROM ${routesRelation} AS ${q(\"routes\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"routes\")}.${q(\"__node_key\")} = ${edgeFromKey}\n INNER JOIN ${toEndRelation} AS ${q(\"can_reach_end\")}\n ON ${edgeToKey} = ${q(\"can_reach_end\")}.${q(\"__key\")}\n CROSS JOIN ${endpointRelation}\n CROSS JOIN ${settingsRelation} AS ${q(\"settings\")}\n WHERE ${q(\"routes\")}.${q(\"__node_key\")} <> ${q(\"__end_key\")}\n AND NOT list_contains(${q(\"routes\")}.${q(\"__visited\")}, ${edgeToKey})\n AND ${temporal.transition(\"routes\", \"edges\", direction, gap)}\n ), ${completeRelation} AS (\n SELECT ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${routesRelation}\n CROSS JOIN ${endpointRelation}\n WHERE ${q(\"__node_key\")} = ${q(\"__end_key\")}\n ), ${rankedRelation} AS (\n SELECT CAST(row_number() OVER (ORDER BY ${q(\"__edge_keys\")}) - 1 AS BIGINT)\n AS ${q(\"pathId\")}, ${q(\"steps\")}\n FROM ${completeRelation}\n )\n ${graphRouteResultSelect(rankedRelation, route.input, route.edgeIdColumn, false, elapsedTime)}`;\n}\n","import buildGraphTemporalReachabilitySql from \"./buildGraphTemporalReachabilitySql.ts\";\nimport type { PreparedGraphTemporalSql } from \"./prepareGraphTemporalSql.ts\";\nimport type { PreparedGraphSql } from \"./prepareGraphTraversal.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/** Builds all-pairs chronological reachability and maximal-clique membership SQL. */\nexport default function buildChronologicalGraphComponentsSql(\n prepared: PreparedGraphSql,\n temporal: PreparedGraphTemporalSql,\n): string {\n const q = quoteIdentifier;\n // Temporal mutual reachability is not transitive: groups are maximal cliques\n // that may overlap. Returning every group has exponential worst-case output.\n const reachability = buildGraphTemporalReachabilitySql(\n prepared,\n (edges) =>\n `SELECT ${q(\"__from\")} AS ${q(\"start\")},\n ${q(\"__from_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n UNION\n SELECT ${q(\"__to\")}, ${q(\"__to_key\")} FROM ${edges}`,\n \"outgoing\",\n temporal,\n );\n const relations = prepared.relationNames([\n \"graph_component_nodes\",\n \"graph_component_reachability\",\n \"graph_mutual_neighbors\",\n \"graph_mutual_adjacency\",\n \"graph_clique_initial\",\n \"graph_clique_search\",\n \"graph_maximal_cliques\",\n \"graph_numbered_cliques\",\n ]);\n const nodes = relations.graph_component_nodes;\n const reached = relations.graph_component_reachability;\n const mutual = relations.graph_mutual_neighbors;\n const adjacency = relations.graph_mutual_adjacency;\n const initial = relations.graph_clique_initial;\n const search = relations.graph_clique_search;\n const maximal = relations.graph_maximal_cliques;\n const numbered = relations.graph_numbered_cliques;\n const edges = reachability.edgesRelation;\n const reachable = reachability.reachableRelation;\n\n return `${reachability.withClause}, ${nodes} AS MATERIALIZED (\n SELECT ${q(\"node\")}, ${q(\"__key\")}\n FROM (\n SELECT ${q(\"__from\")} AS ${q(\"node\")},\n ${q(\"__from_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n UNION\n SELECT ${q(\"__to\")}, ${q(\"__to_key\")} FROM ${edges}\n ) AS ${q(\"valid_nodes\")}\n ), ${reached} AS MATERIALIZED (\n SELECT ${q(\"__start_key\")}, ${q(\"__node_key\")}\n FROM ${reachable}\n UNION\n SELECT ${q(\"__key\")}, ${q(\"__key\")} FROM ${nodes}\n ), ${mutual} AS MATERIALIZED (\n SELECT ${q(\"forward\")}.${q(\"__start_key\")} AS ${q(\"__key\")},\n ${q(\"forward\")}.${q(\"__node_key\")} AS ${q(\"__neighbor_key\")}\n FROM ${reached} AS ${q(\"forward\")}\n INNER JOIN ${reached} AS ${q(\"reverse\")}\n ON ${q(\"forward\")}.${q(\"__start_key\")} =\n ${q(\"reverse\")}.${q(\"__node_key\")}\n AND ${q(\"forward\")}.${q(\"__node_key\")} =\n ${q(\"reverse\")}.${q(\"__start_key\")}\n WHERE ${q(\"forward\")}.${q(\"__start_key\")} !=\n ${q(\"forward\")}.${q(\"__node_key\")}\n ), ${buildMaximalGraphCliquesSql(nodes, mutual, {\n adjacency,\n initial,\n maximal,\n numbered,\n search,\n })}\n SELECT ${q(\"numbered\")}.${q(\"componentId\")},\n ${q(\"nodes\")}.${q(\"node\")}\n FROM ${numbered} AS ${q(\"numbered\")}\n CROSS JOIN unnest(${q(\"numbered\")}.${q(\"__members\")}) WITH ORDINALITY\n AS ${q(\"member\")}(${q(\"__key\")}, ${q(\"__order\")})\n INNER JOIN ${nodes} AS ${q(\"nodes\")}\n ON ${q(\"member\")}.${q(\"__key\")} = ${q(\"nodes\")}.${q(\"__key\")}\n ORDER BY ${q(\"numbered\")}.${q(\"componentId\")},\n ${q(\"member\")}.${q(\"__order\")}`;\n}\n\nexport type MaximalGraphCliqueRelations = {\n adjacency: string;\n initial: string;\n maximal: string;\n numbered: string;\n search: string;\n};\n\n/** Builds pivoted Bron–Kerbosch CTEs over typed node and mutual-edge relations. */\nexport function buildMaximalGraphCliquesSql(\n nodes: string,\n mutual: string,\n relations: MaximalGraphCliqueRelations,\n): string {\n const q = quoteIdentifier;\n const { adjacency, initial, maximal, numbered, search } = relations;\n // Sibling candidates are P minus the pivot's neighbors. For branch v, move\n // only earlier siblings (candidate < v and outside N(pivot)) from P to X;\n // earlier P vertices inside N(pivot) must remain prospective.\n return `${adjacency} AS MATERIALIZED (\n SELECT ${q(\"nodes\")}.${q(\"__key\")},\n COALESCE(\n list(${q(\"mutual\")}.${q(\"__neighbor_key\")}\n ORDER BY ${q(\"mutual\")}.${q(\"__neighbor_key\")})\n FILTER (WHERE ${q(\"mutual\")}.${q(\"__neighbor_key\")} IS NOT NULL),\n list_slice(list_value(${q(\"nodes\")}.${q(\"__key\")}), 1, 0)\n ) AS ${q(\"__neighbors\")}\n FROM ${nodes} AS ${q(\"nodes\")}\n LEFT JOIN ${mutual} AS ${q(\"mutual\")}\n ON ${q(\"nodes\")}.${q(\"__key\")} = ${q(\"mutual\")}.${q(\"__key\")}\n GROUP BY ${q(\"nodes\")}.${q(\"__key\")}\n ), ${initial} AS MATERIALIZED (\n SELECT list_slice(${q(\"__keys\")}, 1, 0) AS ${q(\"__r\")},\n ${q(\"__keys\")} AS ${q(\"__p\")},\n list_slice(${q(\"__keys\")}, 1, 0) AS ${q(\"__x\")}\n FROM (\n SELECT list(${q(\"__key\")} ORDER BY ${q(\"__key\")}) AS ${q(\"__keys\")}\n FROM ${nodes}\n ) AS ${q(\"all_nodes\")}\n WHERE ${q(\"__keys\")} IS NOT NULL\n ), ${search}(${q(\"__r\")}, ${q(\"__p\")}, ${q(\"__x\")}) AS (\n SELECT ${q(\"__r\")}, ${q(\"__p\")}, ${q(\"__x\")} FROM ${initial}\n UNION ALL\n SELECT list_append(${q(\"state\")}.${q(\"__r\")},\n ${q(\"branch\")}.${q(\"__key\")}),\n list_filter(${q(\"state\")}.${q(\"__p\")}, ${q(\"candidate\")} ->\n list_contains(${q(\"branch_neighbors\")}.${q(\"__neighbors\")},\n ${q(\"candidate\")})\n AND (\n ${q(\"candidate\")} >= ${q(\"branch\")}.${q(\"__key\")}\n OR list_contains(${q(\"pivot\")}.${q(\"__neighbors\")},\n ${q(\"candidate\")})\n )),\n list_filter(\n list_concat(${q(\"state\")}.${q(\"__x\")},\n ${q(\"state\")}.${q(\"__p\")}),\n ${q(\"candidate\")} ->\n list_contains(${q(\"branch_neighbors\")}.${q(\"__neighbors\")},\n ${q(\"candidate\")})\n AND (\n list_contains(${q(\"state\")}.${q(\"__x\")}, ${q(\"candidate\")})\n OR (\n ${q(\"candidate\")} < ${q(\"branch\")}.${q(\"__key\")}\n AND NOT list_contains(${q(\"pivot\")}.${q(\"__neighbors\")},\n ${q(\"candidate\")})\n )\n )\n )\n FROM ${search} AS ${q(\"state\")}\n CROSS JOIN LATERAL (\n SELECT ${q(\"candidate_adjacency\")}.${q(\"__key\")},\n ${q(\"candidate_adjacency\")}.${q(\"__neighbors\")}\n FROM unnest(list_concat(${q(\"state\")}.${q(\"__p\")},\n ${q(\"state\")}.${q(\"__x\")})) AS ${q(\"candidate_key\")}(${q(\"__key\")})\n INNER JOIN ${adjacency} AS ${q(\"candidate_adjacency\")}\n ON ${q(\"candidate_key\")}.${q(\"__key\")} =\n ${q(\"candidate_adjacency\")}.${q(\"__key\")}\n ORDER BY list_unique(list_intersect(\n ${q(\"state\")}.${q(\"__p\")},\n ${q(\"candidate_adjacency\")}.${q(\"__neighbors\")}\n )) DESC,\n ${q(\"candidate_adjacency\")}.${q(\"__key\")}\n LIMIT 1\n ) AS ${q(\"pivot\")}\n CROSS JOIN LATERAL (\n SELECT ${q(\"candidate\")}.${q(\"__key\")}\n FROM unnest(${q(\"state\")}.${q(\"__p\")})\n AS ${q(\"candidate\")}(${q(\"__key\")})\n WHERE NOT list_contains(${q(\"pivot\")}.${q(\"__neighbors\")},\n ${q(\"candidate\")}.${q(\"__key\")})\n ) AS ${q(\"branch\")}\n INNER JOIN ${adjacency} AS ${q(\"branch_neighbors\")}\n ON ${q(\"branch\")}.${q(\"__key\")} =\n ${q(\"branch_neighbors\")}.${q(\"__key\")}\n ), ${maximal} AS MATERIALIZED (\n SELECT list_sort(${q(\"__r\")}) AS ${q(\"__members\")}\n FROM ${search}\n WHERE len(${q(\"__p\")}) = 0 AND len(${q(\"__x\")}) = 0\n ), ${numbered} AS MATERIALIZED (\n SELECT ${q(\"__members\")},\n CAST(row_number() OVER (ORDER BY ${q(\"__members\")}) - 1 AS BIGINT)\n AS ${q(\"componentId\")}\n FROM ${maximal}\n )`;\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/** Builds weak component labels and zero-based IDs from bidirectional edges. */\nexport default function buildWeakGraphComponentsSql(\n edges: string,\n nodes: string,\n labels: string,\n roots: string,\n): string {\n const q = quoteIdentifier;\n return `${labels}(\n ${q(\"node\")}, ${q(\"__node_key\")}, ${q(\"__root_key\")}\n ) USING KEY(${q(\"__node_key\")}) AS (\n SELECT ${q(\"node\")}, ${q(\"__key\")}, ${q(\"__key\")}\n FROM ${nodes}\n UNION\n SELECT ${q(\"edges\")}.${q(\"__to\")},\n ${q(\"edges\")}.${q(\"__to_key\")},\n MIN(${q(\"reached\")}.${q(\"__root_key\")})\n FROM ${labels} AS ${q(\"reached\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__node_key\")} =\n ${q(\"edges\")}.${q(\"__from_key\")}\n INNER JOIN recurring.${labels} AS ${q(\"best\")}\n ON ${q(\"edges\")}.${q(\"__to_key\")} =\n ${q(\"best\")}.${q(\"__node_key\")}\n GROUP BY ${q(\"edges\")}.${q(\"__to\")},\n ${q(\"edges\")}.${q(\"__to_key\")}, ${q(\"best\")}.${q(\"__root_key\")}\n HAVING MIN(${q(\"reached\")}.${q(\"__root_key\")}) <\n ${q(\"best\")}.${q(\"__root_key\")}\n ), ${roots} AS (\n SELECT ${q(\"__root_key\")},\n CAST(row_number() OVER (ORDER BY ${q(\"__root_key\")}) - 1 AS BIGINT)\n AS ${q(\"componentId\")}\n FROM (SELECT DISTINCT ${q(\"__root_key\")} FROM ${labels})\n AS ${q(\"distinct_roots\")}\n )`;\n}\n","import buildChronologicalGraphComponentsSql from \"../helpers/buildChronologicalGraphComponentsSql.ts\";\nimport buildWeakGraphComponentsSql from \"../helpers/buildWeakGraphComponentsSql.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getGraphEndpointColumns from \"../helpers/getGraphEndpointColumns.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport { prepareGraphSql } from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\n\ntype ConnectedComponentsOptions = GraphTemporalOptions & {\n mode?: \"weak\" | \"strong\";\n outputTable?: string | boolean;\n};\n\nexport default function connectedComponents(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n options: ConnectedComponentsOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"connectedComponents() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"connectedComponents() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"connectedComponents() options must be an object.\");\n }\n if (options.mode !== undefined && ![\"weak\", \"strong\"].includes(options.mode)) {\n throw new TypeError('connectedComponents() options.mode must be \"weak\" or \"strong\".');\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"connectedComponents() options.outputTable must be a string or boolean.\");\n }\n\n const temporalOptions = prepareGraphTemporalOptions(options, undefined, \"connectedComponents()\");\n if (temporalOptions !== undefined && options.mode !== \"strong\") {\n throw new TypeError(\n 'connectedComponents() chronological options require options.mode to be explicitly set to \"strong\".',\n );\n }\n options = structuredClone(options);\n const mode = options.mode ?? \"weak\";\n const parameters = { sourceColumn, targetColumn, options };\n\n return queueGraphResult(simpleTable, {\n method: \"connectedComponents()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) =>\n validateGraphTemporalEvents(\n input,\n temporalOptions,\n \"connectedComponents()\",\n parameters,\n ),\n values: (schema) => {\n const temporal = validateInputs(schema, sourceColumn, targetColumn, temporalOptions).temporal;\n return temporal === undefined ? [] : [temporal.gapParameter];\n },\n buildSelect: (input, schema) =>\n connectedComponentsSelect(input, schema, sourceColumn, targetColumn, mode, temporalOptions),\n outputSchema: (schema) => ({\n componentId: \"BIGINT\",\n node: validateInputs(schema, sourceColumn, targetColumn, temporalOptions).endpoints.idType,\n }),\n });\n}\n\nfunction validateEndpoints(schema: TableSchema, source: string, target: string) {\n return getGraphEndpointColumns(schema, source, target, \"connectedComponents()\");\n}\n\nfunction validateInputs(\n schema: TableSchema,\n source: string,\n target: string,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n) {\n const endpoints = validateEndpoints(schema, source, target);\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"connectedComponents()\");\n return { endpoints, temporal };\n}\n\nfunction connectedComponentsSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n mode: \"weak\" | \"strong\",\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n): string {\n const prepared = prepareGraphSql(input, schema, source, target, \"connectedComponents()\");\n if (temporalOptions !== undefined) {\n return buildChronologicalGraphComponentsSql(\n prepared,\n prepareGraphTemporalSql(schema, temporalOptions, \"connectedComponents()\"),\n );\n }\n const relationNames =\n mode === \"weak\"\n ? [\"graph_edges\", \"graph_nodes\", \"graph_component_labels\", \"graph_component_roots\"]\n : [\n \"graph_edges\",\n \"graph_nodes\",\n \"graph_reachable\",\n \"graph_component_members\",\n \"graph_component_roots\",\n ];\n const relations = prepared.relationNames(relationNames);\n const edges = relations.graph_edges;\n const nodes = relations.graph_nodes;\n const roots = relations.graph_component_roots;\n const q = quoteIdentifier;\n\n const common = `${edges} AS (\n ${prepared.edges(mode === \"weak\" ? \"both\" : \"outgoing\")}\n ), ${nodes} AS (\n SELECT ${q(\"__from\")} AS ${q(\"node\")},\n ${q(\"__from_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n UNION\n SELECT ${q(\"__to\")} AS ${q(\"node\")},\n ${q(\"__to_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n )`;\n\n if (mode === \"weak\") {\n const labels = relations.graph_component_labels;\n return `WITH RECURSIVE ${common}, ${buildWeakGraphComponentsSql(edges, nodes, labels, roots)}\n SELECT ${q(\"roots\")}.${q(\"componentId\")}, ${q(\"labels\")}.${q(\"node\")}\n FROM ${labels} AS ${q(\"labels\")}\n INNER JOIN ${roots} AS ${q(\"roots\")}\n ON ${q(\"labels\")}.${q(\"__root_key\")} =\n ${q(\"roots\")}.${q(\"__root_key\")}\n ORDER BY ${q(\"labels\")}.${q(\"__node_key\")}`;\n }\n\n const reachable = relations.graph_reachable;\n const members = relations.graph_component_members;\n return `WITH RECURSIVE ${common}, ${reachable}(\n ${q(\"__start_key\")}, ${q(\"__node_key\")}\n ) AS (\n SELECT ${q(\"__key\")}, ${q(\"__key\")} FROM ${nodes}\n UNION\n SELECT ${q(\"reached\")}.${q(\"__start_key\")},\n ${q(\"edges\")}.${q(\"__to_key\")}\n FROM ${reachable} AS ${q(\"reached\")}\n INNER JOIN ${edges} AS ${q(\"edges\")}\n ON ${q(\"reached\")}.${q(\"__node_key\")} =\n ${q(\"edges\")}.${q(\"__from_key\")}\n ), ${members} AS (\n SELECT ${q(\"nodes\")}.${q(\"node\")}, ${q(\"nodes\")}.${q(\"__key\")},\n MIN(${q(\"forward\")}.${q(\"__start_key\")}) AS ${q(\"__root_key\")}\n FROM ${nodes} AS ${q(\"nodes\")}\n INNER JOIN ${reachable} AS ${q(\"forward\")}\n ON ${q(\"nodes\")}.${q(\"__key\")} =\n ${q(\"forward\")}.${q(\"__node_key\")}\n INNER JOIN ${reachable} AS ${q(\"reverse\")}\n ON ${q(\"forward\")}.${q(\"__start_key\")} =\n ${q(\"reverse\")}.${q(\"__node_key\")}\n AND ${q(\"nodes\")}.${q(\"__key\")} =\n ${q(\"reverse\")}.${q(\"__start_key\")}\n GROUP BY ${q(\"nodes\")}.${q(\"node\")}, ${q(\"nodes\")}.${q(\"__key\")}\n ), ${roots} AS (\n SELECT ${q(\"__root_key\")},\n CAST(row_number() OVER (ORDER BY ${q(\"__root_key\")}) - 1 AS BIGINT)\n AS ${q(\"componentId\")}\n FROM (SELECT DISTINCT ${q(\"__root_key\")} FROM ${members})\n AS ${q(\"distinct_roots\")}\n )\n SELECT ${q(\"roots\")}.${q(\"componentId\")}, ${q(\"members\")}.${q(\"node\")}\n FROM ${members} AS ${q(\"members\")}\n INNER JOIN ${roots} AS ${q(\"roots\")}\n ON ${q(\"members\")}.${q(\"__root_key\")} =\n ${q(\"roots\")}.${q(\"__root_key\")}\n ORDER BY ${q(\"members\")}.${q(\"__key\")}`;\n}\n","import buildWeakGraphComponentsSql from \"../helpers/buildWeakGraphComponentsSql.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getGraphEndpointColumns from \"../helpers/getGraphEndpointColumns.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport { prepareGraphSql } from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype TopologicalSortOptions = {\n outputTable?: string | boolean;\n};\n\nexport default function topologicalSort(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n options: TopologicalSortOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"topologicalSort() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"topologicalSort() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"topologicalSort() options must be an object.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"topologicalSort() options.outputTable must be a string or boolean.\");\n }\n\n options = structuredClone(options);\n const parameters = { sourceColumn, targetColumn, options };\n\n const result = queueGraphResult(simpleTable, {\n method: \"topologicalSort()\",\n parameters,\n outputTable: options.outputTable,\n values: (schema) => {\n validateEndpoints(schema, sourceColumn, targetColumn);\n return [];\n },\n buildSelect: (input, schema) =>\n topologicalSortSelect(input, schema, sourceColumn, targetColumn),\n outputSchema: (schema) => ({\n node: validateEndpoints(schema, sourceColumn, targetColumn).idType,\n componentId: \"BIGINT\",\n order: \"BIGINT\",\n }),\n });\n // Materialize the sorting computation before downstream operations: DuckDB\n // can otherwise discard even its terminal cycle check for LIMIT 0 or FALSE.\n // This barrier adds no query or separate validation traversal, and upstream\n // preparation still fuses into the sorting statement.\n queueOp(result, {\n kind: \"barrier\",\n method: \"topologicalSort()\",\n parameters,\n execute: () => Promise.resolve(),\n });\n return result;\n}\n\nfunction validateEndpoints(schema: TableSchema, source: string, target: string) {\n return getGraphEndpointColumns(schema, source, target, \"topologicalSort()\");\n}\n\nfunction topologicalSortSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n): string {\n const prepared = prepareGraphSql(input, schema, source, target, \"topologicalSort()\");\n const relations = prepared.relationNames([\n \"graph_edges\",\n \"graph_nodes\",\n \"graph_topological_order\",\n \"graph_topological_result\",\n \"graph_component_edges\",\n \"graph_component_labels\",\n \"graph_component_roots\",\n \"graph_ordered_nodes\",\n ]);\n const edges = relations.graph_edges;\n const nodes = relations.graph_nodes;\n const ordering = relations.graph_topological_order;\n const result = relations.graph_topological_result;\n const componentEdges = relations.graph_component_edges;\n const labels = relations.graph_component_labels;\n const roots = relations.graph_component_roots;\n const orderedNodes = relations.graph_ordered_nodes;\n const q = quoteIdentifier;\n\n return `WITH RECURSIVE ${edges} AS (\n ${prepared.edges(\"outgoing\")}\n ), ${nodes} AS (\n SELECT ${q(\"__from\")} AS ${q(\"node\")},\n ${q(\"__from_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n UNION\n SELECT ${q(\"__to\")} AS ${q(\"node\")},\n ${q(\"__to_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n ), ${componentEdges} AS (\n SELECT * FROM ${edges}\n UNION ALL\n SELECT ${q(\"__to\")}, ${q(\"__from\")},\n ${q(\"__to_key\")}, ${q(\"__from_key\")}\n FROM ${edges}\n ), ${buildWeakGraphComponentsSql(componentEdges, nodes, labels, roots)},\n ${ordering}(\n ${q(\"node\")}, ${q(\"__key\")}, ${q(\"order\")}, ${q(\"__ordered\")}\n ) AS (\n SELECT ${q(\"eligible\")}.${q(\"node\")},\n ${q(\"eligible\")}.${q(\"__key\")}, CAST(1 AS BIGINT),\n list_value(${q(\"eligible\")}.${q(\"__key\")})\n FROM (\n SELECT ${q(\"candidate\")}.${q(\"node\")},\n ${q(\"candidate\")}.${q(\"__key\")}\n FROM ${nodes} AS ${q(\"candidate\")}\n WHERE NOT EXISTS (\n SELECT 1 FROM ${edges} AS ${q(\"edge\")}\n WHERE ${q(\"edge\")}.${q(\"__to_key\")} =\n ${q(\"candidate\")}.${q(\"__key\")}\n )\n ORDER BY ${q(\"candidate\")}.${q(\"__key\")}\n LIMIT 1\n ) AS ${q(\"eligible\")}\n UNION ALL\n SELECT ${q(\"eligible\")}.${q(\"node\")},\n ${q(\"eligible\")}.${q(\"__key\")},\n ${q(\"ordered\")}.${q(\"order\")} + 1,\n list_append(\n ${q(\"ordered\")}.${q(\"__ordered\")},\n ${q(\"eligible\")}.${q(\"__key\")}\n )\n FROM ${ordering} AS ${q(\"ordered\")}\n CROSS JOIN LATERAL (\n SELECT ${q(\"candidate\")}.${q(\"node\")},\n ${q(\"candidate\")}.${q(\"__key\")}\n FROM ${nodes} AS ${q(\"candidate\")}\n WHERE NOT list_contains(\n ${q(\"ordered\")}.${q(\"__ordered\")},\n ${q(\"candidate\")}.${q(\"__key\")}\n )\n AND NOT EXISTS (\n SELECT 1 FROM ${edges} AS ${q(\"edge\")}\n WHERE ${q(\"edge\")}.${q(\"__to_key\")} =\n ${q(\"candidate\")}.${q(\"__key\")}\n AND NOT list_contains(\n ${q(\"ordered\")}.${q(\"__ordered\")},\n ${q(\"edge\")}.${q(\"__from_key\")}\n )\n )\n ORDER BY ${q(\"candidate\")}.${q(\"__key\")}\n LIMIT 1\n ) AS ${q(\"eligible\")}\n ), ${result} AS (\n SELECT CASE WHEN count(*) < (SELECT count(*) FROM ${nodes})\n THEN error(\n 'topologicalSort() cannot order the graph because it contains a directed cycle.'\n )\n ELSE list(${q(\"node\")} ORDER BY ${q(\"order\")})\n END AS ${q(\"__nodes\")}\n FROM ${ordering}\n ), ${orderedNodes} AS (\n SELECT unnest(${q(\"__nodes\")}) AS ${q(\"node\")},\n generate_subscripts(${q(\"__nodes\")}, 1) AS ${q(\"__order\")}\n FROM ${result}\n )\n SELECT ${q(\"ordered\")}.${q(\"node\")}, ${q(\"roots\")}.${q(\"componentId\")},\n row_number() OVER (\n PARTITION BY ${q(\"roots\")}.${q(\"componentId\")}\n ORDER BY ${q(\"ordered\")}.${q(\"__order\")}\n ) AS ${q(\"order\")}\n FROM ${orderedNodes} AS ${q(\"ordered\")}\n INNER JOIN ${labels} AS ${q(\"labels\")}\n ON ${prepared.key(`${q(\"ordered\")}.${q(\"node\")}`)} =\n ${q(\"labels\")}.${q(\"__node_key\")}\n INNER JOIN ${roots} AS ${q(\"roots\")}\n ON ${q(\"labels\")}.${q(\"__root_key\")} = ${q(\"roots\")}.${q(\"__root_key\")}\n ORDER BY ${q(\"componentId\")}, ${q(\"order\")}`;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport getGraphEndpointColumns from \"../helpers/getGraphEndpointColumns.ts\";\nimport getGraphWeightColumn from \"../helpers/getGraphWeightColumn.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport { prepareGraphSql } from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype DegreeOptions = {\n count?: \"edges\" | \"neighbors\";\n weight?: string;\n outputTable?: string | boolean;\n};\n\nexport default function degree(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n options: DegreeOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"degree() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"degree() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"degree() options must be an object.\");\n }\n if (options.count !== undefined && ![\"edges\", \"neighbors\"].includes(options.count)) {\n throw new TypeError('degree() options.count must be \"edges\" or \"neighbors\".');\n }\n if (options.weight !== undefined && typeof options.weight !== \"string\") {\n throw new TypeError(\"degree() options.weight must be a string.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"degree() options.outputTable must be a string or boolean.\");\n }\n if (options.weight !== undefined && options.count === \"neighbors\") {\n throw new TypeError(\n 'degree() options.weight cannot be combined with count: \"neighbors\" because weighted sums operate on edges, not distinct neighbors.',\n );\n }\n\n options = structuredClone(options);\n const count = options.count ?? \"edges\";\n const weight = options.weight;\n const parameters = { sourceColumn, targetColumn, options };\n\n return queueGraphResult(simpleTable, {\n method: \"degree()\",\n parameters,\n outputTable: options.outputTable,\n values: (schema) => {\n validateInputs(schema, sourceColumn, targetColumn, weight);\n return [];\n },\n buildSelect: (input, schema) =>\n degreeSelect(input, schema, sourceColumn, targetColumn, count, weight),\n outputSchema: (schema) => {\n const validated = validateInputs(schema, sourceColumn, targetColumn, weight);\n return {\n node: validated.idType,\n incoming: validated.degreeType,\n outgoing: validated.degreeType,\n total: validated.degreeType,\n };\n },\n });\n}\n\nfunction validateInputs(\n schema: TableSchema,\n source: string,\n target: string,\n weight: string | undefined,\n) {\n const endpoints = getGraphEndpointColumns(schema, source, target, \"degree()\");\n const degreeType =\n weight === undefined\n ? \"BIGINT\"\n : sumType(getGraphWeightColumn(schema, weight, \"degree()\").distanceType);\n return { idType: endpoints.idType, degreeType };\n}\n\nfunction sumType(type: string): string {\n // DuckDB SUM widens FLOAT to DOUBLE; retain that aggregate precision.\n return type === \"FLOAT\" ? \"DOUBLE\" : type;\n}\n\nfunction degreeSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n count: \"edges\" | \"neighbors\",\n weight: string | undefined,\n): string {\n const prepared = prepareGraphSql(input, schema, source, target, \"degree()\");\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, \"degree()\");\n const degreeType = sumType(weightColumn?.distanceType ?? \"BIGINT\");\n const relations = prepared.relationNames([\n \"graph_edges\",\n \"graph_node_candidates\",\n \"graph_nodes\",\n \"graph_incoming\",\n \"graph_outgoing\",\n ]);\n const edges = relations.graph_edges;\n const candidates = relations.graph_node_candidates;\n const nodes = relations.graph_nodes;\n const incoming = relations.graph_incoming;\n const outgoing = relations.graph_outgoing;\n const q = quoteIdentifier;\n const edgeWeight =\n weightColumn === undefined\n ? undefined\n : `CAST(${q(\"edges\")}.${q(weightColumn.column)} AS ${degreeType}) AS ${q(\"__weight\")}`;\n const aggregate = (direction: \"incoming\" | \"outgoing\") => {\n const neighborKey = direction === \"incoming\" ? \"__from_key\" : \"__to_key\";\n if (edgeWeight !== undefined) {\n return `CAST(SUM(${q(\"__weight\")}) AS ${degreeType})`;\n }\n return count === \"neighbors\" ? `COUNT(DISTINCT ${q(neighborKey)})` : \"COUNT(*)\";\n };\n const zero = `CAST(0 AS ${degreeType})`;\n const incomingDegree = `COALESCE(${q(\"incoming\")}.${q(\"incoming\")}, ${zero})`;\n const outgoingDegree = `COALESCE(${q(\"outgoing\")}.${q(\"outgoing\")}, ${zero})`;\n\n return `WITH ${edges} AS (\n ${prepared.edges(\"outgoing\", edgeWeight === undefined ? [] : [edgeWeight])}\n ), ${candidates} AS (\n SELECT ${q(\"__from\")} AS ${q(\"node\")},\n ${q(\"__from_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n UNION ALL\n SELECT ${q(\"__to\")} AS ${q(\"node\")},\n ${q(\"__to_key\")} AS ${q(\"__key\")}\n FROM ${edges}\n ), ${nodes} AS (\n SELECT MIN(${q(\"node\")}) AS ${q(\"node\")}, ${q(\"__key\")}\n FROM ${candidates}\n GROUP BY ${q(\"__key\")}\n ), ${incoming} AS (\n SELECT ${q(\"__to_key\")} AS ${q(\"__key\")},\n ${aggregate(\"incoming\")} AS ${q(\"incoming\")}\n FROM ${edges}\n GROUP BY ${q(\"__to_key\")}\n ), ${outgoing} AS (\n SELECT ${q(\"__from_key\")} AS ${q(\"__key\")},\n ${aggregate(\"outgoing\")} AS ${q(\"outgoing\")}\n FROM ${edges}\n GROUP BY ${q(\"__from_key\")}\n )\n SELECT ${q(\"nodes\")}.${q(\"node\")},\n ${incomingDegree} AS ${q(\"incoming\")},\n ${outgoingDegree} AS ${q(\"outgoing\")},\n CAST(${incomingDegree} + ${outgoingDegree} AS ${degreeType}) AS ${q(\"total\")}\n FROM ${nodes} AS ${q(\"nodes\")}\n LEFT JOIN ${incoming} AS ${q(\"incoming\")}\n ON ${q(\"nodes\")}.${q(\"__key\")} = ${q(\"incoming\")}.${q(\"__key\")}\n LEFT JOIN ${outgoing} AS ${q(\"outgoing\")}\n ON ${q(\"nodes\")}.${q(\"__key\")} = ${q(\"outgoing\")}.${q(\"__key\")}\n ORDER BY ${q(\"total\")} DESC, ${q(\"nodes\")}.${q(\"__key\")}`;\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTraversal, {\n type GraphDirection,\n validateGraphStarts,\n} from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype CommonNeighborsOptions = {\n direction?: GraphDirection;\n outputTable?: string | boolean;\n};\n\nexport default function commonNeighbors(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n nodeA: GraphId,\n nodeB: GraphId,\n options: CommonNeighborsOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"commonNeighbors() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"commonNeighbors() targetColumn must be a string.\");\n }\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"commonNeighbors() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError(\n 'commonNeighbors() options.direction must be \"outgoing\", \"incoming\", or \"both\".',\n );\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"commonNeighbors() options.outputTable must be a string or boolean.\");\n }\n\n const nodes = prepareNodes(nodeA, nodeB);\n options = structuredClone(options);\n const direction = options.direction ?? \"outgoing\";\n const parameters = { sourceColumn, targetColumn, nodeA, nodeB, options };\n\n return queueGraphResult(simpleTable, {\n method: \"commonNeighbors()\",\n parameters,\n outputTable: options.outputTable,\n values: (schema) => {\n validateNodes(schema, sourceColumn, targetColumn, nodes);\n return nodes.values;\n },\n buildSelect: (input, schema) =>\n commonNeighborsSelect(input, schema, sourceColumn, targetColumn, nodes, direction),\n outputSchema: (schema) => ({\n node: validateNodes(schema, sourceColumn, targetColumn, nodes).idType,\n }),\n });\n}\n\nfunction prepareNodes(nodeA: GraphId, nodeB: GraphId): PreparedGraphStarts {\n if (Array.isArray(nodeA)) {\n throw new TypeError(\"commonNeighbors() nodeA must be one node ID.\");\n }\n if (Array.isArray(nodeB)) {\n throw new TypeError(\"commonNeighbors() nodeB must be one node ID.\");\n }\n const first = prepareGraphStarts(nodeA, \"commonNeighbors()\", \"nodeA\", true);\n const second = prepareGraphStarts(nodeB, \"commonNeighbors()\", \"nodeB\", true);\n if (first.family !== second.family) {\n throw new TypeError(\n \"commonNeighbors() nodeA and nodeB must both be string IDs or both be numeric IDs.\",\n );\n }\n if (first.values[0] === second.values[0]) {\n throw new TypeError(\"commonNeighbors() nodeA and nodeB must be different.\");\n }\n return {\n family: first.family,\n numericValues: [...first.numericValues, ...second.numericValues],\n values: [first.values[0], second.values[0]],\n };\n}\n\nfunction validateNodes(\n schema: TableSchema,\n source: string,\n target: string,\n nodes: PreparedGraphStarts,\n) {\n return validateGraphStarts(schema, source, target, nodes, \"commonNeighbors()\", \"nodeA and nodeB\");\n}\n\nfunction commonNeighborsSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n nodes: PreparedGraphStarts,\n direction: GraphDirection,\n): string {\n const prepared = prepareGraphTraversal(\n input,\n schema,\n source,\n target,\n nodes,\n \"commonNeighbors()\",\n \"nodeA and nodeB\",\n );\n const relations = prepared.relationNames([\n \"graph_requested_nodes\",\n \"graph_edges\",\n \"graph_neighbor_memberships\",\n \"graph_common_neighbors\",\n ]);\n const requested = relations.graph_requested_nodes;\n const edges = relations.graph_edges;\n const memberships = relations.graph_neighbor_memberships;\n const common = relations.graph_common_neighbors;\n const q = quoteIdentifier;\n\n return `WITH ${requested}(${q(\"node\")}) AS (\n VALUES ${prepared.startValues}\n ), ${edges} AS (\n ${prepared.edges(direction)}\n ), ${memberships} AS (\n SELECT ${q(\"requested\")}.${q(\"node\")} AS ${q(\"requested_node\")},\n ${q(\"edges\")}.${q(\"__from_key\")} AS ${q(\"__requested_key\")},\n ${q(\"edges\")}.${q(\"__to\")} AS ${q(\"node\")},\n ${q(\"edges\")}.${q(\"__to_key\")} AS ${q(\"__node_key\")}\n FROM ${edges} AS ${q(\"edges\")}\n INNER JOIN ${requested} AS ${q(\"requested\")}\n ON ${q(\"edges\")}.${q(\"__from_key\")} =\n ${prepared.key(`${q(\"requested\")}.${q(\"node\")}`)}\n ), ${common} AS (\n SELECT MIN(${q(\"node\")}) AS ${q(\"node\")}, ${q(\"__node_key\")}\n FROM ${memberships}\n GROUP BY ${q(\"__node_key\")}\n HAVING COUNT(DISTINCT ${q(\"__requested_key\")}) = 2\n )\n SELECT ${q(\"node\")}\n FROM ${common}\n ORDER BY ${q(\"__node_key\")}`;\n}\n","import prepareGraphMetricOptions from \"../helpers/prepareGraphMetricOptions.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport getGraphEdgeIdColumn from \"../helpers/getGraphEdgeIdColumn.ts\";\nimport getGraphWeightColumn from \"../helpers/getGraphWeightColumn.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\nimport graphRouteResultSchema from \"../helpers/graphRouteResultSchema.ts\";\nimport graphRouteResultSelect from \"../helpers/graphRouteResultSelect.ts\";\nimport prepareGraphTemporalSql, {\n type GraphTemporalOptions,\n type PreparedGraphTemporalOptions,\n prepareGraphTemporalOptions,\n} from \"../helpers/prepareGraphTemporalSql.ts\";\nimport prepareGraphStarts, {\n type GraphId,\n type PreparedGraphStarts,\n} from \"../helpers/prepareGraphStarts.ts\";\nimport prepareGraphTraversal, {\n type GraphDirection,\n validateGraphStarts,\n} from \"../helpers/prepareGraphTraversal.ts\";\nimport queueGraphResult from \"../helpers/queueGraphResult.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport validateGraphTemporalEvents from \"../helpers/validateGraphTemporalEvents.ts\";\nimport validateGraphRouteResultSchema from \"../helpers/validateGraphRouteResultSchema.ts\";\n\ntype FindCyclesOptions = GraphTemporalOptions & {\n elapsedTime?: boolean;\n direction?: GraphDirection;\n outputTable?: string | boolean;\n weight?: string;\n};\n\nexport default function findCycles(\n simpleTable: SimpleTable,\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n startNodes: GraphId | GraphId[],\n options: FindCyclesOptions = {},\n): SimpleTable {\n if (typeof sourceColumn !== \"string\") {\n throw new TypeError(\"findCycles() sourceColumn must be a string.\");\n }\n if (typeof targetColumn !== \"string\") {\n throw new TypeError(\"findCycles() targetColumn must be a string.\");\n }\n if (typeof edgeId !== \"string\") {\n throw new TypeError(\"findCycles() edgeId must be a string.\");\n }\n const preparedStarts = prepareGraphStarts(startNodes, \"findCycles()\", \"startNodes\");\n if (options === null || typeof options !== \"object\" || Array.isArray(options)) {\n throw new TypeError(\"findCycles() options must be an object.\");\n }\n if (\n options.direction !== undefined &&\n ![\"outgoing\", \"incoming\", \"both\"].includes(options.direction)\n ) {\n throw new TypeError(\n 'findCycles() options.direction must be \"outgoing\", \"incoming\", or \"both\".',\n );\n }\n if (options.weight !== undefined && typeof options.weight !== \"string\") {\n throw new TypeError(\"findCycles() options.weight must be a string.\");\n }\n if (\n options.outputTable !== undefined &&\n typeof options.outputTable !== \"string\" &&\n typeof options.outputTable !== \"boolean\"\n ) {\n throw new TypeError(\"findCycles() options.outputTable must be a string or boolean.\");\n }\n\n const metric = prepareGraphMetricOptions(options, \"findCycles()\", false);\n const direction = options.direction ?? \"outgoing\";\n const temporalOptions = prepareGraphTemporalOptions(options, direction, \"findCycles()\");\n options = structuredClone(options);\n const parameters = {\n sourceColumn,\n targetColumn,\n edgeId,\n startNodes: structuredClone(startNodes),\n options,\n };\n\n return queueGraphResult(simpleTable, {\n method: \"findCycles()\",\n parameters,\n outputTable: options.outputTable,\n preflight:\n temporalOptions === undefined\n ? undefined\n : (input) =>\n validateGraphTemporalEvents(input, temporalOptions, \"findCycles()\", parameters),\n values: (schema) => {\n const validated = validateFindCyclesInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n preparedStarts,\n options.weight,\n );\n graphRouteResultSchema(schema, validated.distanceType, \"findCycles()\", metric.elapsedTime);\n const temporal =\n temporalOptions === undefined\n ? undefined\n : prepareGraphTemporalSql(schema, temporalOptions, \"findCycles()\");\n return temporal === undefined\n ? preparedStarts.values\n : [temporal.gapParameter, ...preparedStarts.values];\n },\n buildSelect: (input, schema) =>\n findCyclesSelect(\n input,\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n preparedStarts,\n direction,\n options.weight,\n temporalOptions,\n metric.elapsedTime,\n ),\n outputSchema: (schema) => {\n const validated = validateFindCyclesInputs(\n schema,\n sourceColumn,\n targetColumn,\n edgeId,\n preparedStarts,\n options.weight,\n );\n if (temporalOptions !== undefined) {\n prepareGraphTemporalSql(schema, temporalOptions, \"findCycles()\");\n }\n return {\n start: validated.nodeIdType,\n ...graphRouteResultSchema(\n schema,\n validated.distanceType,\n \"findCycles()\",\n metric.elapsedTime,\n ),\n };\n },\n });\n}\n\nfunction validateFindCyclesInputs(\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n starts: PreparedGraphStarts,\n weight: string | undefined,\n) {\n const endpoints = validateGraphStarts(\n schema,\n source,\n target,\n starts,\n \"findCycles()\",\n \"startNodes\",\n );\n const edgeIdColumn = getGraphEdgeIdColumn(schema, edgeId, \"findCycles()\");\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, \"findCycles()\");\n validateGraphRouteResultSchema(schema, \"findCycles()\", [\"start\"]);\n return {\n distanceType: weightColumn?.distanceType ?? \"BIGINT\",\n edgeIdType: edgeIdColumn.idType,\n nodeIdType: endpoints.idType,\n };\n}\n\nfunction findCyclesSelect(\n input: string,\n schema: TableSchema,\n source: string,\n target: string,\n edgeId: string,\n starts: PreparedGraphStarts,\n direction: GraphDirection,\n weight: string | undefined,\n temporalOptions: PreparedGraphTemporalOptions | undefined,\n elapsedTime: boolean,\n): string {\n const prepared = prepareGraphTraversal(\n input,\n schema,\n source,\n target,\n starts,\n \"findCycles()\",\n \"startNodes\",\n );\n const edgeIdColumn = getGraphEdgeIdColumn(schema, edgeId, \"findCycles()\");\n const weightColumn =\n weight === undefined ? undefined : getGraphWeightColumn(schema, weight, \"findCycles()\");\n const distanceType = weightColumn?.distanceType ?? \"BIGINT\";\n const q = quoteIdentifier;\n const edgeIdReference = `${q(\"edges\")}.${q(edgeIdColumn.column)}`;\n const typedEdgeId = `CAST(${edgeIdReference} AS ${edgeIdColumn.idType})`;\n const edgeKey = edgeIdColumn.family === \"string\" ? `ENCODE(${typedEdgeId})` : typedEdgeId;\n const edgeWeight =\n weightColumn === undefined\n ? `CAST(1 AS ${distanceType})`\n : `CAST(${q(\"edges\")}.${q(weightColumn.column)} AS ${distanceType})`;\n const stepType = `STRUCT(${q(\"edgeId\")} ${edgeIdColumn.idType}, ${q(\n \"source\",\n )} ${prepared.endpoints.idType}, ${q(\n \"target\",\n )} ${prepared.endpoints.idType}, ${q(\"weight\")} ${distanceType}, ${q(\n \"distance\",\n )} ${distanceType}${elapsedTime ? `, ${q(\"elapsedTimeMs\")} DOUBLE` : \"\"})`;\n\n if (temporalOptions !== undefined) {\n const temporal = prepareGraphTemporalSql(schema, temporalOptions, \"findCycles()\");\n return temporalFindCyclesSelect(\n prepared,\n direction as Exclude<GraphDirection, \"both\">,\n temporal,\n typedEdgeId,\n edgeKey,\n edgeWeight,\n distanceType,\n stepType,\n input,\n edgeIdColumn,\n elapsedTime,\n );\n }\n\n const relations = prepared.relationNames([\n \"graph_start_values\",\n \"graph_starts\",\n \"graph_edges\",\n \"graph_cycle_walks\",\n \"graph_complete_cycles\",\n \"graph_ranked_cycles\",\n ]);\n const startValuesRelation = relations.graph_start_values;\n const startsRelation = relations.graph_starts;\n const edgesRelation = relations.graph_edges;\n const walksRelation = relations.graph_cycle_walks;\n const completeRelation = relations.graph_complete_cycles;\n const rankedRelation = relations.graph_ranked_cycles;\n const edgeFrom = `${q(\"edges\")}.${q(\"__from\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeIdentity = `${q(\"edges\")}.${q(\"__edge_id\")}`;\n const edgeIdentityKey = `${q(\"edges\")}.${q(\"__edge_key\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const walkDistance = `${q(\"walks\")}.${q(\"distance\")}`;\n const candidateDistance = `CAST(${walkDistance} + ${edgeCost} AS ${distanceType})`;\n\n return `WITH RECURSIVE ${startValuesRelation}(${q(\"start\")}) AS (\n VALUES ${prepared.startValues}\n ), ${startsRelation} AS (\n SELECT ${q(\"start\")},\n ${prepared.key(q(\"start\"))} AS ${q(\"__start_key\")}\n FROM ${startValuesRelation}\n ), ${edgesRelation} AS (\n ${prepared.edges(direction, [\n `${typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${edgeKey} AS ${q(\"__edge_key\")}`,\n `${edgeWeight} AS ${q(\"__weight\")}`,\n ])}\n ), ${walksRelation}(\n ${q(\"start\")}, ${q(\"__start_key\")}, ${q(\"node\")},\n ${q(\"__node_key\")}, ${q(\"__visited\")}, ${q(\"__edge_keys\")},\n ${q(\"steps\")}, ${q(\"distance\")}, ${q(\"closed\")}\n ) AS (\n SELECT ${q(\"starts\")}.${q(\"start\")},\n ${q(\"starts\")}.${q(\"__start_key\")}, ${edgeTo}, ${edgeToKey},\n CASE WHEN ${edgeFromKey} = ${edgeToKey}\n THEN [${edgeFromKey}]\n ELSE [${edgeFromKey}, ${edgeToKey}]\n END,\n [${edgeIdentityKey}],\n [struct_pack(\n ${q(\"edgeId\")} := ${edgeIdentity},\n ${q(\"source\")} := ${edgeFrom},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${edgeCost}\n )]::${stepType}[],\n ${edgeCost}, ${edgeFromKey} = ${edgeToKey}\n FROM ${edgesRelation} AS ${q(\"edges\")}\n INNER JOIN ${startsRelation} AS ${q(\"starts\")}\n ON ${q(\"starts\")}.${q(\"__start_key\")} = ${edgeFromKey}\n UNION ALL\n SELECT ${q(\"walks\")}.${q(\"start\")},\n ${q(\"walks\")}.${q(\"__start_key\")}, ${edgeTo}, ${edgeToKey},\n list_append(${q(\"walks\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"walks\")}.${q(\"__edge_keys\")}, ${edgeIdentityKey}),\n list_append(${q(\"walks\")}.${q(\"steps\")}, struct_pack(\n ${q(\"edgeId\")} := ${edgeIdentity},\n ${q(\"source\")} := ${edgeFrom},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${candidateDistance}\n )), ${candidateDistance},\n ${edgeToKey} = ${q(\"walks\")}.${q(\"__start_key\")}\n FROM ${walksRelation} AS ${q(\"walks\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"walks\")}.${q(\"__node_key\")} = ${edgeFromKey}\n WHERE NOT ${q(\"walks\")}.${q(\"closed\")}\n AND NOT list_contains(\n ${q(\"walks\")}.${q(\"__edge_keys\")}, ${edgeIdentityKey}\n )\n AND (\n ${edgeToKey} = ${q(\"walks\")}.${q(\"__start_key\")}\n OR NOT list_contains(\n ${q(\"walks\")}.${q(\"__visited\")}, ${edgeToKey}\n )\n )\n ), ${completeRelation} AS (\n SELECT DISTINCT ${q(\"start\")}, ${q(\"__start_key\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${walksRelation}\n WHERE ${q(\"closed\")}${\n direction === \"both\"\n ? `\n AND ${q(\"__edge_keys\")} <= list_reverse(${q(\"__edge_keys\")})`\n : \"\"\n }\n ), ${rankedRelation} AS (\n SELECT ${q(\"start\")}, ${q(\"__start_key\")},\n CAST(row_number() OVER (\n PARTITION BY ${q(\"__start_key\")}\n ORDER BY ${q(\"__edge_keys\")}) - 1\n AS BIGINT) AS ${q(\"pathId\")}, ${q(\"steps\")}\n FROM ${completeRelation}\n )\n ${graphRouteResultSelect(rankedRelation, input, edgeIdColumn, true)}`;\n}\n\nfunction temporalFindCyclesSelect(\n prepared: ReturnType<typeof prepareGraphTraversal>,\n direction: Exclude<GraphDirection, \"both\">,\n temporal: ReturnType<typeof prepareGraphTemporalSql>,\n typedEdgeId: string,\n edgeKey: string,\n edgeWeight: string,\n distanceType: string,\n stepType: string,\n input: string,\n edgeIdColumn: ReturnType<typeof getGraphEdgeIdColumn>,\n elapsedTime: boolean,\n): string {\n const q = quoteIdentifier;\n const relations = prepared.relationNames([\n \"graph_start_values\",\n \"graph_starts\",\n \"graph_temporal_settings\",\n \"graph_event_rows\",\n \"graph_edges\",\n \"graph_cycle_walks\",\n \"graph_complete_cycles\",\n \"graph_ranked_cycles\",\n ]);\n const startValuesRelation = relations.graph_start_values;\n const startsRelation = relations.graph_starts;\n const settingsRelation = relations.graph_temporal_settings;\n const eventRowsRelation = relations.graph_event_rows;\n const edgesRelation = relations.graph_edges;\n const walksRelation = relations.graph_cycle_walks;\n const completeRelation = relations.graph_complete_cycles;\n const rankedRelation = relations.graph_ranked_cycles;\n const edgeFrom = `${q(\"edges\")}.${q(\"__from\")}`;\n const edgeTo = `${q(\"edges\")}.${q(\"__to\")}`;\n const edgeFromKey = `${q(\"edges\")}.${q(\"__from_key\")}`;\n const edgeToKey = `${q(\"edges\")}.${q(\"__to_key\")}`;\n const edgeIdentity = `${q(\"edges\")}.${q(\"__edge_id\")}`;\n const edgeIdentityKey = `${q(\"edges\")}.${q(\"__edge_key\")}`;\n const edgeCost = `${q(\"edges\")}.${q(\"__weight\")}`;\n const walkDistance = `${q(\"walks\")}.${q(\"distance\")}`;\n const candidateDistance = `CAST(${walkDistance} + ${edgeCost} AS ${distanceType})`;\n const gap = `${q(\"settings\")}.${q(\"__gap\")}`;\n const firstAnchor = temporal.journeyAnchor(\"edges\", direction);\n const anchor = `${q(\"walks\")}.${q(\"__journey_anchor\")}`;\n const step = (distance: string, journeyAnchor: string) =>\n `struct_pack(\n ${q(\"edgeId\")} := ${edgeIdentity},\n ${q(\"source\")} := ${edgeFrom},\n ${q(\"target\")} := ${edgeTo},\n ${q(\"weight\")} := ${edgeCost},\n ${q(\"distance\")} := ${distance}${\n elapsedTime\n ? `, ${q(\"elapsedTimeMs\")} := ${temporal.elapsedMilliseconds(\n temporal.journeyElapsed(\"edges\", journeyAnchor, direction),\n )}`\n : \"\"\n }\n )`;\n\n return `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (\n SELECT CAST(? AS HUGEINT) AS ${q(\"__gap\")}\n ), ${startValuesRelation}(${q(\"start\")}) AS (\n VALUES ${prepared.startValues}\n ), ${startsRelation} AS (\n SELECT ${q(\"start\")},\n ${prepared.key(q(\"start\"))} AS ${q(\"__start_key\")}\n FROM ${startValuesRelation}\n ), ${eventRowsRelation} AS MATERIALIZED (\n ${prepared.edges(direction, [\n `${typedEdgeId} AS ${q(\"__edge_id\")}`,\n `${edgeKey} AS ${q(\"__edge_key\")}`,\n `${edgeWeight} AS ${q(\"__weight\")}`,\n ...temporal.eventSelections(\"edges\"),\n ])}\n ), ${edgesRelation} AS MATERIALIZED (\n SELECT *\n FROM ${eventRowsRelation} AS ${q(\"events\")}\n WHERE ${temporal.eventValidity(\"events\")}\n ), ${walksRelation}(\n ${q(\"start\")}, ${q(\"__start_key\")}, ${q(\"node\")},\n ${q(\"__node_key\")}, ${q(\"__visited\")}, ${q(\"__event_ids\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}, ${q(\"distance\")},\n ${q(\"closed\")}, ${q(\"__event_id\")}, ${q(\"__event_start\")},\n ${q(\"__event_end\")}${elapsedTime ? `, ${q(\"__journey_anchor\")}` : \"\"}\n ) AS (\n SELECT ${q(\"starts\")}.${q(\"start\")},\n ${q(\"starts\")}.${q(\"__start_key\")}, ${edgeTo}, ${edgeToKey},\n CASE WHEN ${edgeFromKey} = ${edgeToKey}\n THEN [${edgeFromKey}]\n ELSE [${edgeFromKey}, ${edgeToKey}]\n END,\n [${q(\"edges\")}.${q(\"__event_id\")}], [${edgeIdentityKey}],\n [${step(edgeCost, firstAnchor)}]::${stepType}[], ${edgeCost},\n ${edgeFromKey} = ${edgeToKey},\n ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${elapsedTime ? `, ${firstAnchor}` : \"\"}\n FROM ${edgesRelation} AS ${q(\"edges\")}\n INNER JOIN ${startsRelation} AS ${q(\"starts\")}\n ON ${q(\"starts\")}.${q(\"__start_key\")} = ${edgeFromKey}\n UNION ALL\n SELECT ${q(\"walks\")}.${q(\"start\")},\n ${q(\"walks\")}.${q(\"__start_key\")}, ${edgeTo}, ${edgeToKey},\n list_append(${q(\"walks\")}.${q(\"__visited\")}, ${edgeToKey}),\n list_append(${q(\"walks\")}.${q(\"__event_ids\")},\n ${q(\"edges\")}.${q(\"__event_id\")}),\n list_append(${q(\"walks\")}.${q(\"__edge_keys\")}, ${edgeIdentityKey}),\n list_append(${q(\"walks\")}.${q(\"steps\")}, ${step(candidateDistance, anchor)}),\n ${candidateDistance},\n ${edgeToKey} = ${q(\"walks\")}.${q(\"__start_key\")},\n ${q(\"edges\")}.${q(\"__event_id\")},\n ${q(\"edges\")}.${q(\"__event_start\")},\n ${q(\"edges\")}.${q(\"__event_end\")}${elapsedTime ? `, ${anchor}` : \"\"}\n FROM ${walksRelation} AS ${q(\"walks\")}\n INNER JOIN ${edgesRelation} AS ${q(\"edges\")}\n ON ${q(\"walks\")}.${q(\"__node_key\")} = ${edgeFromKey}\n CROSS JOIN ${settingsRelation} AS ${q(\"settings\")}\n WHERE NOT ${q(\"walks\")}.${q(\"closed\")}\n AND NOT list_contains(${q(\"walks\")}.${q(\"__event_ids\")},\n ${q(\"edges\")}.${q(\"__event_id\")})\n AND (\n ${edgeToKey} = ${q(\"walks\")}.${q(\"__start_key\")}\n OR NOT list_contains(${q(\"walks\")}.${q(\"__visited\")}, ${edgeToKey})\n )\n AND ${temporal.transition(\"walks\", \"edges\", direction, gap)}\n ), ${completeRelation} AS (\n SELECT DISTINCT ${q(\"start\")}, ${q(\"__start_key\")},\n ${q(\"__edge_keys\")}, ${q(\"steps\")}\n FROM ${walksRelation}\n WHERE ${q(\"closed\")}\n ), ${rankedRelation} AS (\n SELECT ${q(\"start\")}, ${q(\"__start_key\")},\n CAST(row_number() OVER (\n PARTITION BY ${q(\"__start_key\")}\n ORDER BY ${q(\"__edge_keys\")}) - 1\n AS BIGINT) AS ${q(\"pathId\")}, ${q(\"steps\")}\n FROM ${completeRelation}\n )\n ${graphRouteResultSelect(rankedRelation, input, edgeIdColumn, true, elapsedTime)}`;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addRowNumber(\n simpleTable: SimpleTable,\n newColumn: string,\n options: { by?: string | string[] } = {},\n) {\n // The row number is based on rowid, which only exists on the materialized\n // table, not on the output of a fused step: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"addRowNumber()\",\n parameters: { newColumn, options },\n execute: async () => {\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}` : \"\";\n\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT *, (ROW_NUMBER() OVER(${partition} ORDER BY rowid) - 1) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${quoteIdentifier(simpleTable.name)} ORDER BY rowid`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"addRowNumber()\",\n parameters: { newColumn, options },\n }),\n );\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport parseType from \"../helpers/parseTypes.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function addColumn(\n simpleTable: SimpleTable,\n newColumn: string,\n type:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`,\n definition: string,\n) {\n const newType = parseType(type);\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"addColumn()\",\n parameters: { newColumn, type, definition },\n // The schema is needed to reject a duplicate column, as v1's ALTER TABLE\n // ADD did.\n needsSchema: true,\n // A geometry column needs the spatial extension, both to cast to the\n // GEOMETRY type and for the spatial functions in the definition.\n needsSpatial: newType.toLowerCase().includes(\"geometry\"),\n rawSQL: [definition],\n outputSchema: (types) => ({ ...types, [newColumn]: newType }),\n buildSelect: (input, types) => {\n assertNewColumns(types, [newColumn], \"addColumn()\");\n return `SELECT *, CAST((${definition}) AS ${newType}) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${input}`;\n },\n });\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\n\ntype DatePart =\n | \"year\"\n | \"quarter\"\n | \"month\"\n | \"week\"\n | \"day\"\n | \"dayOfWeek\"\n | \"dayOfYear\"\n | \"hour\"\n | \"minute\"\n | \"second\";\n\nconst sqlParts: { [part in DatePart]: string } = {\n year: \"year\",\n quarter: \"quarter\",\n month: \"month\",\n week: \"week\",\n day: \"day\",\n dayOfWeek: \"dayofweek\",\n dayOfYear: \"dayofyear\",\n hour: \"hour\",\n minute: \"minute\",\n second: \"second\",\n};\n\nexport default function extractDatePart(\n simpleTable: SimpleTable,\n column: string,\n parts: DatePart | { [newColumn: string]: DatePart },\n) {\n const capturedParts = typeof parts === \"string\" ? parts : structuredClone(parts);\n const entries: [string, DatePart][] =\n typeof capturedParts === \"string\"\n ? [[capturedParts, capturedParts]]\n : Object.entries(capturedParts);\n\n if (entries.length === 0) {\n throw new Error(\"extractDatePart() requires at least one date part.\");\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"extractDatePart()\",\n parameters: { column, parts: capturedParts },\n needsSchema: true,\n buildSelect: (input, schema) => {\n assertNewColumns(\n schema,\n entries.map(([newColumn]) => newColumn),\n \"extractDatePart()\",\n );\n const source = quoteIdentifier(column);\n const extractions = entries.map(\n ([newColumn, part]) =>\n `date_part('${sqlParts[part]}', ${source}) AS ${quoteIdentifier(newColumn)}`,\n );\n return `SELECT *, ${extractions.join(\", \")} FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function removeColumns(simpleTable: SimpleTable, columns: string | string[]) {\n const cols = stringToArray(columns);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"removeColumns()\",\n parameters: { columns },\n needsSchema: false,\n buildSelect: (input) =>\n `SELECT * EXCLUDE (${cols.map((d) => `${quoteIdentifier(d)}`).join(\", \")}) FROM ${input}`,\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport parseType from \"../helpers/parseTypes.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\n\nexport default function convert(\n simpleTable: SimpleTable,\n types: {\n [key: string]:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`;\n },\n options: {\n strict?: boolean;\n datetimeFormat?: string;\n } = {},\n) {\n types = structuredClone(types);\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"convert()\",\n parameters: { types, options },\n needsSchema: true,\n needsSpatial: Object.values(types).some((type) => type.toLowerCase().startsWith(\"geometry\")),\n outputSchema: (allTypes) => ({\n ...allTypes,\n ...Object.fromEntries(\n Object.entries(types).map(([column, type]) => [column, parseType(type)]),\n ),\n }),\n values: (allTypes) =>\n getDatetimeFormatValues(\n Object.keys(types),\n Object.values(types),\n Object.keys(allTypes),\n allTypes,\n options,\n ),\n buildSelect: (input, allTypes) => {\n const allColumns = Object.keys(allTypes);\n\n for (const col in types) {\n if (!allColumns.includes(col)) {\n throw new Error(`The column ${col} does not exist in the table.`);\n }\n }\n\n return convertSelect(\n input,\n Object.keys(types),\n Object.values(types),\n allColumns,\n allTypes,\n options,\n );\n },\n });\n}\n\nexport function convertSelect(\n input: string,\n columns: string[],\n columnsTypes: (\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`\n )[],\n allColumns: string[],\n allTypes: TableSchema,\n options: { datetimeFormat?: string; strict?: boolean },\n) {\n let query = `SELECT`;\n\n const cast = options.strict === false ? \"TRY_CAST\" : \"CAST\";\n\n for (const column of allColumns) {\n const indexOf = columns.indexOf(column);\n if (indexOf === -1) {\n query += ` ${quoteIdentifier(column)},`;\n } else {\n const expectedType = parseType(columnsTypes[indexOf]);\n const currentType = allTypes[column];\n const datetimeFormatExist = typeof options.datetimeFormat === \"string\";\n\n const stringToNumber =\n currentType === \"VARCHAR\" && [\"DOUBLE\", \"BIGINT\"].includes(expectedType);\n const stringToDate =\n currentType === \"VARCHAR\" &&\n (expectedType.includes(\"TIME\") || expectedType.includes(\"DATE\"));\n const dateToString =\n (currentType.includes(\"DATE\") || currentType.includes(\"TIME\")) &&\n expectedType === \"VARCHAR\";\n const timeToMs = currentType.includes(\"TIME\") && [\"DOUBLE\", \"BIGINT\"].includes(expectedType);\n const dateToMs = currentType.includes(\"DATE\") && [\"DOUBLE\", \"BIGINT\"].includes(expectedType);\n const msToTime = [\"DOUBLE\", \"BIGINT\"].includes(currentType) && expectedType === \"TIME\";\n const msToDate = [\"DOUBLE\", \"BIGINT\"].includes(currentType) && expectedType.includes(\"DATE\");\n const msToTimestamp =\n [\"DOUBLE\", \"BIGINT\"].includes(currentType) && expectedType.includes(\"TIMESTAMP\");\n\n if (datetimeFormatExist && stringToDate) {\n query += ` strptime(${quoteIdentifier(column)}, ?) AS ${quoteIdentifier(column)},`;\n } else if (datetimeFormatExist && dateToString) {\n query += ` strftime(${quoteIdentifier(column)}, ?) AS ${quoteIdentifier(column)},`;\n } else if (timeToMs) {\n query += ` date_part('epoch', ${quoteIdentifier(column)}) * 1000 AS ${quoteIdentifier(\n column,\n )},`;\n } else if (dateToMs) {\n query += ` epoch(${quoteIdentifier(column)}) * 1000 AS ${quoteIdentifier(column)},`;\n } else if (msToTime) {\n query += ` TIME '00:00:00' + to_milliseconds(${quoteIdentifier(\n column,\n )}) AS ${quoteIdentifier(column)},`;\n } else if (msToDate) {\n query += ` DATE '1970-01-01' + to_milliseconds(${quoteIdentifier(\n column,\n )}) AS ${quoteIdentifier(column)},`;\n } else if (msToTimestamp) {\n query += ` TIMESTAMP '1970-01-01 00:00:00' + to_milliseconds(${quoteIdentifier(\n column,\n )}) AS ${quoteIdentifier(column)},`;\n } else if (options.strict === false && expectedType.startsWith(\"GEOMETRY\")) {\n // DuckDB's geometry parser can throw even inside TRY_CAST.\n query += ` TRY(CAST(${quoteIdentifier(\n column,\n )} AS ${expectedType})) AS ${quoteIdentifier(column)},`;\n } else if (stringToNumber) {\n // Thousand separators would make the cast fail.\n query += ` ${cast}(REPLACE(${quoteIdentifier(column)}, ',', '') AS ${parseType(\n columnsTypes[indexOf],\n )}) AS ${quoteIdentifier(column)},`;\n } else {\n query += ` ${cast}(${quoteIdentifier(columns[indexOf])} AS ${parseType(\n columnsTypes[indexOf],\n )}) AS ${quoteIdentifier(columns[indexOf])},`;\n }\n }\n }\n\n query = query.slice(0, query.length - 1);\n query += ` FROM ${input}`;\n\n return query;\n}\n\nfunction getDatetimeFormatValues(\n columns: string[],\n columnsTypes: (\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`\n )[],\n allColumns: string[],\n allTypes: TableSchema,\n options: { datetimeFormat?: string },\n): string[] {\n const datetimeFormat = options.datetimeFormat;\n if (typeof datetimeFormat !== \"string\") {\n return [];\n }\n return allColumns.flatMap((column) => {\n const index = columns.indexOf(column);\n if (index === -1) {\n return [];\n }\n const currentType = allTypes[column];\n const expectedType = parseType(columnsTypes[index]);\n const stringToDate =\n currentType === \"VARCHAR\" && (expectedType.includes(\"TIME\") || expectedType.includes(\"DATE\"));\n const dateToString =\n (currentType.includes(\"DATE\") || currentType.includes(\"TIME\")) && expectedType === \"VARCHAR\";\n return stringToDate || dateToString ? [datetimeFormat] : [];\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function longer(\n simpleTable: SimpleTable,\n columns: string[],\n namesTo: string,\n valuesTo: string,\n) {\n columns = [...columns];\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"longer()\",\n parameters: { columns, namesTo, valuesTo },\n needsSchema: true,\n buildSelect: (input, schema) => {\n // The pivoted columns are consumed by UNPIVOT and don't appear in the\n // output, so namesTo/valuesTo may reuse one of those names.\n assertNewColumns(schema, [namesTo, valuesTo], \"longer()\", columns);\n\n return `SELECT * FROM (\n FROM ${input} UNPIVOT INCLUDE NULLS (\n ${quoteIdentifier(valuesTo)}\n for ${quoteIdentifier(namesTo)} in (${columns\n .map((d) => `${quoteIdentifier(d)}`)\n .join(\", \")})\n )\n )`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertColumnsExist from \"../helpers/assertColumnsExist.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function renameColumns(\n simpleTable: SimpleTable,\n names: { [key: string]: string },\n options: { strict?: boolean } = {},\n) {\n const oldNames = Object.keys(names);\n const newNames = Object.values(names);\n // DuckDB's SELECT * RENAME silently drops a rename whose source column is\n // absent, so a typo would pass unnoticed. Validating requires the schema;\n // strict: false skips both the check and its DESCRIBE round-trip.\n const strict = options.strict !== false;\n\n names = { ...names };\n options = { ...options };\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"renameColumns()\",\n parameters: { names, options },\n needsSchema: strict,\n buildSelect: (input, schema) => {\n if (strict) {\n assertColumnsExist(schema, oldNames, \"renameColumns()\");\n }\n return `SELECT * RENAME (${oldNames\n .map((d, i) => `${quoteIdentifier(d)} AS ${quoteIdentifier(newNames[i])}`)\n .join(\", \")}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport type { TableSchema } from \"../helpers/pendingOps.ts\";\n\nexport default function trim(\n simpleTable: SimpleTable,\n columns: string | string[],\n options: {\n character?: string;\n side?: \"left\" | \"right\" | \"both\";\n } = {},\n) {\n const cols = columns === \"all\" ? null : stringToArray(columns);\n const resolveColumns = (schema: TableSchema) =>\n cols ?? Object.keys(schema).filter((column) => schema[column] === \"VARCHAR\");\n const side = options.side ?? \"both\";\n const fn =\n side === \"left\" ? \"LTRIM\" : side === \"right\" ? \"RTRIM\" : side === \"both\" ? \"TRIM\" : null;\n if (fn === null) {\n throw new Error(\n `trim() options.side must be \"left\", \"right\", or \"both\". Received ${JSON.stringify(\n options.side,\n )}.`,\n );\n }\n const character = options.character;\n const specialCharacter = typeof character === \"string\" ? \", ?\" : \"\";\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"trim()\",\n parameters: { columns, options },\n values:\n typeof character === \"string\"\n ? (schema) => resolveColumns(schema).map(() => character)\n : undefined,\n needsSchema: columns === \"all\",\n buildSelect: (input, schema) => {\n const selectedColumns = resolveColumns(schema);\n if (columns === \"all\" && selectedColumns.length === 0) {\n return `SELECT * FROM ${input}`;\n }\n return `SELECT * REPLACE (${selectedColumns\n .map((c) => `${fn}(${quoteIdentifier(c)}${specialCharacter}) AS ${quoteIdentifier(c)}`)\n .join(\", \")}) FROM ${input}`;\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport resolveOutputTable from \"../helpers/resolveOutputTable.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function selectRows(\n simpleTable: SimpleTable,\n count: number | string,\n options: { offset?: number; outputTable?: string | boolean } = {},\n): SimpleTable {\n options = { ...options };\n options.outputTable = resolveOutputTable(simpleTable, options.outputTable);\n\n const limitAndOffset = `LIMIT ${count}${\n typeof options.offset === \"number\" ? ` OFFSET ${options.offset}` : \"\"\n }`;\n\n if (typeof options.outputTable === \"string\") {\n // The output table instance is created at call time so it can be\n // returned synchronously and chained on right away.\n const outputTable = simpleTable.sdb.newTable(options.outputTable);\n queueOp(outputTable, {\n kind: \"source\",\n method: \"selectRows()\",\n parameters: { count, options },\n // The output table reads simpleTable by name rather than through its\n // own (nonexistent) chain, so simpleTable's pending work must close\n // and execute before this SELECT runs, as it would at this call\n // position.\n rawSQL: [`${quoteIdentifier(simpleTable.name)}`],\n buildSelect: () => `SELECT * FROM ${quoteIdentifier(simpleTable.name)} ${limitAndOffset}`,\n });\n return outputTable;\n }\n\n queueOp(simpleTable, {\n kind: \"fusable\",\n method: \"selectRows()\",\n parameters: { count, options },\n needsSchema: false,\n preservesSchema: true,\n buildSelect: (input) => `SELECT * FROM ${input} ${limitAndOffset}`,\n });\n return simpleTable;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport assertNewColumns from \"../helpers/assertNewColumns.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function cloneColumnWithOffset(\n simpleTable: SimpleTable,\n column: string,\n newColumn: string,\n options: {\n offset?: number;\n by?: string | string[];\n } = {},\n) {\n // The offset is based on rowid, which only exists on the materialized\n // table, not on the output of a fused step: it executes as a barrier.\n options = structuredClone(options);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"cloneColumnWithOffset()\",\n parameters: { column, newColumn, options },\n execute: async () => {\n // A SELECT *, expr AS col colliding with an existing column would be\n // silently renamed by DuckDB (col -> col_1) instead of erroring.\n assertNewColumns(await simpleTable.getTypes(), [newColumn], \"cloneColumnWithOffset()\");\n\n const offset = options.offset ?? 1;\n const by = options.by ? stringToArray(options.by) : [];\n const partition =\n by.length > 0 ? `PARTITION BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}` : \"\";\n\n // When by are specified, also sort the final result by\n // by.\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT *, LEAD(${quoteIdentifier(\n column,\n )}, ${offset}) OVER(${partition} ORDER BY rowid) AS ${quoteIdentifier(\n newColumn,\n )} FROM ${quoteIdentifier(simpleTable.name)}${\n by.length > 0\n ? ` ORDER BY ${by.map((d) => `${quoteIdentifier(d)}`).join(\", \")}, rowid`\n : ` ORDER BY rowid`\n };`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"cloneColumnWithOffset()\",\n parameters: { column, newColumn },\n }),\n );\n },\n });\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport stringToArray from \"../helpers/stringToArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function clone(\n simpleTable: SimpleTable,\n nameOrOptions:\n | string\n | {\n name?: string;\n conditions?: string;\n columns?: string | string[];\n limit?: number;\n offset?: number;\n } = {},\n): SimpleTable {\n const columns =\n typeof nameOrOptions === \"object\" && nameOrOptions.columns\n ? stringToArray(nameOrOptions.columns)\n : [];\n\n // The cloned table instance is created at call time so it can be returned\n // synchronously and chained on right away. Delegating to sdb.newTable()\n // makes subclasses using tableClass work correctly.\n let clonedTable: SimpleTable;\n const options =\n typeof nameOrOptions === \"string\" ? { name: nameOrOptions } : { ...nameOrOptions };\n if (typeof options.name === \"string\") {\n clonedTable = simpleTable.sdb.newTable(options.name);\n } else {\n clonedTable = simpleTable.sdb.newTable(undefined);\n }\n\n const selectClause =\n columns.length > 0 ? columns.map((col) => `${quoteIdentifier(col)}`).join(\", \") : \"*\";\n\n queueOp(clonedTable, {\n kind: \"source\",\n method: \"clone()\",\n parameters: { options },\n // The clone reads simpleTable by name rather than through clonedTable's\n // own (nonexistent) chain, so simpleTable's pending work must close and\n // execute before this SELECT runs, as it would at this call position.\n rawSQL: [`${quoteIdentifier(simpleTable.name)}`],\n buildSelect: () =>\n `SELECT ${selectClause} FROM ${quoteIdentifier(simpleTable.name)}${\n options.conditions ? ` WHERE ${options.conditions}` : \"\"\n }${typeof options.limit === \"number\" ? ` LIMIT ${options.limit}` : \"\"}${\n typeof options.offset === \"number\" ? ` OFFSET ${options.offset}` : \"\"\n }`,\n });\n\n return clonedTable;\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Drops columns immediately, without queueing. For use inside a barrier's\n * execute, which runs during a flush: a sync builder method called there\n * would queue an operation for the next flush instead of running now.\n */\nexport default async function removeColumnsNow(\n simpleTable: SimpleTable,\n columns: string[],\n method: string,\n): Promise<void> {\n await queryDB(\n simpleTable,\n columns\n .map((d) => `ALTER TABLE ${quoteIdentifier(simpleTable.name)} DROP ${quoteIdentifier(d)};`)\n .join(\"\\n\"),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method,\n parameters: { columns },\n }),\n );\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\n/**\n * Adds the columns missing from each table (filled with NULL) so all tables\n * share the same columns. Runs immediately, without queueing, so it's safe\n * inside a barrier's execute, which runs during a flush.\n */\nexport default async function unifyColumns(\n allTables: SimpleTable[],\n allTypes: { [key: string]: string },\n) {\n const columnsAdded: {\n [key: string]: string[];\n } = {};\n\n // Each table's columns are fetched once, instead of one hasColumn\n // round-trip per column and table.\n const existingColumns = new Map<SimpleTable, Set<string>>();\n for (const table of allTables) {\n existingColumns.set(table, new Set(await table.getColumns()));\n }\n\n for (const column in allTypes) {\n for (const table of allTables) {\n if (!existingColumns.get(table)!.has(column)) {\n await queryDB(\n table,\n `ALTER TABLE ${quoteIdentifier(table.name)} ADD ${quoteIdentifier(\n column,\n )} ${allTypes[column]};`,\n mergeOptions(table, {\n table: table.name,\n method: \"insertTables()\",\n parameters: { column, type: allTypes[column] },\n }),\n );\n if (!columnsAdded[table.name]) {\n columnsAdded[table.name] = [];\n }\n columnsAdded[table.name].push(column);\n }\n }\n }\n\n return columnsAdded;\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport ensureSpatial from \"../helpers/ensureSpatial.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport removeColumnsNow from \"../helpers/removeColumnsNow.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport unifyColumns from \"../helpers/unifyColumns.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\n\nexport default function insertTables(\n simpleTable: SimpleTable,\n tables: SimpleTable | SimpleTable[],\n options: { unifyColumns?: boolean } = {},\n) {\n const array = Array.isArray(tables) ? [...tables] : [tables];\n assertSameDatabase(simpleTable.sdb, array, \"insertTables()\");\n options = structuredClone(options);\n\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"insertTables()\",\n parameters: {\n tables: array.map((t) => t.name),\n options,\n },\n execute: () => executeInsertTables(simpleTable, array, options),\n });\n}\n\nasync function executeInsertTables(\n simpleTable: SimpleTable,\n array: SimpleTable[],\n options: { unifyColumns?: boolean },\n): Promise<void> {\n if (!(await simpleTable.sdb.hasTable(simpleTable.name))) {\n // The table is created directly (not with the sync setTypes builder,\n // which would queue for the next flush).\n const firstTableTypes = await array[0].getTypes();\n if (\n Object.values(firstTableTypes)\n .map((d) => d.toLowerCase())\n .some((d) => d.startsWith(\"geometry\"))\n ) {\n await ensureSpatial(simpleTable);\n }\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(simpleTable.name)} (${Object.keys(firstTableTypes)\n .map((d) => `${quoteIdentifier(d)} ${firstTableTypes[d]}`)\n .join(\", \")});`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"insertTables()\",\n parameters: { types: firstTableTypes },\n }),\n );\n }\n\n // Checking columns, types\n if (!options.unifyColumns) {\n const thisColumns = (await simpleTable.getColumns()).sort();\n const thisColumnSet = new Set(thisColumns);\n for (const table of array) {\n const tableColumns = (await table.getColumns()).sort();\n const tableColumnSet = new Set(tableColumns);\n const missingFromTable = thisColumns.filter((column) => !tableColumnSet.has(column));\n const missingFromSimpleTable = tableColumns.filter((column) => !thisColumnSet.has(column));\n if (missingFromTable.length > 0 || missingFromSimpleTable.length > 0) {\n const differences: string[] = [];\n if (missingFromTable.length > 0) {\n differences.push(\n `${missingFromTable.length} column${\n missingFromTable.length === 1 ? \"\" : \"s\"\n } missing from ${quoteIdentifier(table.name)}: ${missingFromTable\n .map(quoteIdentifier)\n .join(\", \")}.`,\n );\n }\n if (missingFromSimpleTable.length > 0) {\n differences.push(\n `${missingFromSimpleTable.length} column${\n missingFromSimpleTable.length === 1 ? \"\" : \"s\"\n } missing from ${quoteIdentifier(simpleTable.name)}: ${missingFromSimpleTable\n .map(quoteIdentifier)\n .join(\", \")}.`,\n );\n }\n throw new Error(\n `Tables ${quoteIdentifier(simpleTable.name)} and ${quoteIdentifier(\n table.name,\n )} do not have the same columns.\\n${differences.join(\n \"\\n\",\n )}\\nPass { unifyColumns: true } to fill missing columns with NULL values.`,\n );\n }\n }\n }\n const allTables = [simpleTable, ...array];\n const allTypes: { [key: string]: string } = {};\n const typeSourceTables: { [key: string]: SimpleTable } = {};\n for (const table of allTables) {\n const types = await table.getTypes();\n for (const key in types) {\n if (!allTypes[key]) {\n allTypes[key] = types[key];\n typeSourceTables[key] = table;\n } else {\n if (allTypes[key] !== types[key]) {\n const sourceTable = typeSourceTables[key];\n throw new Error(\n `Column ${quoteIdentifier(key)} has different types:\\n${quoteIdentifier(\n sourceTable.name,\n )}: ${allTypes[key]}\\n${quoteIdentifier(table.name)}: ${\n types[key]\n }\\nConvert ${quoteIdentifier(key)} to the same type in both tables before inserting.`,\n );\n }\n }\n }\n }\n\n let columnsAdded: {\n [key: string]: string[];\n } = {};\n if (options.unifyColumns) {\n columnsAdded = await unifyColumns(allTables, allTypes);\n }\n\n await queryDB(\n simpleTable,\n array\n .map(\n (tableToInsert) =>\n `INSERT INTO ${quoteIdentifier(\n simpleTable.name,\n )} BY NAME SELECT * FROM ${quoteIdentifier(tableToInsert.name)};`,\n )\n .join(\"\\n\"),\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"insertTables()\",\n parameters: { tables: array.map((t) => t.name) },\n }),\n );\n\n if (options.unifyColumns) {\n for (const table of array) {\n const cols = columnsAdded[table.name];\n if (cols) {\n await removeColumnsNow(table, cols, \"insertTables()\");\n }\n }\n }\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport { executePreparedArray, prepareArray } from \"./loadArray.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport toDuckDBValue from \"../helpers/toDuckDBValue.ts\";\n\nexport default function insertRows(simpleTable: SimpleTable, rows: { [key: string]: unknown }[]) {\n const prepared = prepareArray(rows);\n const statement = insertRowsStatement(simpleTable.name, rows);\n // Whether the rows are inserted or loaded depends on the table existing,\n // so insertRows can't be expressed as a single SELECT over its input: it\n // executes as a barrier.\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"insertRows()\",\n parameters: { rows: `${rows.length} rows` },\n execute: async () => {\n if (await simpleTable.sdb.hasTable(simpleTable.name)) {\n await queryDB(\n simpleTable,\n statement.query,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"insertRows()\",\n parameters: { rows: `${rows.length} rows` },\n values: statement.values,\n }),\n );\n } else {\n await executePreparedArray(simpleTable, prepared);\n }\n },\n });\n}\n\nfunction insertRowsStatement(\n table: string,\n rows: { [key: string]: unknown }[],\n): { query: string; values: import(\"@duckdb/node-api\").DuckDBValue[] } {\n const columns = Object.keys(rows[0]);\n const values = rows.flatMap((row) => columns.map((column) => toDuckDBValue(row[column])));\n\n let query = `INSERT INTO ${quoteIdentifier(table)} (${columns.map(quoteIdentifier).join(\", \")})\n VALUES`;\n\n for (const _row of rows) {\n query += `\\n(${columns.map(() => \"?\").join(\", \")}),`;\n }\n\n return { query: query.slice(0, query.length - 1), values };\n}\n","import crypto from \"node:crypto\";\nimport { createWriteStream, mkdirSync } from \"node:fs\";\nimport { rm, stat } from \"node:fs/promises\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport prettyDuration from \"./prettyDuration.ts\";\n\nexport type OsmFileSuffix = \".osm\" | \".osm.pbf\";\n\ntype RetryFailure = {\n reason: string;\n retryable: boolean;\n explanation: string;\n retryAfterSeconds?: number;\n};\n\nexport function getOsmFileSuffix(file: string): OsmFileSuffix | null {\n const comparable = isRemoteOsmUrl(file) ? new URL(file).pathname : file;\n const lower = comparable.toLowerCase();\n if (lower.endsWith(\".osm.pbf\")) return \".osm.pbf\";\n if (lower.endsWith(\".osm\")) return \".osm\";\n return null;\n}\n\nexport function isRemoteOsmUrl(file: string): boolean {\n try {\n const protocol = new URL(file).protocol;\n return protocol === \"http:\" || protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nexport function normalizeRemoteOsmUrl(file: string): string {\n let url: URL;\n try {\n url = new URL(file);\n } catch {\n throw new Error(\"loadOpenStreetMap() remote sources must be valid HTTP or HTTPS URLs.\");\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"loadOpenStreetMap() remote sources must use an HTTP or HTTPS URL.\");\n }\n return url.href;\n}\n\nexport function sanitizeOsmUrl(source: string): string {\n let url: URL;\n try {\n url = new URL(source);\n } catch {\n return source;\n }\n url.username = \"\";\n url.password = \"\";\n // Snapshot keys because set() removes duplicate query parameters.\n const keys = [...url.searchParams.keys()];\n for (const key of keys) {\n if (/(?:api[-_]?key|auth|credential|password|secret|signature|token)/i.test(key)) {\n url.searchParams.set(key, \"[REDACTED]\");\n }\n }\n return url.href;\n}\n\nexport async function downloadOsmToTemporaryFile(\n url: string,\n options: {\n suffix: OsmFileSuffix;\n prefix?: string;\n request?: RequestInit;\n retries?: number;\n retryDelay?: number;\n timeout?: number;\n overpass?: boolean;\n verbose?: boolean;\n wait?: (milliseconds: number) => Promise<void>;\n },\n): Promise<string> {\n const temporaryDirectory = \".sda-cache/tmp\";\n mkdirSync(temporaryDirectory, { recursive: true });\n const prefix = options.prefix === undefined ? \"remote\" : options.prefix;\n const retries = options.retries ?? 3;\n const retryDelay = options.retryDelay ?? 5;\n const totalAttempts = retries + 1;\n const sanitizedSource = sanitizeOsmUrl(url);\n const wait = options.wait ?? waitFor;\n let totalDelay = 0;\n let lastFailure: RetryFailure | undefined;\n\n for (let attempt = 1; attempt <= totalAttempts; attempt++) {\n const temporaryFile = `${temporaryDirectory}/${prefix}.${crypto.randomUUID()}${options.suffix}`;\n const start = Date.now();\n if (options.verbose) {\n console.log(\n `${\n options.overpass ? \"Querying Overpass\" : \"Downloading OSM data\"\n } (attempt ${attempt} of ${totalAttempts})...`,\n );\n }\n\n try {\n const response = await fetchWithTimeout(url, options.request, options.timeout);\n if (!response.ok) {\n const failure = classifyHttpFailure(response, options.overpass ?? false);\n if (!failure.retryable) {\n const responseText = (await response.text()).slice(0, 500).trim();\n if (responseText.length > 0) {\n failure.reason += ` Response: ${responseText}`;\n }\n } else {\n await response.body?.cancel();\n }\n throw failure;\n }\n if (response.body === null) {\n throw {\n reason: \"The response body was empty.\",\n retryable: true,\n explanation: \"an empty response can be caused by an interrupted transfer\",\n } satisfies RetryFailure;\n }\n\n await pipeline(\n Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]),\n createWriteStream(temporaryFile, { flags: \"wx\" }),\n );\n if (options.verbose) {\n const size = (await stat(temporaryFile)).size;\n console.log(\n `${options.overpass ? \"Received\" : \"Downloaded\"} ${formatBytes(\n size,\n )} in ${prettyDuration(start)}.`,\n );\n }\n return temporaryFile;\n } catch (error) {\n await rm(temporaryFile, { force: true }).catch(() => undefined);\n lastFailure = isRetryFailure(error) ? error : classifyFetchFailure(error, options.timeout);\n const canRetry = lastFailure.retryable && attempt < totalAttempts;\n logAttemptFailure(sanitizedSource, attempt, totalAttempts, lastFailure, canRetry);\n if (!canRetry) {\n throw new Error(finalRequestError(attempt, retries, totalDelay, lastFailure), {\n cause: error,\n });\n }\n\n const calculatedDelay = retryDelay * 2 ** (attempt - 1);\n const delay = Math.max(calculatedDelay, lastFailure.retryAfterSeconds ?? 0);\n logRetryDelay(\n delay,\n calculatedDelay,\n lastFailure.retryAfterSeconds,\n attempt,\n retries,\n retryDelay,\n );\n totalDelay += delay;\n await wait(delay * 1000);\n }\n }\n\n throw new Error(\n finalRequestError(\n totalAttempts,\n retries,\n totalDelay,\n lastFailure ?? {\n reason: \"Unknown request failure.\",\n retryable: false,\n explanation: \"the failure could not be classified\",\n },\n ),\n );\n}\n\nasync function fetchWithTimeout(\n url: string,\n request: RequestInit | undefined,\n timeout: number | undefined,\n): Promise<Response> {\n const timeoutSignal = timeout === undefined ? undefined : AbortSignal.timeout(timeout * 1000);\n const requestSignal = request?.signal ?? undefined;\n const signal =\n timeoutSignal === undefined\n ? requestSignal\n : requestSignal === undefined\n ? timeoutSignal\n : AbortSignal.any([timeoutSignal, requestSignal]);\n return await fetch(url, { ...request, signal });\n}\n\nfunction classifyHttpFailure(response: Response, overpass: boolean): RetryFailure {\n const status = `HTTP ${response.status}${\n response.statusText.length > 0 ? ` ${response.statusText}` : \"\"\n }`;\n const retryAfterSeconds = parseRetryAfter(response.headers.get(\"retry-after\"));\n if (response.status === 408) {\n return {\n reason: status,\n retryable: true,\n explanation: \"HTTP 408 indicates a transient request timeout\",\n retryAfterSeconds,\n };\n }\n if (response.status === 429) {\n return {\n reason: status,\n retryable: true,\n explanation: \"HTTP 429 indicates temporary rate limiting\",\n retryAfterSeconds,\n };\n }\n if (response.status >= 500 && response.status <= 599) {\n return {\n reason: status,\n retryable: true,\n explanation: \"it is a server error\",\n retryAfterSeconds,\n };\n }\n if (overpass && response.status === 406) {\n return {\n reason: status,\n retryable: true,\n explanation: \"Overpass public instances use HTTP 406 for temporary resource limits\",\n retryAfterSeconds,\n };\n }\n return {\n reason: status,\n retryable: false,\n explanation: `HTTP ${response.status} is not considered a transient failure`,\n };\n}\n\nfunction classifyFetchFailure(error: unknown, timeout: number | undefined): RetryFailure {\n const message = error instanceof Error ? error.message : String(error);\n const timedOut =\n error instanceof DOMException &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\") &&\n timeout !== undefined;\n return {\n reason: timedOut ? `The request timed out after ${timeout} seconds.` : message,\n retryable: true,\n explanation: timedOut\n ? \"a configured request timeout is retryable\"\n : \"fetch and transfer errors are treated as transient network failures\",\n };\n}\n\nfunction isRetryFailure(error: unknown): error is RetryFailure {\n if (typeof error !== \"object\" || error === null) return false;\n const candidate = error as { [key: string]: unknown };\n return (\n typeof candidate.reason === \"string\" &&\n typeof candidate.retryable === \"boolean\" &&\n typeof candidate.explanation === \"string\"\n );\n}\n\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (value === null) return undefined;\n const trimmed = value.trim();\n if (/^\\d+$/.test(trimmed)) return Number(trimmed);\n const date = Date.parse(trimmed);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, Math.ceil((date - Date.now()) / 1000));\n}\n\nfunction logAttemptFailure(\n source: string,\n attempt: number,\n totalAttempts: number,\n failure: RetryFailure,\n canRetry: boolean,\n): void {\n console.log(\n `loadOpenStreetMap(): request attempt ${attempt} of ${totalAttempts} failed.\\n` +\n `Source: ${source}\\n` +\n `Reason: ${failure.reason}\\n` +\n `${\n canRetry\n ? `This failure is retryable because ${failure.explanation}.`\n : `Not retrying because ${\n failure.retryable\n ? totalAttempts === 1\n ? \"no retries were configured\"\n : \"the configured retries have been exhausted\"\n : failure.explanation\n }.`\n }`,\n );\n}\n\nfunction logRetryDelay(\n delay: number,\n calculatedDelay: number,\n retryAfter: number | undefined,\n attempt: number,\n retries: number,\n retryDelay: number,\n): void {\n if (retryAfter !== undefined && retryAfter > calculatedDelay) {\n console.log(\n `Retrying in ${formatSeconds(\n delay,\n )} because the server returned Retry-After: ${retryAfter}.\\n` +\n `The calculated retry delay was ${formatSeconds(\n calculatedDelay,\n )}; the longer server-requested delay is being used.`,\n );\n return;\n }\n console.log(\n `Retrying in ${formatSeconds(\n delay,\n )} (retry ${attempt} of ${retries}; configured base delay: ${formatSeconds(retryDelay)}).`,\n );\n}\n\nfunction finalRequestError(\n attempts: number,\n retries: number,\n totalDelay: number,\n failure: RetryFailure,\n): string {\n const exhausted = failure.retryable && attempts === retries + 1;\n return (\n `loadOpenStreetMap(): request failed after ${attempts} ${\n attempts === 1 ? \"attempt\" : \"attempts\"\n }.\\n${\n exhausted\n ? retries === 0\n ? \"No retries were configured.\"\n : `All ${retries} configured ${retries === 1 ? \"retry was\" : \"retries were\"} exhausted.`\n : \"No further retry was attempted because the failure is nonretryable.\"\n }\\nTotal retry delay: ${formatSeconds(totalDelay)}.\\n` +\n `Last failure: ${failure.reason}\\n` +\n `No further retry occurred because ${\n exhausted\n ? retries === 0\n ? \"no retries were configured\"\n : \"the configured retries were exhausted\"\n : failure.explanation\n }.\\n` +\n \"No invalid cached data was returned.\"\n );\n}\n\nfunction formatSeconds(seconds: number): string {\n return `${seconds} ${seconds === 1 ? \"second\" : \"seconds\"}`;\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} ${bytes === 1 ? \"byte\" : \"bytes\"}`;\n const units = [\"KB\", \"MB\", \"GB\", \"TB\"];\n let value = bytes;\n let unit = units[0];\n for (const candidate of units) {\n value /= 1024;\n unit = candidate;\n if (value < 1024) break;\n }\n return `${value.toFixed(1)} ${unit}`;\n}\n\nfunction waitFor(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport getExtension from \"../helpers/getExtension.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport removeColumnsNow from \"../helpers/removeColumnsNow.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { recordCacheTableReferences } from \"../helpers/cacheTableDependencies.ts\";\nimport { getOsmFileSuffix } from \"../helpers/osmFiles.ts\";\n\ntype LoadGeoDataOptions = {\n toEPSG4326?: boolean;\n columns?: string[];\n conditions?: string;\n};\n\nexport default function loadGeoData(\n simpleTable: SimpleTable,\n file: string,\n options: LoadGeoDataOptions = {},\n) {\n if (getOsmFileSuffix(file) !== null) {\n throw new Error(\n \"loadGeoData() does not support .osm or .osm.pbf files. Use loadOpenStreetMap() instead.\",\n );\n }\n options = structuredClone(options);\n if (options.conditions !== undefined) {\n recordCacheTableReferences(simpleTable, [options.conditions]);\n }\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"loadGeoData()\",\n parameters: { file, options },\n execute: () => executeLoadGeoData(simpleTable, file, options),\n });\n}\n\nasync function executeLoadGeoData(\n simpleTable: SimpleTable,\n file: string,\n options: LoadGeoDataOptions,\n): Promise<void> {\n const fileExtension = getExtension(file);\n const selectColumns =\n options.columns !== undefined && options.columns.length > 0\n ? options.columns.map(quoteIdentifier).join(\", \")\n : \"*\";\n const spatialSetup = simpleTable.sdb.spatialLoaded\n ? \"\"\n : \"INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\";\n const conditions = options.conditions ? ` WHERE ${options.conditions}` : \"\";\n\n if (fileExtension === \"geoparquet\" || fileExtension === \"parquet\") {\n await queryDB(\n simpleTable,\n `${spatialSetup}${file.toLowerCase().includes(\"http\") ? \" INSTALL https; LOAD https;\" : \"\"}\n CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT ${selectColumns} FROM read_parquet(${parseValue(file)})${conditions};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"loadGeoData()\",\n parameters: { file, options },\n }),\n );\n } else {\n await queryDB(\n simpleTable,\n `${spatialSetup}${file.toLowerCase().includes(\"http\") ? \" INSTALL https; LOAD https;\" : \"\"}\n CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT ${selectColumns} FROM ST_Read(${parseValue(file)})${conditions};`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"loadGeoData()\",\n parameters: { file, options },\n }),\n );\n }\n simpleTable.sdb.spatialLoaded = true;\n\n const mayIncludeOgcFid =\n options.columns === undefined ||\n options.columns.length === 0 ||\n options.columns.includes(\"OGC_FID\");\n if (mayIncludeOgcFid && (await simpleTable.hasColumn(\"OGC_FID\"))) {\n await removeColumnsNow(simpleTable, [\"OGC_FID\"], \"loadGeoData()\");\n }\n\n if (options.toEPSG4326) {\n const geoType = await simpleTable.getProjection(\"geom\");\n if (geoType !== \"GEOMETRY('EPSG:4326')\") {\n // The reprojection runs directly (not with the sync reproject builder,\n // which would queue for the next flush).\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(\n simpleTable.name,\n )} AS SELECT * REPLACE (ST_Transform(\"geom\", 'EPSG:4326')::GEOMETRY('EPSG:4326') AS \"geom\") FROM ${quoteIdentifier(\n simpleTable.name,\n )}`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"loadGeoData()\",\n parameters: { file, options },\n }),\n );\n }\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport parseValue from \"./parseValue.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nexport default async function loadOsmFile(\n table: SimpleTable,\n file: string,\n context: {\n method: \"loadOpenStreetMap()\";\n parameters: { [key: string]: unknown };\n },\n): Promise<void> {\n await queryDB(\n table,\n `INSTALL spatial;\n LOAD spatial;\n INSTALL osmium FROM community;\n LOAD osmium;\n SET geometry_always_xy = true;\n CREATE OR REPLACE TABLE ${quoteIdentifier(table.name)} AS\n SELECT * EXCLUDE (geometry),\n geometry::GEOMETRY('EPSG:4326') AS geom\n FROM osmium_read(${parseValue(file)});`,\n mergeOptions(table, {\n table: table.name,\n method: context.method,\n parameters: context.parameters,\n }),\n );\n table.sdb.spatialLoaded = true;\n}\n","import crypto from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { cacheEntryExpired, cacheLoadMessage, cacheTtlMessage } from \"./cacheDiagnostics.ts\";\nimport prettyDuration from \"./prettyDuration.ts\";\n\ntype FileCacheSource = {\n file: string | null;\n creation: number;\n duration?: number;\n formatVersion?: string;\n};\n\ntype FileCacheSources = { [id: string]: FileCacheSource };\n\nexport function createFileCacheId(prefix: string, identity: unknown): string {\n const hash = crypto.createHash(\"sha256\").update(JSON.stringify(identity)).digest(\"hex\");\n return `${prefix}.${hash}`;\n}\n\nexport default async function fileCache(\n table: SimpleTable,\n options: {\n directory: string;\n enabled: boolean;\n extension: string;\n formatVersion: string;\n id: string;\n method: string;\n ttl?: number;\n load: (file: string) => Promise<void>;\n compute: () => Promise<void>;\n write: (file: string) => Promise<void>;\n },\n): Promise<void> {\n if (!options.enabled) {\n logFileCacheDisabled(table, options.method);\n } else if (await loadFileCache(table, options)) {\n return;\n }\n\n const start = Date.now();\n await options.compute();\n if (options.enabled) {\n await writeFileCache(table, {\n ...options,\n duration: Date.now() - start,\n });\n }\n}\n\nasync function loadFileCache(\n table: SimpleTable,\n options: {\n directory: string;\n formatVersion: string;\n id: string;\n method: string;\n ttl?: number;\n load: (file: string) => Promise<void>;\n },\n): Promise<boolean> {\n const sourcesFile = `${options.directory}/sources.json`;\n const sources = readFileCacheSources(sourcesFile);\n const source = sources[options.id];\n const now = Date.now();\n\n if (table.sdb.cacheVerbose) {\n console.log(`\\n${options.method} cache for ${table.name}`);\n }\n if (source === undefined) {\n logCacheMiss(table, \"No matching cache entry exists.\");\n return false;\n }\n if (source.formatVersion !== options.formatVersion) {\n logCacheMiss(table, \"The cache format changed.\");\n return false;\n }\n if (source.file === null || !existsSync(source.file)) {\n logCacheMiss(table, \"The cached file is missing.\");\n return false;\n }\n if (options.ttl !== undefined && cacheEntryExpired(source.creation, options.ttl, now)) {\n if (table.sdb.cacheVerbose) {\n console.log(\n `Cache entry is stale.\\n${cacheTtlMessage(\n source.creation,\n options.ttl,\n now,\n true,\n )}\\nFetching fresh data and refreshing the cache entry.`,\n );\n }\n return false;\n }\n\n if (table.sdb.cacheVerbose) {\n console.log(\"Cache hit.\");\n if (options.ttl !== undefined) {\n console.log(cacheTtlMessage(source.creation, options.ttl, now, false));\n }\n }\n\n const start = Date.now();\n try {\n await options.load(source.file);\n } catch {\n rmSync(source.file, { force: true });\n delete sources[options.id];\n writeFileCacheSources(options.directory, sourcesFile, sources);\n if (table.sdb.cacheVerbose) {\n console.log(\"Could not load cached data. Fetching fresh data...\");\n }\n return false;\n }\n const end = Date.now();\n if (table.sdb.cacheVerbose) {\n console.log(`${cacheLoadMessage(start, end, source.duration)}\\n`);\n if (source.duration !== undefined) {\n table.sdb.cacheTimeSaved += source.duration - (end - start);\n }\n }\n return true;\n}\n\nasync function writeFileCache(\n table: SimpleTable,\n options: {\n directory: string;\n extension: string;\n formatVersion: string;\n id: string;\n duration: number;\n write: (file: string) => Promise<void>;\n },\n): Promise<void> {\n mkdirSync(options.directory, { recursive: true });\n const file = `${options.directory}/${options.id}.${options.extension}`;\n const temporaryFile = `${file}.${crypto.randomUUID()}.tmp.${options.extension}`;\n\n if (table.sdb.cacheVerbose) {\n console.log(`Computations done in ${prettyDuration(0, { end: options.duration })}.`);\n }\n const start = Date.now();\n try {\n await options.write(temporaryFile);\n rmSync(file, { force: true });\n renameSync(temporaryFile, file);\n } catch (error) {\n rmSync(temporaryFile, { force: true });\n throw error;\n }\n const end = Date.now();\n\n const sourcesFile = `${options.directory}/sources.json`;\n const sources = readFileCacheSources(sourcesFile);\n sources[options.id] = {\n file,\n creation: Date.now(),\n duration: options.duration,\n formatVersion: options.formatVersion,\n };\n writeFileCacheSources(options.directory, sourcesFile, sources);\n\n if (table.sdb.cacheVerbose) {\n console.log(`Wrote in cache in ${prettyDuration(start, { end })}.\\n`);\n table.sdb.cacheTimeWriting += end - start;\n }\n}\n\nfunction logFileCacheDisabled(table: SimpleTable, method: string): void {\n if (table.sdb.cacheVerbose) {\n console.log(\n `\\n${method} cache for ${table.name}\\nCache disabled.\\nFetching fresh data without storing a cache entry.`,\n );\n }\n}\n\nfunction logCacheMiss(table: SimpleTable, reason: string): void {\n if (table.sdb.cacheVerbose) {\n console.log(`Cache miss.\\n${reason}\\nFetching fresh data and storing a new cache entry.`);\n }\n}\n\nfunction readFileCacheSources(sourcesFile: string): FileCacheSources {\n if (!existsSync(sourcesFile)) {\n return {};\n }\n return JSON.parse(readFileSync(sourcesFile, \"utf-8\")) as FileCacheSources;\n}\n\nfunction writeFileCacheSources(\n directory: string,\n sourcesFile: string,\n sources: FileCacheSources,\n): void {\n mkdirSync(directory, { recursive: true });\n writeFileSync(sourcesFile, JSON.stringify(sources));\n}\n","import crypto from \"node:crypto\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport { cacheEntryExpired } from \"./cacheDiagnostics.ts\";\nimport { createFileCacheId } from \"./fileCache.ts\";\nimport { formatBytes } from \"./osmFiles.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport parseValue from \"./parseValue.ts\";\nimport prettyDuration from \"./prettyDuration.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nconst CACHE_DIRECTORY = \".sda-cache/osm\";\nconst OSM_CACHE_FORMAT_VERSION = \"osm-geoparquet-v2\";\n\ntype OsmCacheSource = {\n file: string;\n creation: number;\n duration?: number;\n formatVersion: string;\n};\n\ntype OsmCacheSources = { [id: string]: OsmCacheSource };\n\nexport function createOsmCacheId(identity: unknown): string {\n return createFileCacheId(\"osm\", [OSM_CACHE_FORMAT_VERSION, identity]);\n}\n\nexport async function useProcessedOsmCache(\n table: SimpleTable,\n options: {\n id: string;\n enabled: boolean;\n ttl?: number;\n verbose: boolean;\n parameters: { [key: string]: unknown };\n compute: () => Promise<void>;\n },\n): Promise<void> {\n if (!options.enabled) {\n if (options.verbose) {\n console.log(\n \"Processed cache disabled. Fresh data will be used without reading or writing cache entries.\",\n );\n }\n await options.compute();\n return;\n }\n\n const sourcesFile = `${CACHE_DIRECTORY}/sources.json`;\n const sources = readSources(sourcesFile);\n const cached = sources[options.id];\n if (cached !== undefined) {\n if (!isOsmCacheSource(cached)) {\n delete sources[options.id];\n writeSources(sourcesFile, sources);\n console.log(\n \"The matching processed cache entry was incomplete and was removed. Fresh data is being requested.\",\n );\n } else {\n const now = Date.now();\n if (options.ttl !== undefined && cacheEntryExpired(cached.creation, options.ttl, now)) {\n const age = now - cached.creation;\n removeEntry(options.id, cached, sources, sourcesFile);\n console.log(\n `Processed cache entry expired after ${prettyDuration(0, { end: age })}; ` +\n `the configured TTL is ${prettyDuration(0, { end: options.ttl * 1000 })}.\\n` +\n \"The matching cache file was removed. Fresh data is being requested.\",\n );\n } else if (await loadEntry(table, cached, sources, sourcesFile, options)) {\n return;\n }\n }\n } else {\n if (options.verbose) {\n console.log(\"No processed cache entry matched this source.\");\n }\n }\n\n const started = Date.now();\n await options.compute();\n const computeDuration = Date.now() - started;\n await writeEntry(table, sources, sourcesFile, options, computeDuration);\n}\n\nasync function loadEntry(\n table: SimpleTable,\n cached: OsmCacheSource,\n sources: OsmCacheSources,\n sourcesFile: string,\n options: {\n id: string;\n verbose: boolean;\n parameters: { [key: string]: unknown };\n },\n): Promise<boolean> {\n if (\n cached.formatVersion !== OSM_CACHE_FORMAT_VERSION ||\n typeof cached.file !== \"string\" ||\n !existsSync(cached.file)\n ) {\n removeEntry(options.id, cached, sources, sourcesFile);\n console.log(\n \"The matching processed cache entry was incomplete or missing and was removed. Fresh data is being requested.\",\n );\n return false;\n }\n\n const size = statSync(cached.file).size;\n if (options.verbose) {\n console.log(\n `Processed cache hit.\\nLoading ${formatBytes(\n size,\n )} from the GeoParquet cache; Osmium will not run.`,\n );\n }\n const started = Date.now();\n try {\n await queryDB(\n table,\n `INSTALL spatial;\n LOAD spatial;\n SET geometry_always_xy = true;\n CREATE OR REPLACE TABLE ${quoteIdentifier(table.name)} AS\n SELECT * FROM read_parquet(${parseValue(cached.file)});`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadOpenStreetMap()\",\n parameters: options.parameters,\n }),\n );\n table.sdb.spatialLoaded = true;\n if (options.verbose) {\n const rows = await getRowCount(table, options.parameters);\n console.log(`Loaded ${rows.toLocaleString(\"en-US\")} rows in ${prettyDuration(started)}.`);\n if (cached.duration !== undefined) {\n table.sdb.cacheTimeSaved += cached.duration - (Date.now() - started);\n }\n }\n return true;\n } catch {\n removeEntry(options.id, cached, sources, sourcesFile);\n console.log(\n \"The matching processed cache entry was corrupt or unusable and was removed. Fresh data is being requested.\",\n );\n return false;\n }\n}\n\nasync function writeEntry(\n table: SimpleTable,\n sources: OsmCacheSources,\n sourcesFile: string,\n options: {\n id: string;\n verbose: boolean;\n parameters: { [key: string]: unknown };\n },\n computeDuration: number,\n): Promise<void> {\n mkdirSync(CACHE_DIRECTORY, { recursive: true });\n const file = `${CACHE_DIRECTORY}/${options.id}.geoparquet`;\n const temporaryFile = `${file}.${crypto.randomUUID()}.tmp.geoparquet`;\n if (options.verbose) {\n console.log(\"Writing processed GeoParquet cache...\");\n }\n const started = Date.now();\n try {\n await queryDB(\n table,\n `COPY ${quoteIdentifier(table.name)} TO ${parseValue(temporaryFile)}\n WITH (FORMAT PARQUET);`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadOpenStreetMap()\",\n parameters: options.parameters,\n }),\n );\n renameSync(temporaryFile, file);\n } catch (error) {\n rmSync(temporaryFile, { force: true });\n throw error;\n }\n\n const creation = Date.now();\n sources[options.id] = {\n file,\n creation,\n duration: computeDuration,\n formatVersion: OSM_CACHE_FORMAT_VERSION,\n };\n try {\n writeSources(sourcesFile, sources);\n } catch (error) {\n rmSync(file, { force: true });\n delete sources[options.id];\n throw error;\n }\n if (options.verbose) {\n const size = statSync(file).size;\n console.log(`Wrote ${formatBytes(size)} in ${prettyDuration(started)}.`);\n table.sdb.cacheTimeWriting += Date.now() - started;\n }\n}\n\nasync function getRowCount(\n table: SimpleTable,\n parameters: { [key: string]: unknown },\n): Promise<number> {\n const data = await queryDB(\n table,\n `SELECT count(*)::DOUBLE AS count FROM ${quoteIdentifier(table.name)};`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadOpenStreetMap()\",\n parameters,\n returnData: true,\n }),\n );\n const count = data?.[0]?.count;\n return typeof count === \"number\" ? count : Number(count ?? 0);\n}\n\nfunction removeEntry(\n id: string,\n source: Partial<OsmCacheSource>,\n sources: OsmCacheSources,\n sourcesFile: string,\n): void {\n if (typeof source.file === \"string\") rmSync(source.file, { force: true });\n delete sources[id];\n writeSources(sourcesFile, sources);\n}\n\nfunction readSources(sourcesFile: string): OsmCacheSources {\n if (!existsSync(sourcesFile)) return {};\n try {\n const value = JSON.parse(readFileSync(sourcesFile, \"utf-8\")) as unknown;\n return typeof value === \"object\" && value !== null ? (value as OsmCacheSources) : {};\n } catch {\n rmSync(sourcesFile, { force: true });\n console.log(\n \"The OpenStreetMap cache index was corrupt and was removed. Fresh data is being requested.\",\n );\n return {};\n }\n}\n\nfunction isOsmCacheSource(value: unknown): value is OsmCacheSource {\n if (typeof value !== \"object\" || value === null) return false;\n const source = value as { [key: string]: unknown };\n return (\n typeof source.file === \"string\" &&\n typeof source.creation === \"number\" &&\n Number.isFinite(source.creation) &&\n typeof source.formatVersion === \"string\" &&\n (source.duration === undefined ||\n (typeof source.duration === \"number\" && Number.isFinite(source.duration)))\n );\n}\n\nfunction writeSources(sourcesFile: string, sources: OsmCacheSources): void {\n mkdirSync(CACHE_DIRECTORY, { recursive: true });\n const temporaryFile = `${sourcesFile}.${crypto.randomUUID()}.tmp`;\n try {\n writeFileSync(temporaryFile, JSON.stringify(sources));\n renameSync(temporaryFile, sourcesFile);\n } catch (error) {\n rmSync(temporaryFile, { force: true });\n throw error;\n }\n}\n","import { realpathSync, rmSync, statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport SDAError from \"../class/SDAError.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport loadOsmFile from \"../helpers/loadOsmFile.ts\";\nimport { createOsmCacheId, useProcessedOsmCache } from \"../helpers/osmCache.ts\";\nimport {\n downloadOsmToTemporaryFile,\n formatBytes,\n getOsmFileSuffix,\n isRemoteOsmUrl,\n normalizeRemoteOsmUrl,\n sanitizeOsmUrl,\n} from \"../helpers/osmFiles.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport prettyDuration from \"../helpers/prettyDuration.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\n\nconst DEFAULT_OVERPASS_ENDPOINT = \"https://overpass-api.de/api/interpreter\";\nconst DEFAULT_REMOTE_FILE_TIMEOUT = 30 * 60;\nconst QUERY_GENERATOR_VERSION = \"overpass-ql-v1\";\n\ntype BoundingBox = {\n west: number;\n south: number;\n east: number;\n north: number;\n};\n\ntype CommonOptions = {\n cache?: boolean;\n ttl?: number;\n retries?: number;\n retryDelay?: number;\n verbose?: boolean;\n};\n\ntype LoadOpenStreetMapFileOptions = CommonOptions;\n\ntype LoadOpenStreetMapOverpassOptions = CommonOptions & {\n filters: string | [string, string] | [string, string][];\n endpoint?: string;\n timeout?: number;\n};\n\nexport default function loadOpenStreetMap(\n table: SimpleTable,\n source: string | BoundingBox,\n options: LoadOpenStreetMapFileOptions | LoadOpenStreetMapOverpassOptions = {},\n): void {\n if (typeof source === \"string\") {\n queueOpenStreetMapFileLoad(table, source, options as LoadOpenStreetMapFileOptions);\n return;\n }\n queueOverpassLoad(table, source, options as LoadOpenStreetMapOverpassOptions);\n}\n\nfunction queueOpenStreetMapFileLoad(\n table: SimpleTable,\n file: string,\n options: LoadOpenStreetMapFileOptions,\n): void {\n const suffix = getOsmFileSuffix(file);\n if (suffix === null) {\n throw new Error(\"loadOpenStreetMap() file paths and URLs must end with .osm or .osm.pbf.\");\n }\n options = structuredClone(options);\n assertOptions(options, false);\n\n let remoteUrl: string | undefined;\n if (isRemoteOsmUrl(file)) {\n remoteUrl = normalizeRemoteOsmUrl(file);\n } else {\n try {\n const url = new URL(file);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"loadOpenStreetMap() URL sources must use HTTP or HTTPS.\");\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"must use HTTP\")) {\n throw error;\n }\n }\n if (options.retries !== undefined || options.retryDelay !== undefined) {\n throw new Error(\n \"loadOpenStreetMap() options.retries and options.retryDelay are network-only and cannot be used with a local path.\",\n );\n }\n }\n\n const parameters = { file, options };\n queueOp(table, {\n kind: \"barrier\",\n method: \"loadOpenStreetMap()\",\n parameters,\n execute: () =>\n executeOpenStreetMapFileLoad(table, remoteUrl ?? file, suffix, options, parameters),\n });\n}\n\nasync function executeOpenStreetMapFileLoad(\n table: SimpleTable,\n file: string,\n suffix: \".osm\" | \".osm.pbf\",\n options: LoadOpenStreetMapFileOptions,\n parameters: { [key: string]: unknown },\n): Promise<void> {\n const started = Date.now();\n const verbose = options.verbose === true || table.sdb.cacheVerbose;\n const remote = isRemoteOsmUrl(file);\n const displayedSource = remote ? sanitizeOsmUrl(file) : resolve(file);\n if (verbose) {\n console.log(`loadOpenStreetMap(): loading ${displayedSource}`);\n }\n\n try {\n if (remote) {\n const cacheId = createOsmCacheId({ kind: \"remote\", url: file });\n await useProcessedOsmCache(table, {\n id: cacheId,\n enabled: options.cache ?? true,\n ttl: options.ttl,\n verbose,\n parameters,\n compute: async () => {\n const temporaryFile = await downloadOsmToTemporaryFile(file, {\n suffix,\n prefix: cacheId,\n request: { headers: { \"accept-encoding\": \"gzip\" } },\n retries: options.retries,\n retryDelay: options.retryDelay,\n timeout: DEFAULT_REMOTE_FILE_TIMEOUT,\n verbose,\n });\n try {\n await processOsmFile(table, temporaryFile, parameters, verbose);\n } finally {\n rmSync(temporaryFile, { force: true });\n if (verbose) {\n console.log(\"Removed the temporary raw OSM download.\");\n }\n }\n },\n });\n } else {\n if (verbose) {\n console.log(\"Resolving and fingerprinting the local OSM file...\");\n }\n const fingerprintStarted = Date.now();\n const resolvedPath = realpathSync(resolve(file));\n const stat = statSync(resolvedPath, { bigint: true });\n if (!stat.isFile()) {\n throw new Error(`The OpenStreetMap source is not a file: ${resolvedPath}`);\n }\n if (verbose) {\n console.log(\n `Resolved ${formatBytes(Number(stat.size))} and fingerprinted it in ${prettyDuration(\n fingerprintStarted,\n )}.`,\n );\n }\n const cacheId = createOsmCacheId({\n kind: \"local\",\n path: resolvedPath,\n size: stat.size.toString(),\n mtimeNs: stat.mtimeNs.toString(),\n });\n await useProcessedOsmCache(table, {\n id: cacheId,\n enabled: options.cache ?? true,\n ttl: options.ttl,\n verbose,\n parameters,\n compute: () => processOsmFile(table, resolvedPath, parameters, verbose),\n });\n }\n if (verbose) {\n console.log(`loadOpenStreetMap(): completed in ${prettyDuration(started)}.`);\n }\n } catch (error) {\n if (error instanceof SDAError) throw error;\n throw new SDAError({\n method: \"loadOpenStreetMap()\",\n parameters,\n query: \"\",\n cause: error,\n });\n }\n}\n\nfunction queueOverpassLoad(\n table: SimpleTable,\n bbox: BoundingBox,\n options: LoadOpenStreetMapOverpassOptions,\n): void {\n bbox = normalizeBoundingBox(bbox);\n options = structuredClone(options);\n assertOptions(options, true);\n const endpoint = normalizeEndpoint(options.endpoint ?? DEFAULT_OVERPASS_ENDPOINT);\n const filters = normalizeFilters(options.filters);\n const query = generateOverpassQuery(bbox, filters, options.timeout);\n const parameters = { bbox, options };\n\n queueOp(table, {\n kind: \"barrier\",\n method: \"loadOpenStreetMap()\",\n parameters,\n execute: () => executeOverpassLoad(table, options, endpoint, query, parameters),\n });\n}\n\nasync function executeOverpassLoad(\n table: SimpleTable,\n options: LoadOpenStreetMapOverpassOptions,\n endpoint: string,\n query: string,\n parameters: { [key: string]: unknown },\n): Promise<void> {\n const started = Date.now();\n const verbose = options.verbose === true || table.sdb.cacheVerbose;\n if (verbose) {\n console.log(`loadOpenStreetMap(): querying ${sanitizeOsmUrl(endpoint)}`);\n }\n try {\n const cacheId = createOsmCacheId({\n kind: \"overpass\",\n endpoint,\n query,\n queryGeneratorVersion: QUERY_GENERATOR_VERSION,\n });\n await useProcessedOsmCache(table, {\n id: cacheId,\n enabled: options.cache ?? true,\n ttl: options.ttl,\n verbose,\n parameters,\n compute: async () => {\n const body = new URLSearchParams({ data: query });\n const temporaryFile = await downloadOsmToTemporaryFile(endpoint, {\n suffix: \".osm\",\n prefix: cacheId,\n request: {\n method: \"POST\",\n headers: {\n \"accept-encoding\": \"gzip\",\n \"content-type\": \"application/x-www-form-urlencoded;charset=UTF-8\",\n \"user-agent\":\n \"simple-data-analysis-core (https://github.com/nshiab/simple-data-analysis-core)\",\n },\n body,\n },\n retries: options.retries,\n retryDelay: options.retryDelay,\n timeout: options.timeout,\n overpass: true,\n verbose,\n });\n try {\n try {\n await assertSuccessfulOverpassResponse(temporaryFile);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(\n `${reason}\\nNot retrying because the Overpass response was well-formed and reported a query error.\\nNo invalid cached data was returned.`,\n { cause: error },\n );\n }\n await processOsmFile(table, temporaryFile, parameters, verbose);\n } finally {\n rmSync(temporaryFile, { force: true });\n if (verbose) {\n console.log(\"Removed the temporary raw Overpass download.\");\n }\n }\n },\n });\n if (verbose) {\n console.log(`loadOpenStreetMap(): completed in ${prettyDuration(started)}.`);\n }\n } catch (error) {\n if (error instanceof SDAError) throw error;\n throw new SDAError({\n method: \"loadOpenStreetMap()\",\n parameters,\n query,\n cause: error,\n });\n }\n}\n\nasync function processOsmFile(\n table: SimpleTable,\n file: string,\n parameters: { [key: string]: unknown },\n verbose: boolean,\n): Promise<void> {\n if (verbose) {\n console.log(\"Processing OSM data with Osmium...\");\n }\n const started = Date.now();\n try {\n await loadOsmFile(table, file, {\n method: \"loadOpenStreetMap()\",\n parameters,\n });\n } catch (error) {\n const cause = error instanceof SDAError ? error.cause : error;\n const reason = cause instanceof Error ? cause.message : String(cause);\n throw new Error(\n `${reason}\\nNot retrying because Osmium or a downstream DuckDB operation rejected the source data.\\nNo invalid cached data was returned.`,\n { cause: error },\n );\n }\n if (verbose) {\n const data = await queryDB(\n table,\n `SELECT count(*)::DOUBLE AS count FROM ${quoteIdentifier(table.name)};`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadOpenStreetMap()\",\n parameters,\n returnData: true,\n }),\n );\n const count = Number(data?.[0]?.count ?? 0);\n console.log(`Processed ${count.toLocaleString(\"en-US\")} rows in ${prettyDuration(started)}.`);\n }\n}\n\nasync function assertSuccessfulOverpassResponse(file: string): Promise<void> {\n const contents = await readFile(file, \"utf8\");\n const match = /<(remark|error)\\b[^>]*>([\\s\\S]*?)(?:<\\/\\1\\s*>|$)/i.exec(contents);\n if (match === null) return;\n const message = match[2]\n .replace(/<[^>]*>/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 500);\n throw new Error(\n message.length === 0\n ? \"The Overpass endpoint returned an error response.\"\n : `The Overpass endpoint returned an error response: ${message}`,\n );\n}\n\nexport function generateOverpassQuery(\n bbox: BoundingBox,\n filters: string[],\n timeout?: number,\n): string {\n const box = `${bbox.south},${bbox.west},${bbox.north},${bbox.east}`;\n const selections = filters.map((filter) => `nwr${filter}(${box});`);\n const selection = selections.length === 1 ? selections[0] : `(${selections.join(\"\")});`;\n return `[out:xml]${\n timeout === undefined ? \"\" : `[timeout:${timeout}]`\n };${selection}(._;>;);out body;`;\n}\n\nfunction normalizeBoundingBox(bbox: BoundingBox): BoundingBox {\n const normalized = structuredClone(bbox);\n for (const [name, value] of Object.entries(normalized)) {\n if (!Number.isFinite(value)) {\n throw new Error(`loadOpenStreetMap() bbox.${name} must be a finite number.`);\n }\n }\n if (normalized.west < -180 || normalized.west > 180) {\n throw new Error(\"loadOpenStreetMap() bbox.west must be between -180 and 180.\");\n }\n if (normalized.east < -180 || normalized.east > 180) {\n throw new Error(\"loadOpenStreetMap() bbox.east must be between -180 and 180.\");\n }\n if (normalized.south < -90 || normalized.south > 90) {\n throw new Error(\"loadOpenStreetMap() bbox.south must be between -90 and 90.\");\n }\n if (normalized.north < -90 || normalized.north > 90) {\n throw new Error(\"loadOpenStreetMap() bbox.north must be between -90 and 90.\");\n }\n if (normalized.west >= normalized.east) {\n throw new Error(\"loadOpenStreetMap() bbox.west must be less than bbox.east.\");\n }\n if (normalized.south >= normalized.north) {\n throw new Error(\"loadOpenStreetMap() bbox.south must be less than bbox.north.\");\n }\n normalized.west = Object.is(normalized.west, -0) ? 0 : normalized.west;\n normalized.south = Object.is(normalized.south, -0) ? 0 : normalized.south;\n normalized.east = Object.is(normalized.east, -0) ? 0 : normalized.east;\n normalized.north = Object.is(normalized.north, -0) ? 0 : normalized.north;\n return normalized;\n}\n\nfunction normalizeFilters(filters: string | [string, string] | [string, string][]): string[] {\n if (typeof filters === \"string\") {\n const filter = filters.trim();\n if (filter.length === 0) {\n throw new Error(\n \"loadOpenStreetMap() filters must contain at least one non-empty filter fragment.\",\n );\n }\n return [filter];\n }\n if (!Array.isArray(filters)) {\n throw new TypeError(\"loadOpenStreetMap() options.filters is required.\");\n }\n const tuples = isFilterTuple(filters) ? [filters] : filters;\n const normalized = tuples.map(([key, value]) => {\n if (typeof key !== \"string\" || typeof value !== \"string\") {\n throw new TypeError(\"loadOpenStreetMap() filter tuples must contain two strings.\");\n }\n if (key.length === 0) {\n throw new Error(\"loadOpenStreetMap() filter keys must not be empty.\");\n }\n return `[${JSON.stringify(key)}=${JSON.stringify(value)}]`;\n });\n if (normalized.length === 0) {\n throw new Error(\"loadOpenStreetMap() filters must contain at least one filter tuple.\");\n }\n return normalized;\n}\n\nfunction isFilterTuple(\n filters: [string, string] | [string, string][],\n): filters is [string, string] {\n return filters.length === 2 && typeof filters[0] === \"string\" && typeof filters[1] === \"string\";\n}\n\nfunction normalizeEndpoint(endpoint: string): string {\n try {\n return normalizeRemoteOsmUrl(endpoint);\n } catch {\n throw new Error(\"loadOpenStreetMap() endpoint must be a valid HTTP or HTTPS URL.\");\n }\n}\n\nfunction assertOptions(\n options: CommonOptions & {\n filters?: string | [string, string] | [string, string][];\n endpoint?: string;\n timeout?: number;\n },\n overpass: boolean,\n): void {\n const allowed = new Set([\n \"cache\",\n \"ttl\",\n \"retries\",\n \"retryDelay\",\n \"verbose\",\n ...(overpass ? [\"filters\", \"endpoint\", \"timeout\"] : []),\n ]);\n const unsupported = Object.keys(options).filter((key) => !allowed.has(key));\n if (unsupported.length > 0) {\n throw new Error(\n `loadOpenStreetMap() does not support ${unsupported\n .map((key) => `options.${key}`)\n .join(\n \", \",\n )} for this source. Apply filtering and projection with normal table methods after loading.`,\n );\n }\n if (options.cache !== undefined && typeof options.cache !== \"boolean\") {\n throw new TypeError(\"loadOpenStreetMap() options.cache must be a boolean.\");\n }\n if (options.verbose !== undefined && typeof options.verbose !== \"boolean\") {\n throw new TypeError(\"loadOpenStreetMap() options.verbose must be a boolean.\");\n }\n if (options.ttl !== undefined && (!Number.isFinite(options.ttl) || options.ttl < 0)) {\n throw new Error(\n \"loadOpenStreetMap() options.ttl must be a finite, non-negative number of seconds.\",\n );\n }\n if (options.cache === false && options.ttl !== undefined) {\n throw new Error(\"loadOpenStreetMap() options.cache cannot be false when options.ttl is set.\");\n }\n if (\n options.retries !== undefined &&\n (!Number.isInteger(options.retries) || options.retries < 0)\n ) {\n throw new Error(\"loadOpenStreetMap() options.retries must be a non-negative integer.\");\n }\n if (\n options.retryDelay !== undefined &&\n (!Number.isFinite(options.retryDelay) || options.retryDelay < 0)\n ) {\n throw new Error(\n \"loadOpenStreetMap() options.retryDelay must be a finite, non-negative number of seconds.\",\n );\n }\n if (\n overpass &&\n options.timeout !== undefined &&\n (!Number.isInteger(options.timeout) || options.timeout <= 0)\n ) {\n throw new Error(\"loadOpenStreetMap() options.timeout must be a positive integer in seconds.\");\n }\n}\n","import { createReadStream, createWriteStream } from \"node:fs\";\nimport { open, rm, stat } from \"node:fs/promises\";\nimport { Transform, type TransformCallback } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { createInflateRaw } from \"node:zlib\";\n\n/*\n * Adapted from the ZIP reader in @nshiab/journalism-web-scraping. This\n * version streams the selected entry to disk so complete StatCan tables do\n * not need to be buffered in JavaScript memory.\n */\n\nconst END_OF_CENTRAL_DIRECTORY = 0x0605_4b50;\nconst CENTRAL_DIRECTORY_ENTRY = 0x0201_4b50;\nconst LOCAL_FILE_HEADER = 0x0403_4b50;\nconst MAX_COMMENT_LENGTH = 0xffff;\nconst MAX_END_RECORD_LENGTH = 22 + MAX_COMMENT_LENGTH;\nconst CRC_TABLE = createCrcTable();\n\ntype ZipEntry = {\n compressionMethod: number;\n compressedSize: number;\n uncompressedSize: number;\n expectedCrc: number;\n localHeaderOffset: number;\n};\n\nclass ChecksumTransform extends Transform {\n #crc = 0xffff_ffff;\n size = 0;\n\n get crc32(): number {\n return (this.#crc ^ 0xffff_ffff) >>> 0;\n }\n\n override _transform(\n chunk: Uint8Array,\n _encoding: BufferEncoding,\n callback: TransformCallback,\n ): void {\n for (const byte of chunk) {\n this.#crc = CRC_TABLE[(this.#crc ^ byte) & 0xff] ^ (this.#crc >>> 8);\n }\n this.size += chunk.byteLength;\n callback(null, chunk);\n }\n}\n\n/** Extracts one entry from a non-ZIP64, single-disk ZIP without buffering it. */\nexport default async function extractZipEntryToFile(\n archive: string,\n wantedName: string,\n output: string,\n): Promise<void> {\n const entry = await findZipEntry(archive, wantedName);\n if (entry === undefined) {\n throw new Error(`No ${wantedName} in the zipped file.`);\n }\n if (entry.compressionMethod !== 0 && entry.compressionMethod !== 8) {\n throw new Error(\n `ZIP entry ${wantedName} uses unsupported compression method ${entry.compressionMethod}.`,\n );\n }\n\n const file = await open(archive, \"r\");\n let operationError: unknown;\n try {\n const localHeader = new Uint8Array(30);\n await readExactly(file, localHeader, entry.localHeaderOffset);\n const view = new DataView(localHeader.buffer);\n assertSignature(view, 0, LOCAL_FILE_HEADER, \"local file header\");\n const fileNameLength = view.getUint16(26, true);\n const extraLength = view.getUint16(28, true);\n const dataOffset = entry.localHeaderOffset + 30 + fileNameLength + extraLength;\n const checksum = new ChecksumTransform();\n const source = createReadStream(archive, {\n start: dataOffset,\n end: dataOffset + entry.compressedSize - 1,\n });\n const streams =\n entry.compressionMethod === 8\n ? ([\n source,\n createInflateRaw(),\n checksum,\n createWriteStream(output, {\n flags: \"wx\",\n }),\n ] as const)\n : ([source, checksum, createWriteStream(output, { flags: \"wx\" })] as const);\n await pipeline(streams);\n\n if (checksum.size !== entry.uncompressedSize) {\n throw new Error(`ZIP entry ${wantedName} has an invalid size.`);\n }\n if (checksum.crc32 !== entry.expectedCrc) {\n throw new Error(`ZIP entry ${wantedName} failed its CRC check.`);\n }\n } catch (error) {\n operationError = error;\n }\n\n try {\n await file.close();\n } catch (closeError) {\n operationError =\n operationError === undefined\n ? closeError\n : new AggregateError(\n [operationError, closeError],\n \"Extracting and closing the ZIP archive both failed.\",\n { cause: operationError },\n );\n }\n\n if (operationError !== undefined) {\n try {\n await rm(output, { force: true });\n } catch (cleanupError) {\n throw new AggregateError(\n [operationError, cleanupError],\n \"Extracting and cleaning up the ZIP entry both failed.\",\n { cause: operationError },\n );\n }\n throw operationError;\n }\n}\n\nasync function findZipEntry(archive: string, wantedName: string): Promise<ZipEntry | undefined> {\n const file = await open(archive, \"r\");\n try {\n const size = (await stat(archive)).size;\n const tailLength = Math.min(size, MAX_END_RECORD_LENGTH);\n const tail = new Uint8Array(tailLength);\n await readExactly(file, tail, size - tailLength);\n const tailView = new DataView(tail.buffer);\n const endOffset = findEndOfCentralDirectory(tailView);\n const diskNumber = tailView.getUint16(endOffset + 4, true);\n const centralDirectoryDisk = tailView.getUint16(endOffset + 6, true);\n const entriesOnDisk = tailView.getUint16(endOffset + 8, true);\n const entryCount = tailView.getUint16(endOffset + 10, true);\n const centralDirectorySize = tailView.getUint32(endOffset + 12, true);\n const centralDirectoryOffset = tailView.getUint32(endOffset + 16, true);\n\n if (diskNumber !== 0 || centralDirectoryDisk !== 0 || entriesOnDisk !== entryCount) {\n throw new Error(\"Multi-disk ZIP archives are not supported.\");\n }\n if (\n entryCount === 0xffff ||\n centralDirectorySize === 0xffff_ffff ||\n centralDirectoryOffset === 0xffff_ffff\n ) {\n throw new Error(\"ZIP64 archives are not supported.\");\n }\n if (centralDirectoryOffset + centralDirectorySize > size) {\n throw new Error(\"Invalid ZIP archive: truncated central directory.\");\n }\n\n const centralDirectory = new Uint8Array(centralDirectorySize);\n await readExactly(file, centralDirectory, centralDirectoryOffset);\n const view = new DataView(centralDirectory.buffer);\n let offset = 0;\n for (let index = 0; index < entryCount; index++) {\n assertSignature(view, offset, CENTRAL_DIRECTORY_ENTRY, \"central directory\");\n assertRange(centralDirectory, offset, 46, \"central directory entry\");\n const flags = view.getUint16(offset + 8, true);\n const compressionMethod = view.getUint16(offset + 10, true);\n const expectedCrc = view.getUint32(offset + 16, true);\n const compressedSize = view.getUint32(offset + 20, true);\n const uncompressedSize = view.getUint32(offset + 24, true);\n const fileNameLength = view.getUint16(offset + 28, true);\n const extraLength = view.getUint16(offset + 30, true);\n const commentLength = view.getUint16(offset + 32, true);\n const localHeaderOffset = view.getUint32(offset + 42, true);\n const entryLength = 46 + fileNameLength + extraLength + commentLength;\n assertRange(centralDirectory, offset, entryLength, \"central directory entry\");\n const name = new TextDecoder().decode(\n centralDirectory.subarray(offset + 46, offset + 46 + fileNameLength),\n );\n if (name === wantedName) {\n if ((flags & 1) !== 0) {\n throw new Error(`ZIP entry ${wantedName} is encrypted.`);\n }\n if (\n compressedSize === 0xffff_ffff ||\n uncompressedSize === 0xffff_ffff ||\n localHeaderOffset === 0xffff_ffff\n ) {\n throw new Error(\"ZIP64 archives are not supported.\");\n }\n return {\n compressionMethod,\n compressedSize,\n uncompressedSize,\n expectedCrc,\n localHeaderOffset,\n };\n }\n offset += entryLength;\n }\n return undefined;\n } finally {\n await file.close();\n }\n}\n\nasync function readExactly(\n file: Awaited<ReturnType<typeof open>>,\n buffer: Uint8Array,\n position: number,\n): Promise<void> {\n let offset = 0;\n while (offset < buffer.byteLength) {\n const { bytesRead } = await file.read(\n buffer,\n offset,\n buffer.byteLength - offset,\n position + offset,\n );\n if (bytesRead === 0) {\n throw new Error(\"Invalid ZIP archive: unexpected end of file.\");\n }\n offset += bytesRead;\n }\n}\n\nfunction findEndOfCentralDirectory(view: DataView): number {\n for (let offset = view.byteLength - 22; offset >= 0; offset--) {\n if (\n view.getUint32(offset, true) === END_OF_CENTRAL_DIRECTORY &&\n offset + 22 + view.getUint16(offset + 20, true) === view.byteLength\n ) {\n return offset;\n }\n }\n throw new Error(\"Invalid ZIP archive: end of central directory not found.\");\n}\n\nfunction assertSignature(\n view: DataView,\n offset: number,\n expected: number,\n description: string,\n): void {\n if (offset < 0 || offset + 4 > view.byteLength) {\n throw new Error(`Invalid ZIP archive: truncated ${description}.`);\n }\n if (view.getUint32(offset, true) !== expected) {\n throw new Error(`Invalid ZIP archive: malformed ${description}.`);\n }\n}\n\nfunction assertRange(data: Uint8Array, offset: number, length: number, description: string): void {\n if (offset < 0 || length < 0 || offset + length > data.byteLength) {\n throw new Error(`Invalid ZIP archive: truncated ${description}.`);\n }\n}\n\nfunction createCrcTable(): Uint32Array {\n return Uint32Array.from({ length: 256 }, (_, index) => {\n let value = index;\n for (let bit = 0; bit < 8; bit++) {\n value = (value >>> 1) ^ (0xedb8_8320 & -(value & 1));\n }\n return value >>> 0;\n });\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport fileCache, { createFileCacheId } from \"./fileCache.ts\";\nimport mergeOptions from \"./mergeOptions.ts\";\nimport parseValue from \"./parseValue.ts\";\nimport queryDB from \"./queryDB.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\n\nconst CACHE_DIRECTORY = \".sda-cache/statcan\";\nconst CACHE_FORMAT_VERSION = \"statcan-parquet-v1\";\n\nexport function createStatCanCacheId(pid: string, lang: \"en\" | \"fr\"): string {\n return createFileCacheId(\"statcan\", [CACHE_FORMAT_VERSION, pid, lang]);\n}\n\nexport async function useStatCanCache(\n table: SimpleTable,\n id: string,\n enabled: boolean,\n ttl: number | undefined,\n parameters: { [key: string]: unknown },\n compute: () => Promise<void>,\n): Promise<void> {\n await fileCache(table, {\n directory: CACHE_DIRECTORY,\n enabled,\n extension: \"parquet\",\n formatVersion: CACHE_FORMAT_VERSION,\n id,\n method: \"loadStatCanData()\",\n ttl,\n load: async (file) => {\n await queryDB(\n table,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(table.name)} AS\n SELECT * FROM read_parquet(${parseValue(file)});`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadStatCanData()\",\n parameters,\n }),\n );\n },\n compute,\n write: async (file) => {\n await queryDB(\n table,\n `COPY ${quoteIdentifier(table.name)} TO ${parseValue(file)}\n WITH (FORMAT PARQUET);`,\n mergeOptions(table, {\n table: table.name,\n method: \"loadStatCanData()\",\n parameters,\n }),\n );\n },\n });\n}\n","import crypto from \"node:crypto\";\nimport { createWriteStream, mkdirSync, rmSync } from \"node:fs\";\nimport { pipeline } from \"node:stream/promises\";\nimport { Readable } from \"node:stream\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\nimport SDAError from \"../class/SDAError.ts\";\nimport extractZipEntryToFile from \"../helpers/extractZipEntryToFile.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport { loadDataQuery } from \"./loadData.ts\";\nimport { createStatCanCacheId, useStatCanCache } from \"../helpers/statCanCache.ts\";\n\ntype LoadStatCanOptions = {\n lang?: \"en\" | \"fr\";\n cache?: boolean;\n ttl?: number;\n};\n\ntype StatCanDownloadResponse = {\n status?: unknown;\n object?: unknown;\n};\n\nconst DOWNLOAD_ENDPOINT = \"https://www150.statcan.gc.ca/t1/wds/rest/getFullTableDownloadCSV\";\n\n// Adapted from getStatCanTable() in @nshiab/journalism-web-scraping.\n\nexport default function loadStatCanData(\n table: SimpleTable,\n pid: string,\n options: LoadStatCanOptions = {},\n): void {\n pid = normalizeStatCanPid(pid);\n options = structuredClone(options);\n assertOptions(options);\n const lang = options.lang ?? \"en\";\n const parameters = { pid, options };\n\n queueOp(table, {\n kind: \"barrier\",\n method: \"loadStatCanData()\",\n parameters,\n execute: () => executeLoadStatCanData(table, pid, lang, options, parameters),\n });\n}\n\nasync function executeLoadStatCanData(\n table: SimpleTable,\n pid: string,\n lang: \"en\" | \"fr\",\n options: LoadStatCanOptions,\n parameters: { [key: string]: unknown },\n): Promise<void> {\n const cacheEnabled = options.cache ?? true;\n const cacheId = createStatCanCacheId(pid, lang);\n try {\n await useStatCanCache(table, cacheId, cacheEnabled, options.ttl, parameters, async () => {\n const downloadUrl = await getDownloadUrl(pid, lang);\n const temporaryDirectory = \".sda-cache/tmp\";\n mkdirSync(temporaryDirectory, { recursive: true });\n const prefix = `${cacheId}.${crypto.randomUUID()}`;\n const archive = `${temporaryDirectory}/${prefix}.zip`;\n const csv = `${temporaryDirectory}/${prefix}.csv`;\n\n try {\n await downloadToFile(downloadUrl, archive);\n await extractZipEntryToFile(archive, `${pid}.csv`, csv);\n await queryDB(\n table,\n loadDataQuery(table.name, [csv], { fileType: \"csv\" }),\n mergeOptions(table, {\n table: table.name,\n method: \"loadStatCanData()\",\n parameters,\n }),\n );\n } finally {\n rmSync(archive, { force: true });\n rmSync(csv, { force: true });\n }\n });\n } catch (error) {\n if (error instanceof SDAError) {\n throw error;\n }\n throw new SDAError({\n method: \"loadStatCanData()\",\n parameters,\n query: \"\",\n cause: error,\n });\n }\n}\n\nasync function getDownloadUrl(pid: string, lang: \"en\" | \"fr\"): Promise<string> {\n const url = `${DOWNLOAD_ENDPOINT}/${pid}/${lang}`;\n const response = await fetch(url, {\n headers: {\n \"user-agent\":\n \"simple-data-analysis-core (https://github.com/nshiab/simple-data-analysis-core)\",\n },\n });\n if (!response.ok) {\n throw await httpError(\"retrieve the Statistics Canada download URL\", url, response);\n }\n\n const result = (await response.json()) as StatCanDownloadResponse;\n if (result.status !== \"SUCCESS\" || typeof result.object !== \"string\") {\n throw new Error(`Statistics Canada did not return a CSV download URL for PID ${pid}.`);\n }\n const downloadUrl = new URL(result.object);\n if (downloadUrl.protocol !== \"http:\" && downloadUrl.protocol !== \"https:\") {\n throw new Error(`Statistics Canada returned an invalid CSV download URL for PID ${pid}.`);\n }\n return downloadUrl.href;\n}\n\nasync function downloadToFile(url: string, file: string): Promise<void> {\n const response = await fetch(url, {\n headers: {\n \"user-agent\":\n \"simple-data-analysis-core (https://github.com/nshiab/simple-data-analysis-core)\",\n },\n });\n if (!response.ok) {\n throw await httpError(\"download Statistics Canada data\", url, response);\n }\n if (response.body === null) {\n throw new Error(\n `Could not download Statistics Canada data from ${JSON.stringify(\n url,\n )}: the response body is empty.`,\n );\n }\n try {\n await pipeline(\n Readable.fromWeb(response.body as Parameters<typeof Readable.fromWeb>[0]),\n createWriteStream(file, { flags: \"wx\" }),\n );\n } catch (error) {\n rmSync(file, { force: true });\n throw error;\n }\n}\n\nasync function httpError(action: string, url: string, response: Response): Promise<Error> {\n const responseText = (await response.text()).slice(0, 500).trim();\n return new Error(\n `Could not ${action} from ${JSON.stringify(\n url,\n )}: HTTP ${response.status} ${response.statusText}${\n responseText.length > 0 ? `\\n${responseText}` : \"\"\n }`,\n );\n}\n\nexport function normalizeStatCanPid(pid: string): string {\n if (typeof pid !== \"string\") {\n throw new TypeError(\"loadStatCanData() pid must be a string.\");\n }\n const normalized = pid.replaceAll(\"-\", \"\");\n if (!/^\\d{8}(?:\\d{2})?$/.test(normalized)) {\n throw new Error(\n 'loadStatCanData() pid must contain 8 or 10 digits, optionally formatted like \"36-10-0402-01\".',\n );\n }\n return normalized.slice(0, 8);\n}\n\nfunction assertOptions(options: LoadStatCanOptions): void {\n if (options.lang !== undefined && options.lang !== \"en\" && options.lang !== \"fr\") {\n throw new Error('loadStatCanData() options.lang must be \"en\" or \"fr\".');\n }\n if (options.cache !== undefined && typeof options.cache !== \"boolean\") {\n throw new TypeError(\"loadStatCanData() options.cache must be a boolean.\");\n }\n if (options.ttl !== undefined && (!Number.isFinite(options.ttl) || options.ttl < 0)) {\n throw new Error(\n \"loadStatCanData() options.ttl must be a finite, non-negative number of seconds.\",\n );\n }\n}\n","import type SimpleTable from \"../class/SimpleTable.ts\";\nimport SDAError from \"../class/SDAError.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport { executePreparedArray, prepareArray } from \"./loadArray.ts\";\n\nconst INTERVAL_SECONDS = {\n \"1d\": 24 * 60 * 60,\n \"1h\": 60 * 60,\n \"1m\": 60,\n} as const;\n\nconst COLUMN_TYPES = {\n datetime: \"TIMESTAMP\",\n open: \"DOUBLE\",\n high: \"DOUBLE\",\n low: \"DOUBLE\",\n close: \"DOUBLE\",\n adjustedClose: \"DOUBLE\",\n volume: \"DOUBLE\",\n} as const;\n\ntype YahooInterval = keyof typeof INTERVAL_SECONDS;\ntype YahooQuoteVariable = \"open\" | \"high\" | \"low\" | \"close\" | \"volume\";\ntype YahooValues = Array<number | null>;\n\ntype YahooFinanceResult = {\n timestamp?: number[];\n indicators?: {\n adjclose?: Array<{ adjclose?: YahooValues }>;\n quote?: Array<Partial<Record<YahooQuoteVariable, YahooValues>>>;\n };\n};\n\ntype YahooFinanceResponse = {\n chart?: {\n error?: { description?: string } | null;\n result?: YahooFinanceResult[] | null;\n };\n};\n\ntype YahooFinanceRow = {\n datetime: Date;\n open: number | null;\n high: number | null;\n low: number | null;\n close: number | null;\n adjustedClose: number | null;\n volume: number | null;\n};\n\nexport default function loadYahooFinanceData(\n table: SimpleTable,\n symbol: string,\n startDate: Date,\n endDate: Date,\n interval: YahooInterval,\n): void {\n assertArguments(symbol, startDate, endDate, interval);\n const request = {\n symbol,\n startDate: new Date(startDate),\n endDate: new Date(endDate),\n interval,\n };\n\n queueOp(table, {\n kind: \"barrier\",\n method: \"loadYahooFinanceData()\",\n parameters: request,\n execute: () => executeLoadYahooFinanceData(table, request),\n });\n}\n\nasync function executeLoadYahooFinanceData(\n table: SimpleTable,\n request: {\n symbol: string;\n startDate: Date;\n endDate: Date;\n interval: YahooInterval;\n },\n): Promise<void> {\n try {\n const rows = await getYahooFinanceData(request);\n await executePreparedArray(table, prepareArray(rows, COLUMN_TYPES));\n } catch (error) {\n if (error instanceof SDAError) {\n throw error;\n }\n throw new SDAError({\n method: \"loadYahooFinanceData()\",\n parameters: request,\n query: \"\",\n cause: error,\n });\n }\n}\n\nasync function getYahooFinanceData(request: {\n symbol: string;\n startDate: Date;\n endDate: Date;\n interval: YahooInterval;\n}): Promise<YahooFinanceRow[]> {\n const { symbol, startDate, endDate, interval } = request;\n const startTime = startDate.getTime();\n const exclusiveEndTime = getExclusiveEndTime(endDate, interval);\n const url = new URL(\n `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(symbol)}`,\n );\n url.search = new URLSearchParams({\n includeAdjustedClose: \"true\",\n interval,\n period1: String(Math.floor(startTime / 1000)),\n period2: String(Math.ceil(exclusiveEndTime / 1000)),\n }).toString();\n\n const response = await fetch(url);\n if (!response.ok) {\n const text = (await response.text()).slice(0, 500).trim();\n throw new Error(\n `Failed to fetch Yahoo Finance data: ${response.status} ${response.statusText}${\n text.length > 0 ? `. ${text}` : \"\"\n }. Yahoo may have changed, rate-limited, or disabled this undocumented endpoint.`,\n );\n }\n\n const data = (await response.json()) as YahooFinanceResponse;\n if (data.chart?.error) {\n throw new Error(data.chart.error.description ?? \"Yahoo Finance returned an unknown error.\");\n }\n\n const result = data.chart?.result?.[0];\n const timestamps = result?.timestamp;\n if (!result || !timestamps?.length) {\n throw new Error(\"No Yahoo Finance data found.\");\n }\n\n const quote = result.indicators?.quote?.[0];\n const adjustedClose = result.indicators?.adjclose?.[0]?.adjclose;\n const rows: YahooFinanceRow[] = [];\n for (let index = 0; index < timestamps.length; index++) {\n const timestamp = timestamps[index] * 1000;\n if (Number.isFinite(timestamp) && timestamp >= startTime && timestamp < exclusiveEndTime) {\n rows.push({\n datetime: new Date(timestamp),\n open: getFiniteValue(quote?.open, index),\n high: getFiniteValue(quote?.high, index),\n low: getFiniteValue(quote?.low, index),\n close: getFiniteValue(quote?.close, index),\n adjustedClose: getFiniteValue(adjustedClose, index),\n volume: getFiniteValue(quote?.volume, index),\n });\n }\n }\n\n if (rows.length === 0) {\n throw new Error(`No Yahoo Finance data found for ${symbol}.`);\n }\n return rows;\n}\n\nfunction getFiniteValue(values: YahooValues | undefined, index: number): number | null {\n const value = values?.[index];\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction getExclusiveEndTime(endDate: Date, interval: YahooInterval): number {\n const end = new Date(endDate);\n if (interval === \"1d\") {\n end.setUTCHours(0, 0, 0, 0);\n } else if (interval === \"1h\") {\n end.setUTCMinutes(0, 0, 0);\n } else {\n end.setUTCSeconds(0, 0);\n }\n return end.getTime() + INTERVAL_SECONDS[interval] * 1000;\n}\n\nfunction assertArguments(\n symbol: string,\n startDate: Date,\n endDate: Date,\n interval: YahooInterval,\n): void {\n if (typeof symbol !== \"string\" || symbol.trim().length === 0) {\n throw new TypeError(\"loadYahooFinanceData() symbol must be a non-empty string.\");\n }\n if (\n !(startDate instanceof Date) ||\n !(endDate instanceof Date) ||\n !Number.isFinite(startDate.getTime()) ||\n !Number.isFinite(endDate.getTime())\n ) {\n throw new RangeError(\"loadYahooFinanceData() startDate and endDate must be valid dates.\");\n }\n if (endDate.getTime() < startDate.getTime()) {\n throw new RangeError(\n \"loadYahooFinanceData() endDate must be equal to or later than startDate.\",\n );\n }\n if (interval !== \"1d\" && interval !== \"1h\" && interval !== \"1m\") {\n throw new Error('loadYahooFinanceData() interval must be \"1d\", \"1h\", or \"1m\".');\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport ensureSpatial from \"../helpers/ensureSpatial.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport parseType from \"../helpers/parseTypes.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type SimpleTable from \"../class/SimpleTable.ts\";\n\nexport default function setTypes(\n simpleTable: SimpleTable,\n types: {\n [key: string]:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`;\n },\n) {\n // Creating a table from scratch (possibly with the spatial extension) is\n // multi-statement by nature: it executes as a barrier.\n types = structuredClone(types);\n queueOp(simpleTable, {\n kind: \"barrier\",\n method: \"setTypes()\",\n parameters: { types },\n execute: async () => {\n if (\n Object.values(types)\n .map((d) => d.toLowerCase())\n .some((d) => d.startsWith(\"geometry\"))\n ) {\n await ensureSpatial(simpleTable);\n }\n await queryDB(\n simpleTable,\n `CREATE OR REPLACE TABLE ${quoteIdentifier(simpleTable.name)} (${Object.keys(types)\n .map((d) => `${quoteIdentifier(d)} ${parseType(types[d])}`)\n .join(\", \")});`,\n mergeOptions(simpleTable, {\n table: simpleTable.name,\n method: \"setTypes()\",\n parameters: { types },\n }),\n );\n },\n });\n}\n","import umap from \"../methods/umap.ts\";\nimport hdbscan from \"../methods/hdbscan.ts\";\nimport logBottom from \"../methods/logBottom.ts\";\nimport log from \"../methods/log.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport csvFormat from \"../helpers/csvFormat.ts\";\nimport getDescription from \"../methods/getDescription.ts\";\nimport removeMissing from \"../methods/removeMissing.ts\";\nimport getColumns from \"../methods/getColumns.ts\";\nimport getRow from \"../methods/getRow.ts\";\nimport getRowCount from \"../methods/getRowCount.ts\";\nimport getCharacterCount from \"../methods/getCharacterCount.ts\";\nimport addCharacterCount from \"../methods/addCharacterCount.ts\";\nimport addWordCount from \"../methods/addWordCount.ts\";\nimport getTypes from \"../methods/getTypes.ts\";\nimport getHash from \"../methods/getHash.ts\";\nimport getValues from \"../methods/getValues.ts\";\nimport getUniques from \"../methods/getUniques.ts\";\nimport getFirstRow from \"../methods/getFirstRow.ts\";\nimport getLastRow from \"../methods/getLastRow.ts\";\nimport getTop from \"../methods/getTop.ts\";\nimport getBottom from \"../methods/getBottom.ts\";\nimport getMin from \"../methods/getMin.ts\";\nimport getMax from \"../methods/getMax.ts\";\nimport getMean from \"../methods/getMean.ts\";\nimport getMedian from \"../methods/getMedian.ts\";\nimport getSum from \"../methods/getSum.ts\";\nimport getSkew from \"../methods/getSkew.ts\";\nimport getStdDev from \"../methods/getStdDev.ts\";\nimport getVariance from \"../methods/getVariance.ts\";\nimport getQuantile from \"../methods/getQuantile.ts\";\nimport cloneColumn from \"../methods/cloneColumn.ts\";\nimport getGeoData from \"../methods/getGeoData.ts\";\nimport writeGeoData from \"../helpers/writeGeoData.ts\";\nimport splitSpread from \"../methods/splitSpread.ts\";\nimport type SimpleDB from \"./SimpleDB.ts\";\nimport runQuery from \"../helpers/runQuery.ts\";\nimport summarize from \"../methods/summarize.ts\";\nimport addSummaryRows from \"../methods/addSummaryRows.ts\";\nimport correlations from \"../methods/correlations.ts\";\nimport linearRegressions from \"../methods/linearRegressions.ts\";\nimport joinGeo from \"../methods/joinGeo.ts\";\nimport cache from \"../methods/cache.ts\";\nimport camelCase from \"../helpers/camelCase.ts\";\nimport formatNumber from \"../helpers/formatNumber.ts\";\nimport logData from \"../helpers/logData.ts\";\nimport fill from \"../methods/fill.ts\";\nimport loadArray from \"../methods/loadArray.ts\";\nimport Simple from \"./Simple.ts\";\nimport join from \"../methods/join.ts\";\nimport fuzzyJoin from \"../methods/fuzzyJoin.ts\";\nimport fuzzyClean from \"../methods/fuzzyClean.ts\";\nimport findGeoColumn from \"../helpers/findGeoColumn.ts\";\nimport createFtsIndex from \"../methods/createFtsIndex.ts\";\nimport createVssIndex from \"../methods/createVssIndex.ts\";\nimport bm25 from \"../methods/bm25.ts\";\nimport loadSample from \"../methods/loadSample.ts\";\nimport normalizeString from \"../methods/normalizeString.ts\";\nimport distance from \"../methods/distance.ts\";\nimport extractLatLon from \"../methods/extractLatLon.ts\";\nimport coveredBy from \"../methods/coveredBy.ts\";\nimport intersects from \"../methods/intersects.ts\";\nimport normalize from \"../methods/normalize.ts\";\nimport indexValues from \"../methods/indexValues.ts\";\nimport zScore from \"../methods/zScore.ts\";\nimport rolling from \"../methods/rolling.ts\";\nimport accumulate from \"../methods/accumulate.ts\";\nimport columnProportions from \"../methods/columnProportions.ts\";\nimport rowProportions from \"../methods/rowProportions.ts\";\nimport rowRanks from \"../methods/rowRanks.ts\";\nimport quantiles from \"../methods/quantiles.ts\";\nimport ranks from \"../methods/ranks.ts\";\nimport updateColumn from \"../methods/updateColumn.ts\";\nimport nest from \"../methods/nest.ts\";\nimport repeatRows from \"../methods/repeatRows.ts\";\nimport unnest from \"../methods/unnest.ts\";\nimport concatenate from \"../methods/concatenate.ts\";\nimport lastChars from \"../methods/lastChars.ts\";\nimport firstChars from \"../methods/firstChars.ts\";\nimport splitExtract from \"../methods/splitExtract.ts\";\nimport truncate from \"../methods/truncate.ts\";\nimport capitalize from \"../methods/capitalize.ts\";\nimport upper from \"../methods/upper.ts\";\nimport lower from \"../methods/lower.ts\";\nimport removeTable from \"../methods/removeTable.ts\";\nimport wider from \"../methods/wider.ts\";\nimport removeRows from \"../methods/removeRows.ts\";\nimport removeValues from \"../methods/removeValues.ts\";\nimport keepValues from \"../methods/keepValues.ts\";\nimport filter from \"../methods/filter.ts\";\nimport removeDuplicates from \"../methods/removeDuplicates.ts\";\nimport sample from \"../methods/sample.ts\";\nimport skip from \"../methods/skip.ts\";\nimport selectColumns from \"../methods/selectColumns.ts\";\nimport sort from \"../methods/sort.ts\";\nimport loadData from \"../methods/loadData.ts\";\nimport renameTable from \"../methods/renameTable.ts\";\nimport writeData from \"../methods/writeData.ts\";\nimport getBoundingBox from \"../methods/getBoundingBox.ts\";\nimport linesToPolygons from \"../methods/linesToPolygons.ts\";\nimport aggregateGeo from \"../methods/aggregateGeo.ts\";\nimport addBoundingBox from \"../methods/addBoundingBox.ts\";\nimport unnestGeo from \"../methods/unnestGeo.ts\";\nimport randomPoint from \"../methods/randomPoint.ts\";\nimport centroid from \"../methods/centroid.ts\";\nimport simplify from \"../methods/simplify.ts\";\nimport union from \"../methods/union.ts\";\nimport fillHoles from \"../methods/fillHoles.ts\";\nimport difference from \"../methods/difference.ts\";\nimport intersection from \"../methods/intersection.ts\";\nimport buffer from \"../methods/buffer.ts\";\nimport perimeter from \"../methods/perimeter.ts\";\nimport length from \"../methods/length.ts\";\nimport area from \"../methods/area.ts\";\nimport reproject from \"../methods/reproject.ts\";\nimport reducePrecision from \"../methods/reducePrecision.ts\";\nimport addGeoNoise from \"../methods/addGeoNoise.ts\";\nimport flipCoordinates from \"../methods/flipCoordinates.ts\";\nimport addGeoType from \"../methods/addGeoType.ts\";\nimport addGeoClosedStatus from \"../methods/addGeoClosedStatus.ts\";\nimport fixGeo from \"../methods/fixGeo.ts\";\nimport addVertexCount from \"../methods/addVertexCount.ts\";\nimport addGeoValidity from \"../methods/addGeoValidity.ts\";\nimport createPoints from \"../methods/createPoints.ts\";\nimport getData from \"../methods/getData.ts\";\nimport stream from \"../methods/stream.ts\";\nimport updateWithJS from \"../methods/updateWithJS.ts\";\nimport getSchema from \"../methods/getSchema.ts\";\nimport outliersIQR from \"../methods/outliersIQR.ts\";\nimport bins from \"../methods/bins.ts\";\nimport round from \"../methods/round.ts\";\nimport addNoise from \"../methods/addNoise.ts\";\nimport rowToText from \"../methods/rowToText.ts\";\nimport rowToVector from \"../methods/rowToVector.ts\";\nimport normalizeVector from \"../methods/normalizeVector.ts\";\nimport similarityMahalanobis from \"../methods/similarityMahalanobis.ts\";\nimport replaceNulls from \"../methods/replaceNulls.ts\";\nimport pad from \"../methods/pad.ts\";\nimport replace from \"../methods/replace.ts\";\nimport crossJoin from \"../methods/crossJoin.ts\";\nimport addId from \"../methods/addId.ts\";\nimport neighbors from \"../methods/neighbors.ts\";\nimport reachable from \"../methods/reachable.ts\";\nimport distances from \"../methods/distances.ts\";\nimport shortestPath from \"../methods/shortestPath.ts\";\nimport paths from \"../methods/paths.ts\";\nimport connectedComponents from \"../methods/connectedComponents.ts\";\nimport topologicalSort from \"../methods/topologicalSort.ts\";\nimport degree from \"../methods/degree.ts\";\nimport commonNeighbors from \"../methods/commonNeighbors.ts\";\nimport findCycles from \"../methods/findCycles.ts\";\nimport addRowNumber from \"../methods/addRowNumber.ts\";\nimport addColumn from \"../methods/addColumn.ts\";\nimport extractDatePart from \"../methods/extractDatePart.ts\";\nimport removeColumns from \"../methods/removeColumns.ts\";\nimport convert from \"../methods/convert.ts\";\nimport longer from \"../methods/longer.ts\";\nimport renameColumns from \"../methods/renameColumns.ts\";\nimport trim from \"../methods/trim.ts\";\nimport selectRows from \"../methods/selectRows.ts\";\nimport cloneColumnWithOffset from \"../methods/cloneColumnWithOffset.ts\";\nimport clone from \"../methods/clone.ts\";\nimport insertTables from \"../methods/insertTables.ts\";\nimport insertRows from \"../methods/insertRows.ts\";\nimport loadGeoData from \"../methods/loadGeoData.ts\";\nimport loadOpenStreetMap from \"../methods/loadOpenStreetMap.ts\";\nimport loadStatCanData from \"../methods/loadStatCanData.ts\";\nimport loadYahooFinanceData from \"../methods/loadYahooFinanceData.ts\";\nimport setTypes from \"../methods/setTypes.ts\";\nimport flushAllTables from \"../helpers/flushAllTables.ts\";\nimport queueOp from \"../helpers/queueOp.ts\";\nimport type { PendingOp } from \"../helpers/pendingOps.ts\";\n\n/**\n * IMPORTANT: When extending this class, always use `this.sdb.newTable()` to\n * create new tables instead of `new SimpleTable(...)` directly. This ensures\n * subclasses that override `tableClass` on their parent `SimpleDB` get their\n * own table type back.\n *\n * Represents a table within a SimpleDB database, capable of handling tabular, geospatial, and vector data.\n * SimpleTable instances are typically created via a SimpleDB instance.\n *\n * @example\n * ```ts\n * // Create a SimpleDB instance (in-memory by default)\n * const sdb = new SimpleDB();\n *\n * // Create a table, load a CSV file, and log its first few rows\n * const employees = await sdb\n * .newTable(\"employees\")\n * .loadData(\"./employees.csv\")\n * .log();\n *\n * // Close the database connection and free up resources\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Handling geospatial data\n * // Create a SimpleDB instance\n * const sdb = new SimpleDB();\n *\n * // Create a table and load geospatial data from a GeoJSON file\n * const boundaries = await sdb\n * .newTable(\"boundaries\")\n * .loadGeoData(\"./boundaries.geojson\")\n * .log();\n *\n * // Close the database connection\n * await sdb.close();\n * ```\n * @category Main\n */\n\nexport default class SimpleTable extends Simple {\n #name: string;\n\n /**\n * Name of the table in the database.\n *\n * @example\n * ```ts\n * console.log(table.name); // e.g., \"employees\"\n * ```\n * @category Properties\n */\n get name(): string {\n return this.#name;\n }\n /**\n * The definitions of the indexes belonging to the table, if any. Do not\n * mutate this array directly.\n *\n * @example\n * ```ts\n * console.log(table.indexes);\n * // [{ kind: \"vss\", name: \"vss_cosine_index_articles\", ... }]\n * ```\n * @defaultValue `[]`\n * @category Properties\n */\n indexes: (\n | {\n kind: \"vss\";\n name: string;\n column: string;\n options: {\n efConstruction?: number;\n efSearch?: number;\n M?: number;\n };\n }\n | {\n kind: \"fts\";\n name: string;\n idColumn: string;\n textColumn: string;\n options: {\n stemmer?: string;\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n };\n }\n )[];\n /**\n * The operations queued by sync builder methods, waiting to be executed at\n * the next observation point. This is for internal use only.\n *\n * @defaultValue `[]`\n * @internal\n */\n pendingOps: PendingOp[];\n /**\n * The SimpleDB instance that created this table.\n *\n * @category Properties\n */\n declare sdb: SimpleDB;\n\n /**\n * Creates an instance of SimpleTable.\n *\n * @param name - The name of the table.\n * @param simpleDB - The SimpleDB instance that this table belongs to.\n * @param options - An optional object with configuration options:\n * @param options.rowsToLog - The number of rows to log when displaying table data.\n * @param options.charsToLog - The maximum characters to display for text and stringified nested cells, including truncation markers (default: 75). Independent of column width. Use Infinity for unlimited text.\n * @param options.typesToLog - A boolean indicating whether to include data types when logging a table.\n * @category Constructor\n */\n constructor(\n name: string,\n simpleDB: SimpleDB,\n options: {\n rowsToLog?: number;\n charsToLog?: number;\n typesToLog?: boolean;\n } = {},\n ) {\n super(options);\n this.#name = name;\n this.sdb = simpleDB;\n this.runQuery = runQuery;\n this.indexes = [];\n this.pendingOps = [];\n }\n\n /**\n * Executes all queued methods across every table in the database, not just\n * this table. Sync builder methods (like `filter()` or `convert()`) only\n * queue their operation; execution happens when an async observer method\n * (like `getData()`, `log()`, or `writeData()`) is awaited. Use `run()`\n * when a chain ends in pure mutations with nothing to observe and you want\n * the work done now.\n *\n * Because the whole database is flushed in program order, this behaves\n * identically to `SimpleDB.run()`; call `sdb.run()` when your intent is to\n * flush the database rather than this specific table.\n *\n * @example\n * ```ts\n * // Nothing is observed after convert(), so run() executes the chain.\n * await table\n * .loadData(\"data.csv\")\n * .convert({ price: \"number\" })\n * .run();\n * await table.log();\n * ```\n * @returns A promise that resolves to the table once the queued methods have been executed.\n * @category Table Management\n */\n async run(): Promise<this> {\n await flushAllTables(this.sdb);\n return this;\n }\n\n /**\n * Renames the current table.\n * The new name must not belong to another registered table, ignoring ASCII letter case.\n *\n * @example\n * ```ts\n * // Rename the table to \"new_employees\"\n * await table.renameTable(\"new_employees\");\n * await table.log();\n * ```\n * @param name - The new name for the table.\n * @returns A promise that resolves to the renamed table.\n * @category Table Management\n */\n async renameTable(name: string): Promise<this> {\n await renameTable(this, name);\n this.#name = name;\n return this;\n }\n\n /**\n * Sets the data types for columns in a new table. If the table already exists, it will be replaced.\n * To convert the types of an existing table, use the `.convert()` method instead.\n *\n * @example\n * ```ts\n * // Set types for a new table\n * await table.setTypes({\n * name: \"string\",\n * salary: \"integer\",\n * raise: \"float\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Create an empty table with JSON, embedding, and geometry columns.\n * await table.setTypes({\n * details: \"JSON\",\n * embedding: \"FLOAT[3]\",\n * geom: \"GEOMETRY('EPSG:4326')\",\n * }).log();\n * ```\n * @param types - An object specifying the column names and their target data types (JavaScript or SQL types), including JSON, FLOAT[n] vectors, and GEOMETRY with a CRS.\n * @returns The table, so methods can be chained.\n * @category Table Management\n */\n setTypes(types: {\n [key: string]:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`;\n }): this {\n setTypes(this, types);\n return this;\n }\n\n /**\n * Loads an array of JavaScript objects into the table. Types are inferred for\n * numbers, bigints, strings, booleans, and Date values. Array and object cells\n * require an explicit supported type in columnTypes. Types can also be\n * specified for scalar columns instead of inferred from their values.\n * Inferred bigints use signed 64-bit `BIGINT`; values outside that range throw\n * when written instead of wrapping.\n *\n * JavaScript `Date` values are inferred as DuckDB `TIMESTAMP` values. Their\n * instant is preserved, but JavaScript `Date` does not retain the timezone or\n * offset originally used to construct it.\n *\n * Declare `JSON` for general nested data, `FLOAT[n]` for a fixed-size float\n * vector, or `GEOMETRY('EPSG:4326')` for GeoJSON geometries in WGS84.\n *\n * @example\n * ```ts\n * // Load scalar columns without columnTypes; strings and numbers are inferred.\n * const data = [\n * { letter: \"a\", number: 1 },\n * { letter: \"b\", number: 2 }\n * ];\n * await table.loadArray(data).log();\n * ```\n *\n * @example\n * ```ts\n * // Choose a numeric type when all-null values provide nothing to infer.\n * await table.loadArray(\n * [{ name: \"A\", value: null }, { name: \"B\", value: null }],\n * { columnTypes: { value: \"DOUBLE\" } },\n * ).log();\n * ```\n *\n * @example\n * ```ts\n * // Store the Date as a UTC timestamp with JavaScript's millisecond precision.\n * // The original -04:00 offset is not retained.\n * await table.loadArray([{\n * observedAt: new Date(\"2024-04-07T13:00:00-04:00\"),\n * }]).log();\n * ```\n *\n * @example\n * ```ts\n * // Declare JSON to load nested objects and variable-length arrays directly.\n * await table.loadArray([{\n * name: \"Station\",\n * metadata: { active: true, tags: [\"weather\", \"urban\"] },\n * measurements: [1, 2.5, null],\n * }], { columnTypes: { metadata: \"JSON\", measurements: \"JSON\" } }).log();\n * ```\n *\n * @example\n * ```ts\n * // Declare FLOAT[3] to store each three-element array as a fixed-size vector.\n * await table.loadArray([{ vector: [1, 2, 3] }], {\n * columnTypes: { vector: \"FLOAT[3]\" },\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Declare a geometry type to store WGS84 GeoJSON as a spatial column.\n * await table.loadArray([{\n * name: \"Montreal\",\n * geom: { type: \"Point\", coordinates: [-73.57, 45.50] },\n * }], { columnTypes: { geom: \"GEOMETRY('EPSG:4326')\" } }).log();\n * ```\n * @param rows - An array of objects, where each object represents a row and its properties represent columns.\n * @param options - Options for loading the array, captured when called.\n * @param options.columnTypes - Types for specific columns. Required for array and object cells; omitted scalar columns are inferred, and all-null columns default to VARCHAR. Values must be compatible with the selected type without losing information.\n * @returns The table, so methods can be chained.\n * @category Importing Data\n */\n loadArray(\n rows: { [key: string]: unknown }[],\n options: {\n columnTypes?: {\n [key: string]:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"INTEGER\"\n | \"BIGINT\"\n | \"DOUBLE\"\n | \"VARCHAR\"\n | \"BOOLEAN\"\n | \"DATE\"\n | \"TIME\"\n | \"TIMESTAMP\"\n | \"TIMESTAMP WITH TIME ZONE\"\n | \"GEOMETRY('EPSG:4326')\"\n | \"geometry('EPSG:4326')\"\n | \"JSON\"\n | \"json\"\n | `FLOAT[${number}]`\n | `float[${number}]`;\n };\n } = {},\n ): this {\n loadArray(this, rows, options);\n\n return this;\n }\n\n /**\n * Loads data from one or more local or remote files into the table.\n * Supported file formats include CSV, JSON, Parquet, and Excel.\n *\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Load data from a single local CSV file\n * await table.loadData(\"./some-data.csv\").log();\n * ```\n *\n * @example\n * ```ts\n * // Load data from a remote Parquet file\n * await table.loadData(\"https://some-website.com/some-data.parquet\").log();\n * ```\n *\n * @example\n * ```ts\n * // Load data from multiple local JSON files\n * await table.loadData([\n * \"./some-data1.json\",\n * \"./some-data2.json\",\n * \"./some-data3.json\"\n * ]).log();\n * ```\n *\n * @example\n * ```ts\n * // Load multiple CSV files and unify columns that differ between files\n * await table.loadData(\"./data/*.csv\", { unifyColumns: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Keep the source filename when loading multiple files\n * await table\n * .loadData(\"./data/*.csv\", { includeFilename: true })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Load only specific columns from a CSV file\n * await table.loadData(\"./employees.csv\", { columns: [\"name\", \"salary\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Load up to 100 matching employees, keeping only their names\n * await table\n * .loadData(\"./employees.parquet\", {\n * conditions: \"salary > 100000\",\n * columns: [\"name\"],\n * limit: 100,\n * })\n * .log();\n * ```\n * @param files - The path(s) or URL(s) of the file(s) containing the data to be loaded.\n * @param options - An optional object with configuration options:\n * @param options.fileType - The type of file to load (\"csv\", \"dsv\", \"json\", \"parquet\", \"excel\"). Defaults to being inferred from the file extension.\n * @param options.autoDetect - A boolean indicating whether to automatically detect the data format. Defaults to `true`.\n * @param options.conditions - A SQL `WHERE` clause expression, without the `WHERE` keyword, to filter source rows before applying `limit`. Can reference source columns excluded from `columns`.\n * @param options.limit - A number indicating the maximum number of matching rows to load, after applying `conditions` if provided. Defaults to all matching rows.\n * @param options.includeFilename - A boolean indicating whether to include the filename as a new column in the loaded data. Defaults to `false`.\n * @param options.unifyColumns - A boolean indicating whether to unify columns across multiple files when their structures differ. Missing columns will be filled with `NULL` values. Defaults to `false`.\n * @param options.columnTypes - An object mapping column names to their expected data types. By default, types are inferred. Geometry types are not supported; use loadGeoData() instead.\n * @param options.columns - An array of column names to load. When provided, only the specified columns are loaded, reducing memory usage and improving load times. Not supported for Excel files — combining `columns` with Excel files throws an error. If an invalid column name is provided, DuckDB will throw its native error. An empty array behaves the same as omitting the option (loads all columns). Defaults to loading all columns.\n * @param options.header - A boolean indicating whether the file has a header row. Applicable to CSV files. Defaults to `true`.\n * @param options.allText - A boolean indicating whether all columns should be treated as text. Applicable to CSV files. Defaults to `false`.\n * @param options.delim - The delimiter used in the file. Applicable to CSV and DSV files. By default, the delimiter is inferred.\n * @param options.skip - The number of lines to skip at the beginning of the file. Applicable to CSV files. Defaults to `0`.\n * @param options.nullPadding - If `true`, when a row has fewer columns than expected, the remaining columns on the right will be padded with `NULL` values. Defaults to `false`.\n * @param options.ignoreErrors - If `true`, parsing errors encountered will be ignored, and rows with errors will be skipped. Defaults to `false`.\n * @param options.compression - The compression type of the file. Applicable to CSV files. Defaults to `none`.\n * @param options.strict - If `true`, an error will be thrown when encountering any issues. If `false`, structurally incorrect files will be parsed tentatively. Defaults to `true`.\n * @param options.encoding - The encoding of the file. Applicable to CSV files. Defaults to `utf-8`.\n * @param options.jsonFormat - The format of JSON files (\"unstructured\", \"newlineDelimited\", \"array\"). By default, the format is inferred.\n * @param options.records - A boolean indicating whether each line in a newline-delimited JSON file represents a record. Applicable to JSON files. By default, it's inferred.\n * @param options.sheet - A string indicating a specific sheet to import from an Excel file. By default, the first sheet is imported.\n * @returns The table, so methods can be chained.\n * @category Importing Data\n */\n loadData(\n files: string | string[],\n options: {\n fileType?: \"csv\" | \"dsv\" | \"json\" | \"parquet\" | \"excel\";\n autoDetect?: boolean;\n conditions?: string;\n limit?: number;\n includeFilename?: boolean;\n unifyColumns?: boolean;\n columnTypes?: { [key: string]: string };\n // column selection\n columns?: string[];\n // csv options\n header?: boolean;\n allText?: boolean;\n delim?: string;\n skip?: number;\n nullPadding?: boolean;\n ignoreErrors?: boolean;\n compression?: \"none\" | \"gzip\" | \"zstd\";\n encoding?: string;\n strict?: boolean;\n // json options\n jsonFormat?: \"unstructured\" | \"newlineDelimited\" | \"array\";\n records?: boolean;\n // excel options\n sheet?: string;\n } = {},\n ): this {\n loadData(this, files, options);\n return this;\n }\n\n /**\n * Downloads a complete Statistics Canada table and loads it into this table.\n *\n * Results are cached as Parquet files in `.sda-cache/statcan` by default.\n * Cached data does not expire unless a TTL is provided.\n *\n * @example\n * ```ts\n * await sdb\n * .newTable(\"population\")\n * .loadStatCanData(\"17-10-0005-01\")\n * .filter(\"GEO = 'Canada'\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Refresh French data when the cached table is at least one day old.\n * await table\n * .loadStatCanData(\"17-10-0005\", {\n * lang: \"fr\",\n * ttl: 24 * 60 * 60,\n * })\n * .log();\n * ```\n * @param pid - The Statistics Canada Product ID. Eight-digit PIDs, ten-digit view PIDs, and hyphenated table identifiers are accepted.\n * @param options - Optional retrieval and cache settings.\n * @param options.lang - The language of the table data. Defaults to `\"en\"`.\n * @param options.cache - Whether to read and write the cache. Defaults to `true`.\n * @param options.ttl - Cache lifetime in seconds. Omit for no expiration, use `0` to refresh the matching cache entry immediately, or provide a positive value to refresh once the entry reaches that age.\n * @returns The table, so methods can be chained.\n * @category Importing Data\n */\n loadStatCanData(\n pid: string,\n options: {\n lang?: \"en\" | \"fr\";\n cache?: boolean;\n ttl?: number;\n } = {},\n ): this {\n loadStatCanData(this, pid, options);\n return this;\n }\n\n /**\n * Downloads historical market data from Yahoo Finance and loads it into this\n * table as `datetime`, `open`, `high`, `low`, `close`, `adjustedClose`, and\n * `volume` columns. `datetime` contains Yahoo's timestamps as JavaScript\n * `Date` values. Unavailable values are preserved as `null`.\n *\n * All range boundaries are evaluated in UTC. Use ISO date-time strings ending\n * in `Z`. Yahoo trading sessions may occur on a different UTC date from their\n * exchange-local date, so choose the range appropriate for the market and\n * interval. Avoid numeric constructors such as `new Date(2025, 2, 15)`, which\n * use the runtime's local timezone.\n *\n * This method uses an undocumented Yahoo Finance endpoint and is not\n * affiliated with or endorsed by Yahoo. It is provided for educational,\n * research, and journalistic purposes. Before using it, review Yahoo's terms\n * and any applicable data-provider restrictions.\n *\n * @example\n * ```ts\n * // Request daily observations using explicit UTC boundaries.\n * await table\n * .loadYahooFinanceData(\n * \"^GSPTSE\",\n * new Date(\"2025-03-01T00:00:00Z\"),\n * new Date(\"2025-03-15T00:00:00Z\"),\n * \"1d\",\n * )\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Include the UTC hours from 13:00 through 16:00.\n * await table\n * .loadYahooFinanceData(\n * \"AAPL\",\n * new Date(\"2025-03-14T13:00:00Z\"),\n * new Date(\"2025-03-14T16:00:00Z\"),\n * \"1h\",\n * )\n * .log();\n * ```\n * @param symbol - The stock or index symbol, such as `\"AAPL\"` or `\"^GSPTSE\"`.\n * @param startDate - The inclusive UTC start of the requested range.\n * @param endDate - The inclusive UTC end of the requested range. The UTC day,\n * hour, or minute containing this instant is included, according to\n * `interval`.\n * @param interval - The interval between observations: daily, hourly, or every\n * minute.\n * @returns The table, so methods can be chained.\n * @throws {RangeError} If either date is invalid or `endDate` is before `startDate`.\n * @throws {Error} If Yahoo rejects the request or returns no data.\n * @see https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html\n * @see https://help.yahoo.com/kb/finance/SLN2310.html\n * @category Importing Data\n */\n loadYahooFinanceData(\n symbol: string,\n startDate: Date,\n endDate: Date,\n interval: \"1d\" | \"1h\" | \"1m\",\n ): this {\n loadYahooFinanceData(this, symbol, startDate, endDate, interval);\n return this;\n }\n\n /**\n * Loads geospatial data from an external file or URL into the table.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Load geospatial data from a URL\n * await table.loadGeoData(\"https://some-website.com/some-data.geojson\").log();\n * ```\n *\n * @example\n * ```ts\n * // Load geospatial data from a local file\n * await table.loadGeoData(\"./some-data.geojson\").log();\n * ```\n *\n * @example\n * ```ts\n * // Load only the name and geometry columns\n * await table\n * .loadGeoData(\"./boundaries.geojson\", {\n * columns: [\"name\", \"geom\"],\n * })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Load geospatial data from a shapefile (with relevant files in the same folder) and reproject to EPSG:4326 (WGS84)\n * await table.loadGeoData(\"./some-data/some-data.shp\", { toEPSG4326: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Load geospatial data from a zipped shapefile and reproject to EPSG:4326 (WGS84)\n * await table.loadGeoData(\"./some-data.shp.zip\", { toEPSG4326: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Filter on a source property without retaining it in the table\n * await table\n * .loadGeoData(\"./boundaries.geojson\", {\n * conditions: \"population > 100000\",\n * columns: [\"name\", \"geom\"],\n * })\n * .log();\n * ```\n * @param file - The path or URL of the external file containing the geospatial data.\n * @param options - An optional object with configuration options:\n * @param options.toEPSG4326 - If `true`, the method will attempt to reproject the data to EPSG:4326 (WGS84).\n * @param options.columns - The columns to load. Include the geometry column that should remain in the resulting table, usually `\"geom\"`. By default, all columns are loaded.\n * @param options.conditions - A SQL `WHERE` clause expression, without the `WHERE` keyword, to filter source rows before materialization and reprojection. Can reference source columns excluded from `columns`. Geometry conditions use the source coordinate system.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n loadGeoData(\n file: string,\n options: {\n toEPSG4326?: boolean;\n columns?: string[];\n conditions?: string;\n } = {},\n ): this {\n loadGeoData(this, file, options);\n return this;\n }\n\n /**\n * Loads OpenStreetMap data into the table from a local `.osm` or `.osm.pbf` file, a remote file URL, or an Overpass bounding-box query. Pass a path or URL string to load an existing file, or pass a bounding box with `filters` to download matching features.\n *\n * DuckDB's [Osmium community extension](https://duckdb.org/community_extensions/extensions/osmium) materializes the complete result and reconstructs `geom` as EPSG:4326. By default, that canonical result is cached as GeoParquet in `.sda-cache/osm`. Distinct paths, local file fingerprints, normalized URLs, endpoints, queries, and bounding boxes retain independent entries. The cache has no expiration unless `ttl` is set and can be cleared by removing `.sda-cache/osm`. Immutable URLs can safely use the default indefinite cache; mutable URLs should set a TTL.\n *\n * Bounding-box filters use the standard [Overpass QL filter syntax](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Filters). Equality filters are passed as `[key, value]` tuples and serialized by the method. A raw filter fragment string can be used for advanced Overpass filters.\n *\n * The default Overpass endpoint is a shared public service. Follow the [Overpass public-instance usage guidelines](https://dev.overpass-api.de/overpass-doc/en/preface/commons.html), and configure another endpoint or run your own instance for high-volume usage.\n *\n * OpenStreetMap data is licensed under the [Open Data Commons Open Database License](https://www.openstreetmap.org/copyright). Public use requires [OpenStreetMap attribution](https://osmfoundation.org/wiki/Licence/Attribution_Guidelines), and distributing OSM or derivative databases can trigger the licence's share-alike requirements.\n *\n * @example\n * ```ts\n * // Load an existing local OpenStreetMap PBF file\n * await table.loadOpenStreetMap(\"./montreal.osm.pbf\").log();\n * ```\n *\n * @example\n * ```ts\n * // Filter and project after the complete canonical source has loaded\n * await table\n * .loadOpenStreetMap(\"./montreal.osm.pbf\", { verbose: true })\n * .filter(\"tags['amenity'] = 'school'\")\n * .selectColumns([\"id\", \"tags\", \"geom\"])\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Download features matching one equality filter within a bounding box\n * await table\n * .loadOpenStreetMap(\n * { west: -73.587799, south: 45.445078, east: -73.552265, north: 45.471086 },\n * { filters: [\"amenity\", \"school\"] },\n * )\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Download features matching either equality filter\n * await table.loadOpenStreetMap(\n * { west: -73.587799, south: 45.445078, east: -73.552265, north: 45.471086 },\n * {\n * filters: [[\"amenity\", \"school\"], [\"amenity\", \"college\"]],\n * },\n * ).log();\n * ```\n *\n * @example\n * ```ts\n * // Use a raw Overpass filter fragment for an advanced filter\n * await table.loadOpenStreetMap(\n * { west: -73.587799, south: 45.445078, east: -73.552265, north: 45.471086 },\n * { filters: `[\"amenity\"~\"school|college\"]` },\n * ).log();\n * ```\n * @param source - The local path or remote URL of an existing `.osm` or `.osm.pbf` file, or a bounding box to query through Overpass.\n * @param source.west - The western longitude, between -180 and 180 and less than `east`.\n * @param source.south - The southern latitude, between -90 and 90 and less than `north`.\n * @param source.east - The eastern longitude, between -180 and 180 and greater than `west`.\n * @param source.north - The northern latitude, between -90 and 90 and greater than `south`.\n * @param options - Loading options. When `source` is a bounding box, `options.filters` must be provided.\n * @param options.filters - For a bounding-box query, one `[key, value]` tuple or an array of tuples. Array entries are combined as a union. A raw Overpass QL filter fragment string is also accepted.\n * @param options.endpoint - The Overpass interpreter endpoint. Defaults to `https://overpass-api.de/api/interpreter`.\n * @param options.timeout - A positive integer timeout in seconds, applied to both the Overpass query and HTTP request. If omitted, the endpoint's default query timeout applies and no HTTP request timeout is set.\n * @param options.cache - Whether to read and write the processed GeoParquet cache. Defaults to `true`.\n * @param options.ttl - Cache lifetime in seconds. Omit for no expiration, use `0` to refresh the matching cache entry immediately, or provide a positive value to refresh once the processed entry reaches that age. Cannot be combined with `cache: false`.\n * @param options.retries - Additional network retries after the initial request. Defaults to `3`, for up to four attempts. Network-only; passing it for a local path throws an error.\n * @param options.retryDelay - Base retry delay in seconds. Defaults to `5`, producing deterministic delays of 5, 10, and 20 seconds. A longer valid `Retry-After` value takes precedence. Network-only; passing it for a local path throws an error.\n * @param options.verbose - Whether to log OpenStreetMap cache, network, Osmium, cleanup, and timing lifecycle details. Defaults to `false`. `SimpleDB({ cacheVerbose: true })` also enables these messages and is not overridden by `verbose: false`.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n loadOpenStreetMap(\n source:\n | string\n | {\n west: number;\n south: number;\n east: number;\n north: number;\n },\n options: {\n filters?: string | [string, string] | [string, string][];\n endpoint?: string;\n timeout?: number;\n cache?: boolean;\n ttl?: number;\n retries?: number;\n retryDelay?: number;\n verbose?: boolean;\n } = {},\n ): this {\n loadOpenStreetMap(this, source, options);\n return this;\n }\n\n /**\n * Creates a full-text search (FTS) index on a specified text column using DuckDB's [FTS extension](https://duckdb.org/docs/stable/core_extensions/full_text_search).\n *\n * If an FTS index already exists on the table, this method will skip creation and log a message (when verbose is enabled), unless the `overwrite` option is set to `true`.\n * The index definition is recorded in {@link indexes}. The {@link bm25}\n * method requires an FTS index and creates one automatically when needed.\n * DuckDB FTS indexes do not update automatically when the table changes; use\n * `overwrite: true` to rebuild the index after modifying the table.\n *\n * @example\n * ```ts\n * // Load a dataset and create an FTS index for later searches\n * await table\n * .loadData(\"recipes.parquet\")\n * .createFtsIndex(\"Dish\", \"Recipe\").log();\n * ```\n *\n * @example\n * ```ts\n * // Create an index with a specific language stemmer\n * await table.createFtsIndex(\"Dish\", \"Recipe\", {\n * stemmer: \"french\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Recreate an existing index with different settings\n * await table.createFtsIndex(\"Dish\", \"Recipe\", {\n * stemmer: \"english\",\n * overwrite: true,\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Create index with verbose logging\n * await table.createFtsIndex(\"Dish\", \"Recipe\", {\n * verbose: true,\n * }).log();\n * // Logs: 'Creating FTS index on \"Recipe\" column...'\n * // Logs: \"FTS index created successfully.\"\n * ```\n * @param idColumn - The column containing the document identifiers.\n * @param textColumn - The column containing the text to search.\n * @param options - An optional object with configuration options:\n * @param options.stemmer - The stemmer to use for the FTS index. Supports multiple languages or \"none\" to disable stemming. Defaults to \"porter\".\n * @param options.stopwords - The table containing the stopwords to use for the FTS index. Supports multiple languages or \"none\" to disable stopwords. Defaults to \"english\".\n * @param options.ignore - The regular expression of patterns to be ignored. Defaults to \"(\\\\.|[^a-z])+\".\n * @param options.stripAccents - A boolean indicating whether to remove accents. Defaults to true.\n * @param options.lower - A boolean indicating whether to convert all text to lowercase. Defaults to true.\n * @param options.overwrite - A boolean indicating whether to overwrite the existing FTS index. Defaults to false.\n * @param options.verbose - If `true`, logs FTS index creation status. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Text Search\n */\n createFtsIndex(\n idColumn: string,\n textColumn: string,\n options: {\n stemmer?:\n | \"arabic\"\n | \"basque\"\n | \"catalan\"\n | \"danish\"\n | \"dutch\"\n | \"english\"\n | \"finnish\"\n | \"french\"\n | \"german\"\n | \"greek\"\n | \"hindi\"\n | \"hungarian\"\n | \"indonesian\"\n | \"irish\"\n | \"italian\"\n | \"lithuanian\"\n | \"nepali\"\n | \"norwegian\"\n | \"porter\"\n | \"portuguese\"\n | \"romanian\"\n | \"russian\"\n | \"serbian\"\n | \"spanish\"\n | \"swedish\"\n | \"tamil\"\n | \"turkish\"\n | \"none\";\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n overwrite?: boolean;\n verbose?: boolean;\n } = {},\n ): this {\n createFtsIndex(this, idColumn, textColumn, options);\n return this;\n }\n\n /**\n * Creates a vector similarity search (VSS) index on a specified column using DuckDB's [VSS extension](https://duckdb.org/docs/stable/extensions/vss).\n *\n * If a VSS index already exists on the table, this method will skip creation and log a message (when verbose is enabled), unless the `overwrite` option is set to `true`.\n * The index definition is recorded in {@link indexes}.\n *\n * @example\n * ```ts\n * // Load data that already contains an embedding column\n * await table\n * .loadData(\"data.csv\")\n * .createVssIndex(\"embedding_column\").log();\n * ```\n *\n * @example\n * ```ts\n * // Recreate an existing index\n * await table.createVssIndex(\"embedding_column\", {\n * overwrite: true,\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Create index with verbose logging\n * await table.createVssIndex(\"embedding_column\", {\n * verbose: true,\n * }).log();\n * // Logs: 'Creating VSS index on \"embedding_column\" column...'\n * // Logs: \"VSS index created successfully.\"\n * ```\n *\n * @example\n * ```ts\n * // Create index with custom HNSW parameters for higher accuracy\n * await table.createVssIndex(\"embedding_column\", {\n * efConstruction: 256,\n * efSearch: 128,\n * M: 32,\n * }).log();\n * ```\n * @param column - The name of the column containing vector embeddings (must be FLOAT array type).\n * @param options - An optional object with configuration options:\n * @param options.overwrite - If `true`, drops and recreates the index even if it already exists. Defaults to `false`.\n * @param options.verbose - If `true`, logs VSS index creation status. Defaults to `false`.\n * @param options.efConstruction - The number of candidate vertices to consider during index construction. Higher values result in more accurate indexes but increase build time. Defaults to 128.\n * @param options.efSearch - The number of candidate vertices to consider during search. Higher values result in more accurate searches but increase search time. Defaults to 64.\n * @param options.M - The maximum number of neighbors to keep for each vertex in the graph. Higher values result in more accurate indexes but increase build time and memory usage. Defaults to 16.\n * @returns The table, so methods can be chained.\n * @category Vector Search\n */\n createVssIndex(\n column: string,\n options: {\n overwrite?: boolean;\n verbose?: boolean;\n efConstruction?: number;\n efSearch?: number;\n M?: number;\n } = {},\n ): this {\n createVssIndex(this, column, options);\n return this;\n }\n\n /**\n * Reduces numeric features, such as embeddings, to a two-dimensional UMAP\n * projection. The resulting coordinates are added as `umapX` and `umapY`,\n * while all existing columns (including the source feature columns), their\n * values and types, and the input row order are preserved. DuckDB computes\n * neighbors and the fuzzy graph; TypeScript optimizes the coordinates without\n * copying the input vectors into JavaScript. Neighbor search is selected\n * automatically.\n *\n * Accepts a numeric LIST or ARRAY column, or an array of numeric scalar column\n * names combined internally into a vector in the supplied order. Features\n * must be finite and non-null; vectors must be nonempty and equally sized.\n * Features are converted to DOUBLE without automatic scaling. Large integers\n * and exact decimals can lose precision in this conversion. If feature scales\n * differ, consider `normalize()` or `zScore()` before projection.\n *\n * The defaults are a starting point for exploration. To adjust the projection:\n *\n * - `neighbors` (default `15`): How many nearby points influence the layout.\n * Smaller values emphasize local detail but can fragment groups. Larger\n * values emphasize broader structure, can hide local detail, and generally\n * require more time and memory.\n * - `metric` (default `\"euclidean\"`): How similarity is measured. Euclidean\n * compares distance, including differences in vector magnitude. Cosine\n * compares direction, ignoring magnitude. Choose according to what makes\n * vectors similar in your data; neither is universally better.\n * - `epochs` (default `200`): How many passes refine the coordinates. Fewer\n * passes finish sooner but may leave the layout unfinished. More passes\n * allow further refinement and take longer, with diminishing returns.\n * - `minDistance` (default `0.1`): How tightly points can group in the\n * projection. Smaller values allow tighter clumps; larger values spread\n * points out. This changes the layout's appearance, not an accuracy level\n * or the number of optimization passes.\n * - `learningRate` (default `1`): The initial size of coordinate adjustments.\n * Smaller values make gentler adjustments and may need more epochs. Larger\n * values make bigger adjustments but can overshoot useful positions. This\n * does not change the number of passes.\n * - `negativeSamples` (default `5`): How many random points are sampled for\n * repulsion per attractive update. Smaller values reduce work and\n * repulsion; larger values increase both, tending to separate unrelated\n * points more strongly. More samples do not guarantee a better projection.\n *\n * @example\n * ```ts\n * await table.umap(\"embedding\", {\n * metric: \"cosine\",\n * seed: 42,\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * await table.umap(\"embedding\", {\n * neighbors: 30,\n * minDistance: 0.25,\n * }).selectColumns([\"label\", \"umapX\", \"umapY\"]).log();\n * ```\n *\n * @example\n * ```ts\n * await table\n * .umap([\"height\", \"weight\", \"age\"], { seed: 42 })\n * .log();\n * ```\n * @param columns - A numeric vector column name, or a nonempty array of numeric scalar column names in feature order. Use a one-element array for a single scalar feature.\n * @param options - Optional projection settings.\n * @param options.neighbors - Neighborhood size, including the point itself. Integer of at least 2, clamped to row count minus one. Defaults to 15.\n * @param options.metric - Input distance metric: \"euclidean\" or \"cosine\". Defaults to \"euclidean\".\n * @param options.epochs - Integer number of refinement passes, at least 1. Defaults to 200.\n * @param options.seed - Integer used to initialize random choices. Defaults to 42.\n * @param options.minDistance - Grouping distance parameter between 0 and 1. Defaults to 0.1.\n * @param options.learningRate - Finite, positive initial learning rate. Defaults to 1.\n * @param options.negativeSamples - Integer number of samples used to separate unrelated points, at least 1. Defaults to 5.\n * @returns The table, so methods can be chained.\n * @category Vector Search\n */\n umap(\n columns: string | string[],\n options: {\n neighbors?: number;\n metric?: \"euclidean\" | \"cosine\";\n epochs?: number;\n seed?: number;\n minDistance?: number;\n learningRate?: number;\n negativeSamples?: number;\n } = {},\n ): this {\n umap(this, columns, options);\n return this;\n }\n\n /**\n * Groups rows with similar numeric features using HDBSCAN, without requiring\n * a predefined number of clusters. Adds a VARCHAR column containing\n * `\"cluster-0\"`, `\"cluster-1\"`, etc., or `\"noise\"` for rows outside clusters.\n * Labels identify groups, not their rank.\n *\n * Accepts a numeric vector column or several numeric scalar columns. Features\n * are used as supplied. If their scales differ, consider preparing them with\n * `normalize()`, `zScore()`, or `normalizeVector()` before clustering.\n *\n * Exact clustering is the default and can be expensive for large datasets.\n * Set `approximate: true` to use approximate clustering, which can produce\n * different results, including between repeated runs.\n *\n * @example\n * ```ts\n * // Cluster numeric columns and add membership and outlier scores.\n * await table\n * .hdbscan([\"height\", \"weight\"], \"cluster\", {\n * minClusterSize: 5,\n * membershipScoreColumn: \"membership\",\n * outlierScoreColumn: \"outlierScore\",\n * })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Scale vector dimensions before clustering.\n * await table\n * .normalizeVector(\"features\", \"scaledFeatures\")\n * .hdbscan(\"scaledFeatures\", \"cluster\")\n * .log();\n * ```\n * @param columns - A numeric vector column, or numeric scalar columns in\n * feature-dimension order.\n * @param newColumn - The cluster-label column to create.\n * @param options - HDBSCAN clustering and output settings.\n * @param options.minClusterSize - Minimum cluster size, from `2` through the\n * row count. Defaults to `5`.\n * @param options.minSamples - Number of neighbors used to estimate local\n * density, excluding the point itself. Higher values make clustering more\n * conservative, generally labeling more rows as noise. Set this separately\n * to adjust density sensitivity independently of minimum cluster size.\n * Defaults to `minClusterSize`.\n * @param options.metric - Use `\"euclidean\"` to compare feature values, or\n * `\"cosine\"` to compare vector direction regardless of overall magnitude.\n * Defaults to `\"euclidean\"`.\n * @param options.allowSingleCluster - Allow a result with just one cluster,\n * possibly alongside noise. Defaults to `false`. Setting this to `true` can\n * favor one broad group, even when there is little meaningful structure.\n * @param options.approximate - Use approximate clustering. Defaults to `false`.\n * @param options.membershipScoreColumn - Optional DOUBLE column for membership\n * strength from `0` to `1`. Higher values indicate stronger membership in the\n * assigned cluster; noise scores `0`.\n * @param options.outlierScoreColumn - Optional DOUBLE column for outlier\n * scores from `0` to `1`. Higher values indicate more unusual rows relative to\n * their surroundings, including within clusters. This is not necessarily\n * `1 - membershipScore`.\n * @returns The table, so methods can be chained.\n * @category Vector Search\n */\n hdbscan(\n columns: string | string[],\n newColumn: string,\n options: {\n minClusterSize?: number;\n minSamples?: number;\n metric?: \"euclidean\" | \"cosine\";\n allowSingleCluster?: boolean;\n approximate?: boolean;\n membershipScoreColumn?: string;\n outlierScoreColumn?: string;\n } = {},\n ): this {\n hdbscan(this, columns, newColumn, options);\n return this;\n }\n\n /**\n * Searches a text column using DuckDB's BM25 ranking function, which scores\n * matches using factors including term frequency and document length.\n *\n * This method creates the required index with DuckDB's [FTS extension](https://duckdb.org/docs/stable/core_extensions/full_text_search).\n * It reuses the table's existing FTS index unless `overwriteIndex` is `true`.\n * DuckDB FTS indexes do not update automatically when the source table\n * changes; use `overwriteIndex: true` to rebuild the index after modifying\n * the table.\n *\n * @example\n * ```ts\n * // Load a dataset of recipes\n * const dishes = await table\n * .loadData(\"recipes.parquet\")\n * .bm25(\"italian food\", \"Dish\", \"Recipe\", 5)\n * .log();\n * // Logs the five most relevant dishes.\n * ```\n *\n * @example\n * ```ts\n * // Search with a specific language stemmer\n * await table.bm25(\"french food\", \"Dish\", \"Recipe\", 5, {\n * stemmer: \"french\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Recreate the index with different settings and perform search\n * await table.bm25(\"italian food\", \"Dish\", \"Recipe\", 5, {\n * stemmer: \"english\",\n * overwriteIndex: true,\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Save results to a new table without modifying the original\n * const italianDishes = await table.bm25(\"italian food\", \"Dish\", \"Recipe\", 5, {\n * outputTable: \"italian_results\",\n * }).log();\n *\n * // Original table remains unchanged\n * const allDishes = await table.getValues(\"Dish\");\n * console.log(allDishes.length); // 336 (all dishes)\n *\n * // New table contains only search results\n * const italianOnly = await italianDishes.getValues(\"Dish\");\n * console.log(italianOnly.length); // 5 (top results)\n * ```\n *\n * @example\n * ```ts\n * // Multiple searches reuse the same index for better performance\n * // The first search creates the index\n * const italian = await table.bm25(\"italian food\", \"Dish\", \"Recipe\", 5, {\n * outputTable: \"italian\",\n * }).log();\n *\n * // The second search reuses the existing index, so it's faster\n * const french = await table.bm25(\"french food\", \"Dish\", \"Recipe\", 5, {\n * outputTable: \"french\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Filter results by a minimum BM25 score and include the score in the output\n * await table.bm25(\"spicy noodles\", \"Dish\", \"Recipe\", 10, {\n * minScore: 5.5,\n * scoreColumn: \"bm25_score\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Use the conjunctive option to require all terms\n * await table.bm25(\"italian sauce\", \"Dish\", \"Recipe\", 5, {\n * conjunctive: true,\n * }).log();\n * ```\n * @param text - The search query text to match against the text column.\n * @param idColumn - The name of the column containing unique identifiers for each row.\n * @param textColumn - The name of the column containing the text to search.\n * @param count - The number of top-ranked results to return.\n * @param options - An optional object with configuration options:\n * @param options.outputTable - The name of a new table where the results will be stored. If not provided, the current table will be replaced with the search results.\n * @param options.verbose - If `true`, logs FTS index creation status. Defaults to `false`.\n * @param options.k - The BM25 k parameter controlling term frequency saturation. Defaults to 1.2.\n * @param options.b - The BM25 b parameter controlling document length normalization (0-1 range). Defaults to 0.75.\n * @param options.stemmer - The language stemmer to apply for word normalization. Supports multiple languages or \"none\" to disable stemming. Defaults to 'porter'.\n * @param options.stopwords - The table containing the stopwords to use for the FTS index. Supports multiple languages or \"none\" to disable stopwords. Defaults to \"english\".\n * @param options.ignore - The regular expression of patterns to be ignored. Defaults to \"(\\\\.|[^a-z])+\".\n * @param options.stripAccents - A boolean indicating whether to remove accents. Defaults to true.\n * @param options.lower - A boolean indicating whether to convert all text to lowercase. Defaults to true.\n * @param options.overwriteIndex - If `true`, drops and recreates the FTS index even if it already exists. Defaults to `false`.\n * @param options.conjunctive - If `true`, all terms in the query string must be present in order for a document to be retrieved. Defaults to `false`.\n * @param options.minScore - A threshold to filter out results with a BM25 score below this value.\n * @param options.scoreColumn - If provided, the BM25 score will be included in the output table under this column name.\n * @returns A table instance containing the search results, ordered by relevance (best matches first), so methods can be chained.\n * @category Text Search\n */\n bm25(\n text: string,\n idColumn: string,\n textColumn: string,\n count: number,\n options: {\n outputTable?: string;\n verbose?: boolean;\n k?: number;\n b?: number;\n stemmer?:\n | \"arabic\"\n | \"basque\"\n | \"catalan\"\n | \"danish\"\n | \"dutch\"\n | \"english\"\n | \"finnish\"\n | \"french\"\n | \"german\"\n | \"greek\"\n | \"hindi\"\n | \"hungarian\"\n | \"indonesian\"\n | \"irish\"\n | \"italian\"\n | \"lithuanian\"\n | \"nepali\"\n | \"norwegian\"\n | \"porter\"\n | \"portuguese\"\n | \"romanian\"\n | \"russian\"\n | \"serbian\"\n | \"spanish\"\n | \"swedish\"\n | \"tamil\"\n | \"turkish\"\n | \"none\";\n stopwords?: string;\n ignore?: string;\n stripAccents?: boolean;\n lower?: boolean;\n overwriteIndex?: boolean;\n conjunctive?: boolean;\n minScore?: number;\n scoreColumn?: string;\n } = {},\n ): this {\n return bm25(this, text, idColumn, textColumn, count, options) as this;\n }\n\n /**\n * Inserts rows, provided as an array of JavaScript objects, into the table.\n *\n * @example\n * ```ts\n * // Insert new rows into the table\n * const newRows = [\n * { letter: \"c\", number: 3 },\n * { letter: \"d\", number: 4 }\n * ];\n * await table.insertRows(newRows).log();\n * ```\n * @param rows - An array of objects, where each object represents a row to be inserted and its properties correspond to column names.\n * @returns The table, so methods can be chained.\n * @category Importing Data\n */\n insertRows(rows: { [key: string]: unknown }[]): this {\n insertRows(this, rows);\n return this;\n }\n\n /**\n * Inserts all rows from one or more other tables into this table. If tables do not have the same columns, an error will be thrown unless the `unifyColumns` option is set to `true`.\n *\n * @example\n * ```ts\n * // Insert all rows from 'tableB' into 'tableA'.\n * await tableA.insertTables(\"tableB\").log();\n * ```\n *\n * @example\n * ```ts\n * // Insert all rows from 'tableB' and 'tableC' into 'tableA'.\n * await tableA.insertTables([\"tableB\", \"tableC\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Insert rows from multiple tables, unifying columns. Missing columns will be filled with NULL.\n * await tableA.insertTables([\"tableB\", \"tableC\"], { unifyColumns: true }).log();\n * ```\n * @param tables - The name(s) of the table(s) or SimpleTable instance(s) from which rows will be inserted.\n * @param options - An optional object with configuration options:\n * @param options.unifyColumns - A boolean indicating whether to unify the columns of the tables. If `true`, missing columns in a table will be filled with `NULL` values. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Importing Data\n */\n insertTables(\n tables: SimpleTable | SimpleTable[],\n options: { unifyColumns?: boolean } = {},\n ): this {\n insertTables(this, tables, options);\n return this;\n }\n\n /**\n * Fetches sample data from the simple-data-analysis-core GitHub repository.\n *\n * @example\n * ```ts\n * // Load the fires sample data\n * await table.loadSample(\"fires\").log();\n * ```\n * @param sample - The name of the sample to load.\n *\n * Tabular data:\n * - \"fires\": [firesCanada2023.csv](https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/firesCanada2023.csv)\n * - \"recipes\": [recipes.parquet](https://github.com/nshiab/simple-data-analysis-core/raw/refs/heads/main/test/data/files/recipes.parquet)\n * - \"temperatures\": [dailyTemperatures.csv](https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/data/files/dailyTemperatures.csv)\n * - \"temperaturesCities\": [cities.csv](https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/data/files/cities.csv)\n *\n * Geospatial data:\n * - \"canada\": [CanadianProvincesAndTerritories.json](https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/CanadianProvincesAndTerritories.json)\n * - \"firesGeo\": [firesCanada2023.geojson](https://raw.githubusercontent.com/nshiab/simple-data-analysis-core/refs/heads/main/test/geodata/files/firesCanada2023.geojson)\n *\n * @category Importing Data\n */\n loadSample(\n sample: \"fires\" | \"recipes\" | \"temperatures\" | \"temperaturesCities\" | \"canada\" | \"firesGeo\",\n ): this {\n return loadSample(this, sample) as this;\n }\n\n /**\n * Returns a new table with the same structure and data as this table. The data can be optionally filtered, limited to a specific number of rows, and offset.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * If `conditions`, `limit`, and `offset` are all used, they are applied in this order: `conditions` (WHERE clause) first, then `offset`, and finally `limit` (LIMIT).\n *\n * Note that cloning large tables can be a slow operation.\n *\n * @example\n * ```ts\n * // Clone tableA to a new table with a default generated name (e.g., \"table1\")\n * const tableB = await tableA.clone().log();\n * ```\n *\n * @example\n * ```ts\n * // Clone tableA to a new table named \"my_cloned_table\" using string parameter\n * const tableB = await tableA.clone(\"my_cloned_table\").log();\n * ```\n *\n * @example\n * ```ts\n * // Clone tableA to a new table named \"my_cloned_table\" using options object\n * const tableB = await tableA.clone({ name: \"my_cloned_table\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone tableA, including only rows where 'column1' is greater than 10\n * const tableB = await tableA.clone({ conditions: `column1 > 10` }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone tableA with only specific columns\n * const tableB = await tableA.clone({ columns: [\"name\", \"age\", \"city\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone only the first 10 rows of tableA\n * const tableB = await tableA.clone({ limit: 10 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone 10 rows after skipping the first 5 rows\n * const tableB = await tableA.clone({ limit: 10, offset: 5 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone tableA to a specific table name with filtered data, specific columns, and limited rows\n * const tableB = await tableA.clone({\n * name: \"filtered_data\",\n * conditions: `status = 'active' AND created_date >= '2023-01-01'`,\n * columns: [\"name\", \"status\", \"created_date\"],\n * limit: 100\n * }).log();\n * ```\n * @param nameOrOptions - Either a string specifying the name of the new table, or an optional object with configuration options. If not provided, a default name (e.g., \"table1\", \"table2\") will be generated.\n * @param nameOrOptions.name - The name of the new table to be created in the database. If not provided, a default name (e.g., \"table1\", \"table2\") will be generated.\n * @param nameOrOptions.conditions - A SQL `WHERE` clause condition to filter the data during cloning. Defaults to no condition (clones all rows).\n * @param nameOrOptions.columns - An array of column names to include in the cloned table. If not provided, all columns will be included.\n * @param nameOrOptions.limit - The number of rows to include in the cloned table. If provided, only the first X rows (potentially after filtering and offset) will be cloned.\n * @param nameOrOptions.offset - The number of rows to skip before starting to clone rows.\n * @returns A new table instance containing the cloned data, so methods can be chained.\n * @category Table Management\n */\n clone(\n nameOrOptions:\n | string\n | {\n name?: string;\n conditions?: string;\n columns?: string | string[];\n limit?: number;\n offset?: number;\n } = {},\n ): this {\n return clone(this, nameOrOptions) as this;\n }\n\n /**\n * Clones an existing column in this table, creating a new column with identical values.\n *\n * @example\n * ```ts\n * // Clone 'firstName' column as 'contactName'\n * await table.cloneColumn(\"firstName\", \"contactName\").log();\n * ```\n * @param column - The name of the original column to clone.\n * @param newColumn - The name of the new column to be created.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n cloneColumn(column: string, newColumn: string): this {\n cloneColumn(this, column, newColumn);\n return this;\n }\n\n /**\n * Clones a column in the table and offsets its values by a specified number of rows.\n * This is useful for time-series analysis or comparing values across different time points.\n *\n * **Important:** The offset is applied based on the current row order in the table. For meaningful results, ensure your data is sorted appropriately (e.g., by date/time for time-series analysis) before calling this method.\n *\n * @example\n * ```ts\n * // Clone 'value' as 'previous_value', offsetting by 1 row (value of row N-1 goes to row N)\n * await table.cloneColumnWithOffset(\"value\", \"previous_value\").log();\n * ```\n *\n * @example\n * ```ts\n * // Clone 'sales' as 'sales_2_days_ago', offsetting by 2 rows\n * await table.cloneColumnWithOffset(\"sales\", \"sales_2_days_ago\", { offset: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone 'temperature' as 'prev_temp_by_city', offsetting by 1 row within each 'city' category\n * await table.cloneColumnWithOffset(\"temperature\", \"prev_temp_by_city\", {\n * offset: 1,\n * by: \"city\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Clone 'stock_price' as 'prev_price_by_stock_and_exchange', offsetting by 1 row within each 'stock_symbol' and 'exchange' category\n * await table.cloneColumnWithOffset(\"stock_price\", \"prev_price_by_stock_and_exchange\", {\n * offset: 1,\n * by: [\"stock_symbol\", \"exchange\"],\n * }).log();\n * ```\n * @param column - The name of the original column.\n * @param newColumn - The name of the new column to be created with offset values.\n * @param options - An optional object with configuration options:\n * @param options.offset - The number of rows to offset the values. A positive number shifts values downwards (later rows), a negative number shifts values upwards (earlier rows). Defaults to `1`.\n * @param options.by - A column name or an array of column names to partition by. The offset is applied independently within each group.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n cloneColumnWithOffset(\n column: string,\n newColumn: string,\n options: {\n offset?: number;\n by?: string | string[];\n } = {},\n ): this {\n cloneColumnWithOffset(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Fills `NULL` values in specified columns. By default, each `NULL` is replaced with the last non-`NULL` value from the preceding row. When `interpolate` is `true`, `NULL` values are replaced using linear interpolation (or extrapolation at the ends). Pass `interpolateBy` with a real numeric or date column name to use it as the X-axis, so that interpolated values are proportional to the actual distances between X-axis values rather than treating every row as equidistant. When `interpolateBy` is set, `interpolate` is automatically assumed `true`.\n *\n * @example\n * ```ts\n * // Fill NULL values in 'column1' with the previous non-NULL value\n * await table.fill(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Fill NULL values in multiple columns\n * await table.fill([\"columnA\", \"columnB\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Fill NULL values in 'value' independently within each 'group'\n * await table.fill(\"value\", { by: \"group\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Fill NULL values in 'value' using linear interpolation\n * await table.fill(\"value\", { interpolate: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Fill NULL values in 'value' using linear interpolation, independently within each 'group'\n * await table.fill(\"value\", { by: \"group\", interpolate: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Fill NULL values in 'value' using linear interpolation proportional to 'x' distances\n * await table.fill(\"value\", { interpolate: true, interpolateBy: \"x\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // interpolateBy implies interpolate: true, so this is equivalent to the previous example\n * await table.fill(\"value\", { interpolateBy: \"x\" }).log();\n * ```\n * @param columns - The column(s) for which to fill `NULL` values.\n * @param options - An optional object with configuration options:\n * @param options.by - A column name or an array of column names to partition by. The fill is applied independently within each group.\n * @param options.interpolate - If `true`, replaces `NULL` values with linearly interpolated values using DuckDB's `fill()` window function. When `interpolateBy` is not set, row positions are used as the X-axis, treating rows as equidistant. For `NULL` values at the ends, linear extrapolation is used. Both the column values and the X-axis values must support arithmetic. If `false` or omitted, the previous non-`NULL` value is used instead. Automatically assumed `true` when `interpolateBy` is set.\n * @param options.interpolateBy - A column name to use as the X-axis for interpolation instead of equidistant row positions. When provided, `interpolate` is automatically assumed `true`. Use this when rows are not evenly spaced (e.g., timestamps or non-uniform numeric indices) so that interpolated values are proportional to the actual distance between X-axis values.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n fill(\n columns: string | string[],\n options: {\n by?: string | string[];\n interpolate?: boolean;\n interpolateBy?: string;\n } = {},\n ): this {\n fill(this, columns, options);\n return this;\n }\n\n /**\n * Sorts the rows of the table based on specified column(s) and order(s).\n * If no columns are specified, all columns are sorted from left to right in ascending order.\n *\n * Order-preserving transformations after a sort retain that order. Operations such as joins, grouping, aggregation, and sampling do not guarantee input order; chain `sort()` after them when deterministic output order matters.\n *\n * @example\n * ```ts\n * // Sort all columns from left to right in ascending order\n * await table.sort().log();\n * ```\n *\n * @example\n * ```ts\n * // Sort 'column1' in ascending order\n * await table.sort({ column1: \"asc\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Sort 'column1' ascendingly, then 'column2' descendingly\n * await table.sort({ column1: \"asc\", column2: \"desc\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Sort 'column1' considering French accents\n * await table.sort({ column1: \"asc\" }, { lang: { column1: \"fr\" } }).log();\n * ```\n * @param order - An object mapping column names to their sorting order: `\"asc\"` for ascending or `\"desc\"` for descending. If `null`, all columns are sorted ascendingly.\n * @param options - An optional object with configuration options:\n * @param options.lang - An object mapping column names to language codes for collation (e.g., `{ column1: \"fr\" }`). See DuckDB Collations documentation for more details: https://duckdb.org/docs/sql/expressions/collations.\n * @returns The table, so methods can be chained.\n * @category Restructuring Data\n */\n sort(\n order: { [key: string]: \"asc\" | \"desc\" } | null = null,\n options: {\n lang?: { [key: string]: string };\n } = {},\n ): this {\n sort(this, order, options);\n return this;\n }\n\n /**\n * Selects specific columns in the table, removing all others.\n *\n * @example\n * ```ts\n * // Select only the 'firstName' and 'lastName' columns, removing all other columns.\n * await table.selectColumns([\"firstName\", \"lastName\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Select only the 'productName' column.\n * await table.selectColumns(\"productName\").log();\n * ```\n * @param columns - The name or an array of names of the columns to be selected.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n selectColumns(columns: string | string[]): this {\n selectColumns(this, columns);\n return this;\n }\n\n /**\n * Skips the first `n` rows of the table, effectively removing them.\n *\n * @example\n * ```ts\n * // Skip the first 10 rows of the table\n * await table.skip(10).log();\n * ```\n * @param count - The number of rows to skip from the beginning of the table.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n skip(count: number): this {\n skip(this, count);\n return this;\n }\n\n /**\n * Checks if a column with the specified name exists in the table.\n *\n * @example\n * ```ts\n * // Check if the table has a column named \"age\"\n * const hasAgeColumn = await table.hasColumn(\"age\");\n * console.log(hasAgeColumn); // Output: true or false\n * ```\n * @param column - The name of the column to check.\n * @returns A promise that resolves to `true` if the column exists, `false` otherwise.\n * @category Column Operations\n */\n async hasColumn(column: string): Promise<boolean> {\n const columns = await this.getColumns();\n return columns.includes(column);\n }\n\n /**\n * Selects random rows from the table, removing all others. You can optionally specify a seed to ensure repeatable sampling.\n *\n * @example\n * ```ts\n * // Select 100 random rows from the table\n * await table.sample(100).log();\n * ```\n *\n * @example\n * ```ts\n * // Select 10% of the rows randomly\n * await table.sample(\"10%\").log();\n * ```\n *\n * @example\n * ```ts\n * // Select random rows with a specific seed for repeatable results\n * await table.sample(\"10%\", { seed: 123 }).log();\n * ```\n * @param count - The number of rows to select (e.g., `100`) or a percentage string (e.g., `\"10%\"`) specifying the sampling size.\n * @param options - An optional object with configuration options:\n * @param options.seed - A number specifying the seed for repeatable sampling. Using the same seed will always yield the same random rows. Defaults to a random seed.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n sample(\n count: number | string,\n options: {\n seed?: number;\n } = {},\n ): this {\n sample(this, count, options);\n return this;\n }\n\n /**\n * Selects a specified number of rows from this table. An offset can be applied to skip initial rows, and the results can be output to a new table.\n *\n * @example\n * ```ts\n * // Select the first 100 rows of the current table\n * await table.selectRows(100).log();\n * ```\n *\n * @example\n * ```ts\n * // Select 100 rows after skipping the first 50 rows\n * await table.selectRows(100, { offset: 50 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Select 50 rows and store them in a new table with a generated name\n * const newTable = await table.selectRows(50, { outputTable: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Select 75 rows and store them in a new table named \"top_customers\"\n * const topCustomersTable = await table.selectRows(75, { outputTable: \"top_customers\" }).log();\n * ```\n * @param count - The number of rows to select.\n * @param options - An optional object with configuration options:\n * @param options.offset - The number of rows to skip from the beginning of the table before selecting. Defaults to `0`.\n * @param options.outputTable - If `true`, the selected rows will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be modified. Defaults to `false`.\n * @returns A table instance containing the selected rows (either the current table or a new table), so methods can be chained.\n * @category Selecting or Filtering Data\n */\n selectRows(\n count: number | string,\n options: { offset?: number; outputTable?: string | boolean } = {},\n ): this {\n return selectRows(this, count, options) as this;\n }\n\n /**\n * Removes duplicate rows from this table, keeping only unique rows.\n * Note that the resulting data order might differ from the original.\n *\n * @example\n * ```ts\n * // Remove duplicate rows based on all columns\n * await table.removeDuplicates().log();\n * ```\n *\n * @example\n * ```ts\n * // Remove duplicate rows based only on the 'email' column\n * await table.removeDuplicates({ on: \"email\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove duplicate rows based on 'firstName' and 'lastName' columns\n * await table.removeDuplicates({ on: [\"firstName\", \"lastName\"] }).log();\n * ```\n * @param options - An optional object with configuration options:\n * @param options.on - A column name or an array of column names to consider when identifying duplicates. If specified, duplicates are determined based only on the values in these columns. If omitted, all columns are considered.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n removeDuplicates(\n options: {\n on?: string | string[];\n } = {},\n ): this {\n removeDuplicates(this, options);\n return this;\n }\n\n /**\n * Removes rows with missing values from this table.\n * By default, missing values include SQL `NULL`, as well as string representations like `\"NULL\"`, `\"null\"`, `\"NaN\"`, `\"undefined\"`, and empty strings `\"\"`.\n *\n * @example\n * ```ts\n * // Remove rows with missing values in any column\n * await table.removeMissing().log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows with missing values only in 'firstName' or 'lastName' columns\n * await table.removeMissing({ columns: [\"firstName\", \"lastName\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Keep only rows with missing values in any column\n * await table.removeMissing({ invert: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'age' is missing or is equal to -1\n * await table.removeMissing({ columns: \"age\", missingValues: [-1] }).log();\n * ```\n * @param options - An optional object with configuration options:\n * @param options.columns - A string or an array of strings specifying the columns to consider for missing values. If omitted, all columns are considered.\n * @param options.missingValues - An array of values to be treated as missing values instead of the default ones. Defaults to `[\"undefined\", \"NaN\", \"null\", \"NULL\", \"\"]`.\n * @param options.invert - A boolean indicating whether to invert the condition. If `true`, only rows containing missing values will be kept. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n removeMissing(\n options: {\n columns?: string | string[];\n missingValues?: (string | number)[];\n invert?: boolean;\n } = {},\n ): this {\n removeMissing(this, options);\n return this;\n }\n\n /**\n * Trims specified characters from the beginning, end, or both sides of string values in the given columns.\n * Pass `\"all\"` to trim every string (VARCHAR) column, leaving other types unchanged.\n * If there are no string columns, `\"all\"` leaves the table unchanged.\n * Use `[\"all\"]` to trim a column literally named `all`.\n *\n * @example\n * ```ts\n * // Trim whitespace from 'column1'\n * await table.trim(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Trim whitespace from every string column\n * await table.trim(\"all\").log();\n * ```\n *\n * @example\n * ```ts\n * // Trim leading and trailing asterisks from 'productCode'\n * await table.trim(\"productCode\", { character: \"*\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Right-trim whitespace from 'description' and 'notes' columns\n * await table.trim([\"description\", \"notes\"], { side: \"right\" }).log();\n * ```\n * @param columns - The column name, an array of column names, or `\"all\"` to trim every string (VARCHAR) column.\n * @param options - An optional object with configuration options:\n * @param options.character - The string to trim. Defaults to whitespace characters.\n * @param options.side - The side to trim: `\"left\"` (removes from the beginning), `\"right\"` (removes from the end), or `\"both\"` (removes from both sides). Defaults to `\"both\"`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n trim(\n columns: string | string[],\n options: {\n character?: string;\n side?: \"left\" | \"right\" | \"both\";\n } = {},\n ): this {\n trim(this, columns, options);\n return this;\n }\n\n /**\n * Filters rows from this table based on SQL conditions. Note that it's often faster to use the `removeRows` method for simple removals.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Keep only rows where the 'fruit' column is not 'apple'\n * await table.filter(`fruit != 'apple'`).log();\n * ```\n *\n * @example\n * ```ts\n * // Keep rows where 'price' is greater than 100 AND 'quantity' is greater than 0\n * await table.filter(`price > 100 && quantity > 0`).log(); // Using JS syntax\n * ```\n *\n * @example\n * ```ts\n * // Keep rows where 'category' is 'Electronics' OR 'Appliances'\n * await table.filter(`category === 'Electronics' || category === 'Appliances'`).log(); // Using JS syntax\n * ```\n *\n * @example\n * ```ts\n * // Keep rows where 'lastPurchaseDate' is on or after '2023-01-01'\n * await table.filter(`lastPurchaseDate >= '2023-01-01'`).log();\n * ```\n * @param conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"column1 > 10 AND column2 = 'value'\"`).\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n filter(conditions: string): this {\n filter(this, conditions);\n return this;\n }\n\n /**\n * Keeps rows in this table that have specific values in specified columns, removing all other rows.\n *\n * @example\n * ```ts\n * // Keep only rows where 'job' is 'accountant' or 'developer', AND 'city' is 'Montreal'\n * await table.keepValues({ job: [\"accountant\", \"developer\"], city: \"Montreal\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Keep only rows where 'status' is 'active'\n * await table.keepValues({ status: \"active\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Keep only rows where 'status' is NULL\n * await table.keepValues({ status: null }).log();\n * ```\n * @param columnsAndValues - An object where keys are column names and values are the specific values (or an array of values) to keep in those columns. Use `null` to keep rows where a column is `NULL`.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n keepValues(columnsAndValues: { [key: string]: unknown }): this {\n keepValues(this, columnsAndValues);\n return this;\n }\n\n /**\n * Removes rows from this table that have specific values in specified columns.\n *\n * @example\n * ```ts\n * // Remove rows where 'job' is 'accountant' or 'developer', AND 'city' is 'Montreal'\n * await table.removeValues({ job: [\"accountant\", \"developer\"], city: \"Montreal\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'status' is 'inactive'\n * await table.removeValues({ status: \"inactive\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'status' is NULL\n * await table.removeValues({ status: null }).log();\n * ```\n * @param columnsAndValues - An object where keys are column names and values are the specific values (or an array of values) to remove from those columns. Use `null` to remove rows where a column is `NULL`; otherwise, `NULL` rows are retained.\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n removeValues(columnsAndValues: { [key: string]: unknown }): this {\n removeValues(this, columnsAndValues);\n return this;\n }\n\n /**\n * Removes rows from this table based on SQL conditions. This method is similar to `filter()`, but removes rows instead of keeping them.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Remove rows where the 'fruit' column is 'apple'\n * await table.removeRows(`fruit = 'apple'`).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'quantity' is less than 5\n * await table.removeRows(`quantity < 5`).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'price' is less than 100 AND 'quantity' is 0\n * await table.removeRows(`price < 100 && quantity === 0`).log(); // Using JS syntax\n * ```\n *\n * @example\n * ```ts\n * // Remove rows where 'category' is 'Electronics' OR 'Appliances'\n * await table.removeRows(`category === 'Electronics' || category === 'Appliances'`).log(); // Using JS syntax\n * ```\n * @param conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"fruit = 'apple'\"`).\n * @returns The table, so methods can be chained.\n * @category Selecting or Filtering Data\n */\n removeRows(conditions: string): this {\n removeRows(this, conditions);\n return this;\n }\n\n /**\n * Renames one or more columns in the table. Throws if a source column does\n * not exist, so a typo fails loudly instead of being silently ignored.\n *\n * @example\n * ```ts\n * // Rename \"How old?\" to \"age\" and \"Man or woman?\" to \"sex\"\n * await table.renameColumns({ \"How old?\": \"age\", \"Man or woman?\": \"sex\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Rename a single column\n * await table.renameColumns({ \"product_id\": \"productId\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Skip the existence check when renaming across many tables\n * await table.renameColumns({ \"product_id\": \"productId\" }, { strict: false }).log();\n * ```\n * @param names - An object mapping old column names to their new column names (e.g., `{ \"oldName\": \"newName\", \"anotherOld\": \"anotherNew\" }`).\n * @param options - Configuration options.\n * @param options.strict - Whether to verify the source columns exist before renaming. Defaults to `true`. Set to `false` to skip the check and its schema lookup when you know the columns exist and are renaming across many tables where the extra round-trip adds up.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n renameColumns(names: { [key: string]: string }, options: { strict?: boolean } = {}): this {\n renameColumns(this, names, options);\n return this;\n }\n\n /**\n * Cleans column names by removing non-alphanumeric characters and formatting them to camel case.\n *\n * @example\n * ```ts\n * // Clean all column names in the table\n * // e.g., \"First Name\" becomes \"firstName\", \"Product ID\" becomes \"productId\"\n * await table.cleanColumnNames().log();\n * ```\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n cleanColumnNames(): this {\n queueOp(this, {\n kind: \"fusable\",\n method: \"cleanColumnNames()\",\n parameters: {},\n // The schema provides the column names to clean.\n needsSchema: true,\n buildSelect: (input, schema) =>\n `SELECT * RENAME (${Object.keys(schema)\n .map((col) => `${quoteIdentifier(col)} AS ${quoteIdentifier(camelCase(col))}`)\n .join(\", \")}) FROM ${input}`,\n });\n return this;\n }\n\n /**\n * Restructures this table by stacking (unpivoting) columns. This is useful for tidying up data from a wide format to a long format.\n *\n * For example, given a table showing employee counts per department per year:\n *\n * | Department | 2021 | 2022 | 2023 |\n * | :--------- | :--- | :--- | :--- |\n * | Accounting | 10 | 9 | 15 |\n * | Sales | 52 | 75 | 98 |\n *\n * We can restructure it by putting all year columns into a new column named `Year` and their corresponding employee counts into a new column named `Employees`.\n *\n * @example\n * ```ts\n * // Restructure the table by stacking year columns into 'year' and 'employees'\n * await table.longer([\"2021\", \"2022\", \"2023\"], \"year\", \"employees\").log();\n * ```\n *\n * The table will then look like this:\n *\n * | Department | Year | Employees |\n * | :--------- | :--- | :-------- |\n * | Accounting | 2021 | 10 |\n * | Accounting | 2022 | 9 |\n * | Accounting | 2023 | 15 |\n * | Sales | 2021 | 52 |\n * | Sales | 2022 | 75 |\n * | Sales | 2023 | 98 |\n *\n * @param columns - An array of strings representing the names of the columns to be stacked (unpivoted).\n * @param namesTo - The name of the new column that will contain the original column names (e.g., \"Year\").\n * @param valuesTo - The name of the new column that will contain the values from the stacked columns (e.g., \"Employees\").\n * @returns The table, so methods can be chained.\n * @category Restructuring Data\n */\n longer(columns: string[], namesTo: string, valuesTo: string): this {\n longer(this, columns, namesTo, valuesTo);\n return this;\n }\n\n /**\n * Restructures this table by unstacking (pivoting) values, transforming data from a long format to a wide format.\n *\n * For example, given a table showing employee counts per department per year:\n *\n * | Department | Year | Employees |\n * | :--------- | :--- | :-------- |\n * | Accounting | 2021 | 10 |\n * | Accounting | 2022 | 9 |\n * | Accounting | 2023 | 15 |\n * | Sales | 2021 | 52 |\n * | Sales | 2022 | 75 |\n * | Sales | 2023 | 98 |\n *\n * We can restructure it by creating new columns for each year, with the associated employee counts as values.\n *\n * @example\n * ```ts\n * // Restructure the table by pivoting 'Year' into new columns with 'Employees' as values\n * await table.wider(\"Year\", \"Employees\").log();\n * ```\n *\n * The table will then look like this:\n *\n * | Department | 2021 | 2022 | 2023 |\n * | :--------- | :--- | :--- | :--- |\n * | Accounting | 10 | 9 | 15 |\n * | Sales | 52 | 75 | 98 |\n *\n * When multiple rows share the same `namesFrom`/grouping combination, their `valuesFrom` values are combined with the `options.stat` function (`\"sum\"` by default).\n *\n * @param namesFrom - The name of the column containing the values that will be transformed into new column headers (e.g., \"Year\").\n * @param valuesFrom - The name of the column containing the values to be spread across the new columns (e.g., \"Employees\").\n * @param options - An optional object with configuration options:\n * @param options.stat - The stat function applied when multiple rows share the same `namesFrom`/grouping combination: `\"sum\"`, `\"count\"`, `\"min\"`, `\"max\"`, `\"mean\"`, `\"median\"`, or `\"first\"`. Defaults to `\"sum\"`.\n * @returns The table, so methods can be chained.\n * @category Restructuring Data\n */\n wider(\n namesFrom: string,\n valuesFrom: string,\n options: {\n stat?: \"sum\" | \"count\" | \"min\" | \"max\" | \"mean\" | \"median\" | \"first\";\n } = {},\n ): this {\n wider(this, namesFrom, valuesFrom, options);\n return this;\n }\n\n /**\n * Converts data types of specified columns to target types (JavaScript or SQL types).\n *\n * When converting non-standard timestamp, date, or time strings, provide a `datetimeFormat` option using [DuckDB's format specifiers](https://duckdb.org/docs/sql/functions/dateformat).\n * Strings converted to `datetimeTz` or `timestamp with time zone` use an\n * explicit `Z` or numeric offset when present; strings without an offset are\n * interpreted as UTC. Returned `TIMESTAMP WITH TIME ZONE` values are rendered\n * as UTC strings.\n *\n * When converting timestamps, dates, or times to/from numbers, the numerical representation will be in milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC).\n *\n * When converting strings to numbers, commas (often used as thousand separators) will be automatically removed before conversion.\n *\n * @example\n * ```ts\n * // Convert 'column1' to string and 'column2' to integer (JavaScript types)\n * await table.convert({ column1: \"string\", column2: \"integer\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Convert 'column1' to VARCHAR and 'column2' to BIGINT (SQL types)\n * await table.convert({ column1: \"varchar\", column2: \"bigint\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Convert strings in 'column3' to datetime using a specific format\n * await table.convert({ column3: \"datetime\" }, { datetimeFormat: \"%Y-%m-%d\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Both values identify instants and are rendered in UTC.\n * await table\n * .loadArray([\n * { observedAt: \"2024-04-07T13:00:00-04:00\" },\n * { observedAt: \"2024-04-07T17:00:00Z\" },\n * ])\n * .convert({ observedAt: \"datetimeTz\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Convert datetime values in 'column3' to strings using a specific format\n * await table.convert({ column3: \"string\" }, { datetimeFormat: \"%Y-%m-%d %H:%M:%S\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Convert 'amount' to float, replacing unconvertible values with NULL\n * await table.convert({ amount: \"float\" }, { strict: false }).log();\n * ```\n *\n * @example\n * ```ts\n * // Parse JSON, a fixed-size float vector, and WKT geometry from text.\n * await table.loadArray([{\n * details: '{\"count\":3}',\n * embedding: \"[0.25,0.5,0.75]\",\n * geom: \"POINT (-73 45)\",\n * }])\n * .convert({ details: \"JSON\", embedding: \"FLOAT[3]\", geom: \"GEOMETRY('EPSG:4326')\" })\n * .log();\n * ```\n * @param types - An object mapping column names to their target data types for conversion, including JSON, FLOAT[n] vectors, and GEOMETRY with a CRS.\n * @param options - An optional object with configuration options:\n * @param options.strict - If `false`, values that cannot be converted will be replaced by `NULL` instead of throwing an error. Defaults to `true`.\n * @param options.datetimeFormat - A string specifying the format for date and time conversions. Uses `strftime` and `strptime` functions from DuckDB. For format specifiers, see [DuckDB's documentation](https://duckdb.org/docs/sql/functions/dateformat).\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n convert(\n types: {\n [key: string]:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`;\n },\n options: {\n strict?: boolean;\n datetimeFormat?: string;\n } = {},\n ): this {\n convert(this, types, options);\n return this;\n }\n\n /**\n * Removes the table from the database. After this operation, invoking methods on this SimpleTable instance will result in an error.\n *\n * @example\n * ```ts\n * // Remove the current table from the database\n * await table.removeTable();\n * ```\n * @returns A promise that resolves after the table is removed.\n * @category Table Management\n */\n async removeTable(): Promise<this> {\n await removeTable(this);\n return this;\n }\n\n /**\n * Removes one or more columns from this table.\n *\n * @example\n * ```ts\n * // Remove 'column1' and 'column2' from the table\n * await table.removeColumns([\"column1\", \"column2\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Remove a single column named 'tempColumn'\n * await table.removeColumns(\"tempColumn\").log();\n * ```\n * @param columns - The name or an array of names of the columns to be removed.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n removeColumns(columns: string | string[]): this {\n removeColumns(this, columns);\n return this;\n }\n\n /**\n * Adds a new column to the table based on a specified data type (JavaScript or SQL types) and a SQL definition.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, expressions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Add a new column 'total' as a float, calculated from 'column1' and 'column2'\n * await table.addColumn(\"total\", \"float\", \"column1 + column2\").log();\n * ```\n *\n * @example\n * ```ts\n * // Add a new geometry column 'centroid' using the centroid of an existing 'country' geometry column\n * await table.addColumn(\"centroid\", \"geometry('EPSG:4326')\", `ST_Centroid(\"country\")`).log();\n * ```\n *\n * @example\n * ```ts\n * // Read a number from a JSON object into a new column using dot notation.\n * await table.loadArray([{ details: { count: 3 } }], {\n * columnTypes: { details: \"JSON\" },\n * })\n * .addColumn(\"count\", \"integer\", \"details.count\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Create JSON and fixed-size vector columns with DuckDB expressions.\n * await table.loadArray([{ count: 3 }])\n * .addColumn(\"details\", \"JSON\", \"json_object('count', count)\")\n * .addColumn(\"embedding\", \"FLOAT[3]\", \"[0.25, 0.5, 0.75]\")\n * .log();\n * ```\n * @param newColumn - The name of the new column to be added.\n * @param type - The data type for the new column. Can be a JavaScript type (e.g., `\"number\"`, `\"string\"`) or a SQL type (e.g., `\"integer\"`, `\"varchar\"`, `\"JSON\"`, `\"FLOAT[3]\"`, `\"GEOMETRY('EPSG:4326')\"`).\n * @param definition - A SQL expression defining how the values for the new column should be computed (e.g., `\"column1 + column2\"`, `\"ST_Centroid(geom_column)\"`).\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n addColumn(\n newColumn: string,\n type:\n | \"integer\"\n | \"float\"\n | \"number\"\n | \"string\"\n | \"date\"\n | \"time\"\n | \"datetime\"\n | \"datetimeTz\"\n | \"bigint\"\n | \"double\"\n | \"varchar\"\n | \"timestamp\"\n | \"timestamp with time zone\"\n | \"boolean\"\n | \"json\"\n | \"JSON\"\n | `float[${number}]`\n | `FLOAT[${number}]`\n | `geometry('${string}')`\n | `GEOMETRY('${string}')`,\n definition: string,\n ): this {\n addColumn(this, newColumn, type, definition);\n return this;\n }\n\n /**\n * Adds a unique, non-null ID for each row in the current table. IDs start at\n * `0` and identify rows within this table, including rows with identical\n * contents. Without a prefix, the new column contains numbers. When\n * a prefix is supplied, the new column contains strings with the\n * exact prefix followed by the row number. An empty prefix therefore creates\n * the strings `\"0\"`, `\"1\"`, and so on.\n *\n * IDs are not globally unique: separate tables can generate the same IDs.\n *\n * @example\n * ```ts\n * // Add numeric IDs: 0, 1, 2, ...\n * await table\n * .addId(\"edgeId\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Add string IDs: \"flight-0\", \"flight-1\", \"flight-2\", ...\n * await flights\n * .addId(\"edgeId\", { prefix: \"flight-\" })\n * .log();\n * ```\n * @param newColumn - The name of the new ID column.\n * @param options - An optional object with configuration options.\n * @param options.prefix - Text to place before each row number. Supplying this option, including an empty string, creates string IDs.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n addId(newColumn: string, options: { prefix?: string } = {}): this {\n addId(this, newColumn, options);\n return this;\n }\n\n /**\n * Finds the distinct nodes directly connected to one or more starting nodes.\n * The `direction` option lets you find neighbors from source to target,\n * from target to source, or in either direction. The result has `start` and\n * `node` columns, sorted in ascending order by `start`, then `node`.\n *\n * Unknown starting IDs and starts with no neighbors in the selected\n * direction produce no rows.\n * A self-connection includes the starting node once. Empty start arrays and\n * duplicate starting IDs throw an error.\n *\n * The next three examples each start with this data:\n *\n * | origin | destination |\n * | --- | --- |\n * | A | B |\n * | A | B |\n * | C | A |\n *\n * By default, the method finds neighbors from source to target:\n *\n * @example\n * ```ts\n * await table\n * .neighbors(\"origin\", \"destination\", \"A\")\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | B |\n *\n * B appears only once, even though the input has two connections from A to B.\n *\n * With `direction: \"incoming\"`, the method finds neighbors from target to\n * source. Here, C connects to A:\n *\n * @example\n * ```ts\n * await table\n * .neighbors(\"origin\", \"destination\", \"A\", { direction: \"incoming\" })\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | C |\n *\n * With `direction: \"both\"`, the method finds neighbors in either direction:\n *\n * @example\n * ```ts\n * await table\n * .neighbors(\"origin\", \"destination\", \"A\", { direction: \"both\" })\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | B |\n * | A | C |\n *\n * Multiple starts are evaluated independently. For this input:\n *\n * | source | target | cost |\n * | --- | --- | ---: |\n * | Montreal | Ottawa | 2 |\n * | Ottawa | Toronto | 3 |\n *\n * @example\n * ```ts\n * await table\n * .neighbors(\"source\", \"target\", [\"Montreal\", \"Ottawa\"])\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | Montreal | Ottawa |\n * | Ottawa | Toronto |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param startNodes - One starting node ID or an array of distinct starting node IDs.\n * @param options - An optional object with direction and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n neighbors(\n sourceColumn: string,\n targetColumn: string,\n startNodes: string | number | bigint | (string | number | bigint)[],\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n outputTable?: string | boolean;\n } = {},\n ): SimpleTable {\n return neighbors(this, sourceColumn, targetColumn, startNodes, options);\n }\n\n /**\n * Counts the incoming and outgoing connections for every node found in the\n * source and target columns. By default, each input row is counted separately,\n * even when several rows connect the same two nodes. Set the `count` option to\n * `\"neighbors\"` to count distinct neighboring nodes instead. Use the `weight`\n * option to sum values from a numeric column instead of counting connections.\n * The `weight` option cannot be combined with `count: \"neighbors\"`.\n *\n * The result has `node`, `incoming`, `outgoing`, and `total` columns. The\n * `total` is the sum of `incoming` and `outgoing`. Results are sorted by\n * highest total first, then by node in ascending order when totals are equal.\n * A self-connection contributes once to incoming and once to outgoing, so\n * it contributes twice to the total. With `count: \"neighbors\"`, a neighbor\n * connected in both directions also contributes once in each direction.\n * Endpoint IDs must be non-null strings or whole numbers in compatible\n * columns. Supplied weights must be non-null, finite, and non-negative.\n *\n * The next three examples each start with these flights:\n *\n * | origin | destination | passengers |\n * | --- | --- | ---: |\n * | Montreal | Toronto | 100 |\n * | Montreal | Toronto | 200 |\n * | Montreal | Vancouver | 50 |\n * | Toronto | Montreal | 150 |\n *\n * By default, the method counts connections and overwrites the input table:\n *\n * @example\n * ```ts\n * await flights\n * .degree(\"origin\", \"destination\")\n * .log();\n * ```\n *\n * | node | incoming | outgoing | total |\n * | --- | ---: | ---: | ---: |\n * | Montreal | 1 | 3 | 4 |\n * | Toronto | 2 | 1 | 3 |\n * | Vancouver | 1 | 0 | 1 |\n *\n * With `count: \"neighbors\"`, the two Montreal-to-Toronto flights count as\n * one outgoing neighbor for Montreal:\n *\n * @example\n * ```ts\n * await flights\n * .degree(\"origin\", \"destination\", { count: \"neighbors\" })\n * .log();\n * ```\n *\n * | node | incoming | outgoing | total |\n * | --- | ---: | ---: | ---: |\n * | Montreal | 1 | 2 | 3 |\n * | Toronto | 1 | 1 | 2 |\n * | Vancouver | 1 | 0 | 1 |\n *\n * With `weight: \"passengers\"`, the method adds passenger counts for each\n * city's incoming and outgoing flights:\n *\n * @example\n * ```ts\n * await flights\n * .degree(\"origin\", \"destination\", { weight: \"passengers\" })\n * .log();\n * ```\n *\n * | node | incoming | outgoing | total |\n * | --- | ---: | ---: | ---: |\n * | Montreal | 150 | 350 | 500 |\n * | Toronto | 300 | 150 | 450 |\n * | Vancouver | 50 | 0 | 50 |\n *\n * A self-connection is counted once in each direction. For this input:\n *\n * | source | target |\n * | --- | --- |\n * | A | A |\n * | A | B |\n *\n * @example\n * ```ts\n * await connections\n * .degree(\"source\", \"target\")\n * .log();\n * ```\n *\n * | node | incoming | outgoing | total |\n * | --- | ---: | ---: | ---: |\n * | A | 1 | 2 | 3 |\n * | B | 1 | 0 | 1 |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param options - An optional object with counting and result configuration.\n * @param options.count - Whether to count connection rows (`\"edges\"`) or distinct adjacent nodes (`\"neighbors\"`). Defaults to `\"edges\"`.\n * @param options.weight - The name of the numeric edge-weight column to sum. This requires edge counting.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n degree(\n sourceColumn: string,\n targetColumn: string,\n options: {\n count?: \"edges\" | \"neighbors\";\n weight?: string;\n outputTable?: string | boolean;\n } = {},\n ): SimpleTable {\n return degree(this, sourceColumn, targetColumn, options);\n }\n\n /**\n * Finds the neighbors shared by two different nodes. The `direction` option\n * lets you find neighbors from source to target, from target to source, or\n * in either direction. The result has one `node` column, sorted in\n * ascending order.\n *\n * If either node ID is unknown, or the nodes have no shared neighbors, the\n * result has no rows. Each shared neighbor appears once, even if\n * connections are repeated. A self-connection can make one of the requested\n * nodes a shared neighbor. Using the same ID for both requested nodes\n * throws an error.\n *\n * The next three examples each start with this data:\n *\n * | origin | destination |\n * | --- | --- |\n * | A | C |\n * | A | C |\n * | B | C |\n * | B | C |\n * | D | A |\n * | D | B |\n *\n * By default, the method finds shared neighbors from source to target. Both\n * A and B connect to C:\n *\n * @example\n * ```ts\n * await connections\n * .commonNeighbors(\"origin\", \"destination\", \"A\", \"B\")\n * .log();\n * ```\n *\n * | node |\n * | --- |\n * | C |\n *\n * C appears only once, even though the input repeats the connections.\n *\n * With `direction: \"incoming\"`, the method follows connections from target\n * to source. D connects to both A and B:\n *\n * @example\n * ```ts\n * await connections\n * .commonNeighbors(\"origin\", \"destination\", \"A\", \"B\", { direction: \"incoming\" })\n * .log();\n * ```\n *\n * | node |\n * | --- |\n * | D |\n *\n * With `direction: \"both\"`, the method finds shared neighbors in either\n * direction:\n *\n * @example\n * ```ts\n * await connections\n * .commonNeighbors(\"origin\", \"destination\", \"A\", \"B\", { direction: \"both\" })\n * .log();\n * ```\n *\n * | node |\n * | --- |\n * | C |\n * | D |\n *\n * A self-connection can make a requested node a shared neighbor. For this\n * input, A is a neighbor of both itself and B:\n *\n * | source | target |\n * | --- | --- |\n * | A | A |\n * | B | A |\n *\n * @example\n * ```ts\n * await connections\n * .commonNeighbors(\"source\", \"target\", \"A\", \"B\")\n * .log();\n * ```\n *\n * | node |\n * | --- |\n * | A |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param nodeA - The first node ID.\n * @param nodeB - The second node ID, which must differ from `nodeA`.\n * @param options - An optional object with direction and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n commonNeighbors(\n sourceColumn: string,\n targetColumn: string,\n nodeA: string | number | bigint,\n nodeB: string | number | bigint,\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n outputTable?: string | boolean;\n } = {},\n ): SimpleTable {\n return commonNeighbors(this, sourceColumn, targetColumn, nodeA, nodeB, options);\n }\n\n /**\n * Finds all nodes you can reach from one or more starting nodes, following\n * one or more connections. The `direction` option lets you follow\n * connections from source to target, from target to source, or in either\n * direction. The result has `start` and `node` columns, sorted by `start`,\n * then `node`.\n *\n * A starting node appears in its own results only if following connections\n * leads back to it, such as a self-connection or a cycle. Each reachable\n * node appears only once per start. With `direction: \"both\"`, following\n * the same connection out and back also reaches the starting node.\n *\n * Unknown starting IDs and starts with no connections to follow produce\n * no rows. Empty start arrays and duplicate starting IDs throw an error.\n *\n * Use the `startTimeColumn` or `endTimeColumn` options to follow connections\n * in chronological order. The `minGapMs` option sets the minimum gap between\n * consecutive connections, in milliseconds. With both time columns, gaps are\n * measured from one connection's end to the next connection's start; with one\n * column, between their timestamps. The `strictOrdering` option defaults to\n * `true`, rejecting zero-duration gaps. These options only work with\n * `direction: \"outgoing\"` or `direction: \"incoming\"`.\n *\n * The next four examples each start with this data:\n *\n * | origin | destination |\n * | --- | --- |\n * | A | B |\n * | A | C |\n * | B | D |\n * | C | D |\n * | D | A |\n *\n * By default, the method follows connections from source to target. A\n * appears in its own results because A → B → D → A leads back to it:\n *\n * @example\n * ```ts\n * await connections\n * .reachable(\"origin\", \"destination\", \"A\")\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | A |\n * | A | B |\n * | A | C |\n * | A | D |\n *\n * With `direction: \"incoming\"`, connections are followed from target to\n * source. Starting at B:\n *\n * @example\n * ```ts\n * await connections\n * .reachable(\"origin\", \"destination\", \"B\", { direction: \"incoming\" })\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | B | A |\n * | B | B |\n * | B | C |\n * | B | D |\n *\n * With `direction: \"both\"`, connections can be followed in either\n * direction:\n *\n * @example\n * ```ts\n * await connections\n * .reachable(\"origin\", \"destination\", \"B\", { direction: \"both\" })\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | B | A |\n * | B | B |\n * | B | C |\n * | B | D |\n *\n * With multiple starting nodes, each has its own results:\n *\n * @example\n * ```ts\n * await connections\n * .reachable(\"origin\", \"destination\", [\"B\", \"A\"])\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | A |\n * | A | B |\n * | A | C |\n * | A | D |\n * | B | A |\n * | B | B |\n * | B | C |\n * | B | D |\n *\n * Chronological options retain only journeys with valid connection times.\n * Here, A → B arrives at 10:00, so the 09:00 connection to C is unavailable,\n * while the 11:00 connection to D meets the one-hour minimum gap:\n *\n * | origin | destination | departureTime | arrivalTime |\n * | --- | --- | --- | --- |\n * | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 |\n * | B | C | 2025-01-01 09:00 | 2025-01-01 10:00 |\n * | B | D | 2025-01-01 11:00 | 2025-01-01 12:00 |\n *\n * The departure and arrival columns are timestamps:\n *\n * @example\n * ```ts\n * await flights\n * .reachable(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departureTime\",\n * endTimeColumn: \"arrivalTime\",\n * minGapMs: 60 * 60 * 1000,\n * })\n * .log();\n * ```\n *\n * | start | node |\n * | --- | --- |\n * | A | B |\n * | A | D |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param startNodes - One starting node ID or an array of distinct starting node IDs.\n * @param options - An optional object with direction, time, and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n reachable(\n sourceColumn: string,\n targetColumn: string,\n startNodes: string | number | bigint | (string | number | bigint)[],\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n endTimeColumn?: string;\n minGapMs?: number;\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n } = {},\n ): SimpleTable {\n return reachable(this, sourceColumn, targetColumn, startNodes, options);\n }\n\n /**\n * Groups nodes that are connected to one another, directly or through other\n * nodes. By default, connection direction is ignored. With the `mode`\n * option set to \"strong\", nodes belong to the same group only if each can\n * reach all the others by following connections from source to target.\n *\n * The result has `componentId` and `node` columns. Without `startTimeColumn`\n * or `endTimeColumn`, each node appears once, and rows are sorted by node.\n * Groups are numbered from zero in order of their smallest node ID.\n *\n * Use the `startTimeColumn` or `endTimeColumn` options to follow connections\n * in chronological order. The `minGapMs` option sets the minimum gap between\n * consecutive connections, in milliseconds. With both time columns, gaps are\n * measured from one connection's end to the next connection's start; with one\n * column, between their timestamps. The `strictOrdering` option defaults to\n * `true`, rejecting zero-duration gaps. These options require an explicitly\n * supplied `mode: \"strong\"`.\n *\n * With these options, nodes are grouped when each can reach all the others\n * in chronological order. Groups can overlap, so a node may appear in\n * several rows with different `componentId` values.\n *\n * For the first example, we start with this data:\n *\n * | origin | destination |\n * | --- | --- |\n * | A | B |\n * | C | D |\n *\n * By default, the method groups connected nodes without considering\n * direction. B and D are included even though they only appear as\n * destinations:\n *\n * @example\n * ```ts\n * await table\n * .connectedComponents(\"origin\", \"destination\")\n * .log();\n * ```\n *\n * | componentId | node |\n * | ---: | --- |\n * | 0 | A |\n * | 0 | B |\n * | 1 | C |\n * | 1 | D |\n *\n * The next two examples each start with this chain of connections:\n *\n * | source | target |\n * | --- | --- |\n * | A | B |\n * | B | C |\n *\n * By default, all three nodes belong to the same group:\n *\n * @example\n * ```ts\n * await graph\n * .connectedComponents(\"source\", \"target\")\n * .log();\n * ```\n *\n * | componentId | node |\n * | ---: | --- |\n * | 0 | A |\n * | 0 | B |\n * | 0 | C |\n *\n * With the `mode` option set to \"strong\", each node forms its own group. A\n * can reach B and C, but neither can get back to A:\n *\n * @example\n * ```ts\n * await graph\n * .connectedComponents(\"source\", \"target\", {\n * mode: \"strong\",\n * })\n * .log();\n * ```\n *\n * | componentId | node |\n * | ---: | --- |\n * | 0 | A |\n * | 1 | B |\n * | 2 | C |\n *\n * Adding C -> A would let every node reach the others, so all three would\n * belong to the same group in \"strong\" mode too.\n *\n * Chronological strong groups can overlap. The next example uses one\n * instantaneous timestamp column:\n *\n * | time | source | target |\n * | --- | --- | --- |\n * | 2025-01-01 08:00 | B | C |\n * | 2025-01-01 09:00 | C | B |\n * | 2025-01-01 10:00 | A | B |\n * | 2025-01-01 11:00 | B | A |\n *\n * A and B can reach each other, as can B and C, but A cannot reach C after\n * its first event. This produces the maximal groups `{A, B}` and `{B, C}`:\n *\n * @example\n * ```ts\n * await transactions\n * .connectedComponents(\"source\", \"target\", {\n * mode: \"strong\",\n * startTimeColumn: \"time\",\n * })\n * .log();\n * ```\n *\n * | componentId | node |\n * | ---: | --- |\n * | 0 | A |\n * | 0 | B |\n * | 1 | B |\n * | 1 | C |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param options - An optional object with component, time, and result configuration.\n * @param options.mode - Whether to find `\"weak\"` or `\"strong\"` components. Defaults to `\"weak\"`. Using `startTimeColumn` or `endTimeColumn` requires explicitly setting `mode: \"strong\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n connectedComponents(\n sourceColumn: string,\n targetColumn: string,\n options: {\n endTimeColumn?: string;\n minGapMs?: number;\n mode?: \"weak\" | \"strong\";\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n } = {},\n ): SimpleTable {\n return connectedComponents(this, sourceColumn, targetColumn, options);\n }\n\n /**\n * Orders nodes so each prerequisite comes before the nodes that depend on\n * it. Each input row means the source node must come before the target\n * node. For example, A → B means A must come before B.\n *\n * The result has `node`, `componentId`, and `order` columns, sorted by\n * `componentId`, then `order`. Nodes connected directly or through other\n * nodes belong to the same group, ignoring connection direction.\n * Groups are numbered from zero, with the group containing the smallest\n * node ID first.\n *\n * Within each group, `order` starts at one. When several nodes are ready,\n * the method chooses the smallest node ID first: numeric order for numbers\n * and character order for strings. All nodes in the source and target\n * columns are included.\n *\n * If dependencies form a loop, there is no valid order and the method\n * throws an error. A node depending on itself also causes an error. An\n * empty input produces no rows.\n *\n * For this example, we start with these connections:\n *\n * | source | target |\n * | --- | --- |\n * | A | B |\n * | B | C |\n * | D | C |\n *\n * A must come before B, and both B and D must come before C:\n *\n * @example\n * ```ts\n * await table\n * .topologicalSort(\"source\", \"target\")\n * .log();\n * ```\n *\n * | node | componentId | order |\n * | --- | ---: | ---: |\n * | A | 0 | 1 |\n * | B | 0 | 2 |\n * | D | 0 | 3 |\n * | C | 0 | 4 |\n *\n * C comes last because it depends on both B and D. A comes before D\n * because both are initially ready and A has the smaller ID. After A,\n * B is ready and comes before D for the same reason.\n *\n * With two independent groups, each has its own order starting at one.\n * This example starts with different data:\n *\n * | source | target |\n * | --- | --- |\n * | A | D |\n * | B | C |\n *\n * @example\n * ```ts\n * await table\n * .topologicalSort(\"source\", \"target\")\n * .log();\n * ```\n *\n * | node | componentId | order |\n * | --- | ---: | ---: |\n * | A | 0 | 1 |\n * | D | 0 | 2 |\n * | B | 1 | 1 |\n * | C | 1 | 2 |\n *\n * @param sourceColumn - The name of the column containing each prerequisite node ID.\n * @param targetColumn - The name of the column containing each dependent node ID.\n * @param options - An optional object with result configuration.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n topologicalSort(\n sourceColumn: string,\n targetColumn: string,\n options: {\n outputTable?: string | boolean;\n } = {},\n ): SimpleTable {\n return topologicalSort(this, sourceColumn, targetColumn, options);\n }\n\n /**\n * Finds the shortest routes from each starting node to every reachable\n * node. Without options, shortest means the fewest connections. Use `weight`\n * to report total cost and `elapsedTime` to report duration including waiting\n * between connections. Use `minimize` to choose which metric defines shortest.\n *\n * Each row contains `start`, `node`, and `steps`, plus `total` when `weight`\n * is supplied and `elapsedTimeMs` when enabled. Routes tied on the chosen\n * metric produce separate rows only when their reported summaries differ;\n * identical summaries appear once.\n *\n * Routes cannot repeat nodes except for a final return to the start. A start\n * appears in its own results only through an actual return or self-connection,\n * never with zero steps. With `direction: \"both\"`, a return can follow the\n * same connection out and back. Use `shortestPath()` to inspect individual\n * connections between two different nodes.\n *\n * Reporting weight or elapsed time can require substantial time and memory\n * on dense networks because many routes may need to be explored.\n *\n * The next five examples each start with this data:\n *\n * | origin | destination | minutes |\n * | --- | --- | ---: |\n * | A | B | 4 |\n * | B | C | 1 |\n * | D | B | 2 |\n *\n * By default, the method follows connections from source to target and\n * counts how many connections are needed:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", \"A\")\n * .log();\n * ```\n *\n * | start | node | steps |\n * | --- | --- | ---: |\n * | A | B | 1 |\n * | A | C | 2 |\n *\n * With `weight: \"minutes\"`, `total` is the sum of travel times:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", \"A\", { weight: \"minutes\" })\n * .log();\n * ```\n *\n * | start | node | steps | total |\n * | --- | --- | ---: | ---: |\n * | A | B | 1 | 4 |\n * | A | C | 2 | 5 |\n *\n * With `direction: \"incoming\"`, connections are followed from target to\n * source. Starting at C:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", \"C\", { direction: \"incoming\" })\n * .log();\n * ```\n *\n * | start | node | steps |\n * | --- | --- | ---: |\n * | C | B | 1 |\n * | C | A | 2 |\n * | C | D | 2 |\n *\n * With `direction: \"both\"`, connections can be followed in either\n * direction:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", \"A\", { direction: \"both\" })\n * .log();\n * ```\n *\n * | start | node | steps |\n * | --- | --- | ---: |\n * | A | B | 1 |\n * | A | A | 2 |\n * | A | C | 2 |\n * | A | D | 2 |\n *\n * A appears with 2 steps because A → B → A follows a connection out\n * and back.\n *\n * An array of starting nodes gives separate distances for each start:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", [\"D\", \"A\"], {\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | start | node | steps | total |\n * | --- | --- | ---: | ---: |\n * | A | B | 1 | 4 |\n * | A | C | 2 | 5 |\n * | D | B | 1 | 2 |\n * | D | C | 2 | 3 |\n *\n * A direct self-connection and a longer return route can both lead back\n * to the start. This example uses different data:\n *\n * | origin | destination | minutes |\n * | --- | --- | ---: |\n * | A | A | 10 |\n * | A | B | 2 |\n * | B | A | 3 |\n *\n * The shortest return to A takes 5 minutes through B, compared with\n * 10 minutes for the direct self-connection:\n *\n * @example\n * ```ts\n * await connections\n * .distances(\"origin\", \"destination\", \"A\", { weight: \"minutes\" })\n * .log();\n * ```\n *\n * | start | node | steps | total |\n * | --- | --- | ---: | ---: |\n * | A | B | 1 | 2 |\n * | A | A | 2 | 5 |\n *\n * Chronological options can rule out a cheaper sequence that departs too\n * early. Here, B → C leaves before A → B arrives, while B → D meets the\n * one-hour minimum exactly:\n *\n * | origin | destination | departureTime | arrivalTime | minutes |\n * | --- | --- | --- | --- | ---: |\n * | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 2 |\n * | B | C | 2025-01-01 09:00 | 2025-01-01 10:00 | 1 |\n * | B | D | 2025-01-01 11:00 | 2025-01-01 12:00 | 3 |\n *\n * @example\n * ```ts\n * await scheduledFlights\n * .distances(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departureTime\",\n * endTimeColumn: \"arrivalTime\",\n * minGapMs: 60 * 60 * 1000,\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | start | node | steps | total |\n * | --- | --- | ---: | ---: |\n * | A | B | 1 | 2 |\n * | A | D | 2 | 5 |\n *\n * For the next four examples, `flights` contains these rows, with departure\n * and arrival stored as timestamps on the same day:\n *\n * | flightId | origin | destination | departure | arrival | price |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 09:00 | 2025-01-01 10:00 | 40 |\n * | F2 | B | C | 2025-01-01 12:00 | 2025-01-01 13:00 | 40 |\n * | F3 | A | C | 2025-01-01 09:00 | 2025-01-01 12:00 | 120 |\n *\n * Find the fastest journey from A to each reachable destination, including\n * layovers:\n *\n * @example\n * ```ts\n * await flights\n * .distances(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * })\n * .log();\n * ```\n *\n * | start | node | steps | elapsedTimeMs |\n * | --- | --- | ---: | ---: |\n * | A | B | 1 | 3600000 |\n * | A | C | 1 | 10800000 |\n *\n * The direct flight to C takes three hours (10,800,000 milliseconds).\n * The route through B takes four hours including its layover.\n *\n * Find the fastest journeys from A while also adding up their prices:\n *\n * @example\n * ```ts\n * await flights\n * .distances(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * minimize: \"elapsedTime\",\n * })\n * .log();\n * ```\n *\n * | start | node | steps | total | elapsedTimeMs |\n * | --- | --- | ---: | ---: | ---: |\n * | A | B | 1 | 40 | 3600000 |\n * | A | C | 1 | 120 | 10800000 |\n *\n * Use `minimize: \"weight\"` to find the cheapest journeys instead. The\n * selected route to C now takes two steps through B and costs 80:\n *\n * @example\n * ```ts\n * await flights\n * .distances(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * minimize: \"weight\",\n * })\n * .log();\n * ```\n *\n * | start | node | steps | total | elapsedTimeMs |\n * | --- | --- | ---: | ---: | ---: |\n * | A | B | 1 | 40 | 3600000 |\n * | A | C | 2 | 80 | 14400000 |\n *\n * Choose the fewest connections while still reporting price and elapsed\n * time. The direct flight to C has one step, even though it costs more:\n *\n * @example\n * ```ts\n * await flights\n * .distances(\"origin\", \"destination\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * minimize: \"steps\",\n * })\n * .log();\n * ```\n *\n * | start | node | steps | total | elapsedTimeMs |\n * | --- | --- | ---: | ---: | ---: |\n * | A | B | 1 | 40 | 3600000 |\n * | A | C | 1 | 120 | 10800000 |\n *\n * When two routes to C both take two steps but have different prices,\n * minimizing steps while reporting price returns both summaries:\n *\n * @example\n * ```ts\n * await connections\n * .loadArray([\n * { origin: \"A\", destination: \"B\", price: 20 },\n * { origin: \"B\", destination: \"C\", price: 30 },\n * { origin: \"A\", destination: \"D\", price: 40 },\n * { origin: \"D\", destination: \"C\", price: 40 },\n * ])\n * .distances(\"origin\", \"destination\", \"A\", {\n * weight: \"price\",\n * minimize: \"steps\",\n * })\n * .filter(\"node = 'C'\")\n * .log();\n * ```\n *\n * | start | node | steps | total |\n * | --- | --- | ---: | ---: |\n * | A | C | 2 | 50 |\n * | A | C | 2 | 80 |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param startNodes - One starting node ID or a non-empty array of distinct IDs. Unknown IDs and starts with no connections to follow produce no rows. Empty arrays and duplicate IDs throw an error.\n * @param options - An optional object with direction, time, and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`. Chronological traversal supports only `\"outgoing\"` and `\"incoming\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds; does not apply before the first connection. With both time columns, measured from one connection's end to the next's start; with one column, between timestamps. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.weight - The name of the numeric column used as the cost of each connection. Values must be non-null, finite, and non-negative. Adds `total`, the cumulative sum of those costs. If omitted, no `total` column is generated.\n * @param options.elapsedTime - Whether to add cumulative `elapsedTimeMs` in milliseconds, including connection gaps. Defaults to `false`. Requires both time columns. Optimization compares native timestamp precision before conversion to milliseconds.\n * @param options.minimize - The metric used to select optimal routes: `\"steps\"`, `\"weight\"`, or `\"elapsedTime\"`. Defaults to `\"weight\"` when only `weight` is enabled, `\"elapsedTime\"` when only elapsed-time reporting is enabled, and `\"steps\"` when neither is enabled. Required when both are enabled. `\"steps\"` is always available; the other metrics require their corresponding options.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The table of distinct optimal summaries with `start`, `node`, and `steps`, plus `total` when `weight` is supplied and `elapsedTimeMs` when enabled, so methods can be chained. Sorted by start, the chosen metric, node, then remaining metrics in the order steps, total, elapsed time.\n * @category Graph Operations\n */\n distances(\n sourceColumn: string,\n targetColumn: string,\n startNodes: string | number | bigint | (string | number | bigint)[],\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n elapsedTime?: boolean;\n endTimeColumn?: string;\n minGapMs?: number;\n minimize?: \"steps\" | \"weight\" | \"elapsedTime\";\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n weight?: string;\n } = {},\n ): SimpleTable {\n return distances(this, sourceColumn, targetColumn, startNodes, options);\n }\n\n /**\n * Finds the shortest route between two different nodes. If several routes\n * tie for shortest, all of them are returned. By default, the shortest\n * route uses the fewest connections. Use the `weight` option to find the\n * route with the smallest sum of values from a numeric column, such as\n * travel time. A route cannot visit the same node twice, to avoid loops.\n * Different routes can still share the same nodes.\n *\n * The `direction` option lets you follow connections from source to target,\n * from target to source, or in either direction.\n *\n * Each connection needs a unique, non-null ID. Pass the name of the column\n * containing these IDs as the `edgeId` argument. If your table is missing\n * an ID column, you can easily create one with `addId()`.\n *\n * The result starts with `pathId`, `step`, and `weight`, followed by the\n * optional metric columns and all original columns. Steps start at one and\n * follow the search direction. The `weight` column is the connection cost,\n * or one when no `weight` option is supplied. Supplying `weight` also adds\n * `total`, the sum of those costs up to and including the current step.\n * Enabling `elapsedTime` adds cumulative `elapsedTimeMs`, including gaps.\n *\n * If an input column conflicts with a generated result column (regardless\n * of capitalization), the method throws an error. Rename it with\n * `renameColumns()` first. `total` is reserved only when `weight` is supplied,\n * and `elapsedTimeMs` only when elapsed-time reporting is enabled.\n *\n * Each row is one connection along a route.\n *\n * Use the `startTimeColumn` or `endTimeColumn` options to follow connections\n * in chronological order. The `minGapMs` option sets the minimum gap between\n * consecutive connections, in milliseconds. With both time columns, gaps are\n * measured from one connection's end to the next connection's start; with one\n * column, between their timestamps. The `strictOrdering` option defaults to\n * `true`, rejecting zero-duration gaps. These options only work with\n * `direction: \"outgoing\"` or `direction: \"incoming\"`.\n *\n * The minimum gap applies only between consecutive connections, not before\n * the first connection.\n *\n * Use `minimize: \"steps\"` to choose the fewest connections even when weight\n * or elapsed-time reporting is enabled. Without an explicit `minimize`, the\n * method minimizes weight when only `weight` is enabled, elapsed time when\n * only `elapsedTime` is enabled, and steps when neither is enabled. With\n * both enabled, specify `\"steps\"`, `\"weight\"`, or `\"elapsedTime\"` explicitly.\n * Elapsed-time reporting requires both time columns.\n *\n * All routes tied on the selected metric are returned, even if their other\n * metrics differ. Each route reports its own weights and elapsed times.\n *\n * Routes are numbered from zero by comparing their sequences of connection\n * IDs, element by element. Rows are sorted by `pathId`, then `step`.\n *\n * Unknown IDs or nodes with no route between them produce no rows. The\n * start and end must differ. Self-connections are ignored. Weights must\n * be non-null, finite, and non-negative.\n *\n * There is no limit on route length or the number of tied routes returned.\n * Finding many tied routes can take a long time and use substantial memory.\n *\n * The first example uses this table:\n *\n * | edgeId | source | target |\n * | --- | --- | --- |\n * | E1 | A | B |\n * | E2 | A | C |\n * | E3 | B | D |\n * | E4 | C | D |\n * | E5 | D | E |\n *\n * By default, the method finds routes from source to target with the fewest\n * connections. Two routes from A to E tie at three connections each:\n *\n * @example\n * ```ts\n * await connections\n * .shortestPath(\"source\", \"target\", \"edgeId\", \"A\", \"E\")\n * .log();\n * ```\n *\n * | pathId | step | weight | edgeId | source | target |\n * | ---: | ---: | ---: | --- | --- | --- |\n * | 0 | 1 | 1 | E1 | A | B |\n * | 0 | 2 | 1 | E3 | B | D |\n * | 0 | 3 | 1 | E5 | D | E |\n * | 1 | 1 | 1 | E2 | A | C |\n * | 1 | 2 | 1 | E4 | C | D |\n * | 1 | 3 | 1 | E5 | D | E |\n *\n * For an input without connection IDs, use `addId()` first:\n *\n * | source | target |\n * | --- | --- |\n * | A | B |\n * | B | E |\n *\n * The generated IDs identify the connections in the result:\n *\n * @example\n * ```ts\n * await unnumberedConnections\n * .addId(\"edgeId\", { prefix: \"edge-\" })\n * .shortestPath(\"source\", \"target\", \"edgeId\", \"A\", \"E\")\n * .log();\n * ```\n *\n * | pathId | step | weight | source | target | edgeId |\n * | ---: | ---: | ---: | --- | --- | --- |\n * | 0 | 1 | 1 | A | B | edge-0 |\n * | 0 | 2 | 1 | B | E | edge-1 |\n *\n * The next two examples each start with these flights. The direct flight\n * takes ten minutes; the route through B and D takes three:\n *\n * | flightId | origin | destination | minutes |\n * | --- | --- | --- | ---: |\n * | F1 | A | E | 10 |\n * | F2 | A | B | 1 |\n * | F3 | B | D | 1 |\n * | F4 | D | E | 1 |\n *\n * With `weight: \"minutes\"`, the route with the shortest travel time is\n * chosen:\n *\n * @example\n * ```ts\n * await flights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"E\", {\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | minutes |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | 0 | 1 | 1 | 1 | F2 | A | B | 1 |\n * | 0 | 2 | 1 | 2 | F3 | B | D | 1 |\n * | 0 | 3 | 1 | 3 | F4 | D | E | 1 |\n *\n * Without the `weight` option, the direct flight is shortest because it\n * uses only one connection:\n *\n * @example\n * ```ts\n * await flights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"E\")\n * .log();\n * ```\n *\n * | pathId | step | weight | flightId | origin | destination | minutes |\n * | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | 0 | 1 | 1 | F1 | A | E | 10 |\n *\n * With time options, the cheaper route through B is ruled out because F2\n * leaves before F1 arrives. The route through C meets the one-hour minimum\n * gap:\n *\n * | flightId | origin | destination | departureTime | arrivalTime | cost |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 1 |\n * | F2 | B | E | 2025-01-01 09:00 | 2025-01-01 10:00 | 1 |\n * | F3 | A | C | 2025-01-01 08:00 | 2025-01-01 09:00 | 2 |\n * | F4 | C | E | 2025-01-01 10:00 | 2025-01-01 11:00 | 2 |\n *\n * @example\n * ```ts\n * await scheduledFlights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"E\", {\n * startTimeColumn: \"departureTime\",\n * endTimeColumn: \"arrivalTime\",\n * minGapMs: 60 * 60 * 1000,\n * weight: \"cost\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 2 | 2 | F3 | A | C | 2025-01-01 08:00:00 | 2025-01-01 09:00:00 | 2 |\n * | 0 | 2 | 2 | 4 | F4 | C | E | 2025-01-01 10:00:00 | 2025-01-01 11:00:00 | 2 |\n *\n * With `direction: \"incoming\"`, connections are followed from target to\n * source. The original source and target values remain unchanged. For\n * this input:\n *\n * | edgeId | source | target |\n * | --- | --- | --- |\n * | F1 | A | B |\n *\n * @example\n * ```ts\n * await reverseExample\n * .shortestPath(\"source\", \"target\", \"edgeId\", \"B\", \"A\", {\n * direction: \"incoming\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | edgeId | source | target |\n * | ---: | ---: | ---: | --- | --- | --- |\n * | 0 | 1 | 1 | F1 | A | B |\n *\n * For the next three examples, `flights` contains these rows, with departure\n * and arrival stored as timestamps on the same day:\n *\n * | flightId | origin | destination | departure | arrival | price |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 09:00 | 2025-01-01 10:00 | 40 |\n * | F2 | B | C | 2025-01-01 12:00 | 2025-01-01 13:00 | 40 |\n * | F3 | A | C | 2025-01-01 09:00 | 2025-01-01 12:00 | 120 |\n * | F4 | A | D | 2025-01-01 09:00 | 2025-01-01 09:30 | 60 |\n * | F5 | D | C | 2025-01-01 10:30 | 2025-01-01 11:00 | 80 |\n *\n * Find the fastest journey from A to C, including layovers:\n *\n * @example\n * ```ts\n * await flights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"C\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 1 | 1800000 | F4 | A | D | 2025-01-01 09:00:00 | 2025-01-01 09:30:00 | 60 |\n * | 0 | 2 | 1 | 7200000 | F5 | D | C | 2025-01-01 10:30:00 | 2025-01-01 11:00:00 | 80 |\n *\n * The route through D takes two hours (7,200,000 milliseconds), including\n * a one-hour layover. The direct flight takes three hours.\n *\n * Find the fastest journey while also adding up its price:\n *\n * @example\n * ```ts\n * await flights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"C\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * minimize: \"elapsedTime\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 60 | 60 | 1800000 | F4 | A | D | 2025-01-01 09:00:00 | 2025-01-01 09:30:00 | 60 |\n * | 0 | 2 | 80 | 140 | 7200000 | F5 | D | C | 2025-01-01 10:30:00 | 2025-01-01 11:00:00 | 80 |\n *\n * Use `minimize: \"weight\"` to find the cheapest journey instead.\n * All ties on the chosen metric are returned.\n *\n * Choose the fewest flights while still reporting price and elapsed time.\n * The direct flight takes one step, although the route through D is faster:\n *\n * @example\n * ```ts\n * await flights\n * .shortestPath(\"origin\", \"destination\", \"flightId\", \"A\", \"C\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * minimize: \"steps\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 120 | 120 | 10800000 | F3 | A | C | 2025-01-01 09:00:00 | 2025-01-01 12:00:00 | 120 |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param edgeId - The name of the column uniquely identifying each connection (edge).\n * @param start - The starting node ID.\n * @param end - The ending node ID, which must differ from `start`.\n * @param options - An optional object with direction, time, and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.weight - The name of the numeric column used as the cost of each connection. Adds `total`, the cumulative sum of those costs. If omitted, no `total` column is generated.\n * @param options.elapsedTime - Whether to add cumulative `elapsedTimeMs` in milliseconds, including connection gaps. Defaults to `false`. Requires both time columns.\n * @param options.minimize - The metric used to select optimal routes: `\"steps\"`, `\"weight\"`, or `\"elapsedTime\"`. Defaults to `\"weight\"` when only `weight` is enabled, `\"elapsedTime\"` when only elapsed-time reporting is enabled, and `\"steps\"` when neither is enabled. Required when both are enabled. `\"steps\"` is always available; the other metrics require their corresponding options.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The table of route connections with optional cumulative `total` and `elapsedTimeMs` metrics, so methods can be chained.\n * @category Graph Operations\n */\n shortestPath(\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n start: string | number | bigint,\n end: string | number | bigint,\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n elapsedTime?: boolean;\n endTimeColumn?: string;\n minGapMs?: number;\n minimize?: \"steps\" | \"weight\" | \"elapsedTime\";\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n weight?: string;\n } = {},\n ): SimpleTable {\n return shortestPath(this, sourceColumn, targetColumn, edgeId, start, end, options);\n }\n\n /**\n * Finds all routes between two different nodes. A route cannot visit the\n * same node twice, to avoid loops. Different routes can still share the\n * same nodes.\n *\n * The `direction` option lets you follow connections from source to target,\n * from target to source, or in either direction.\n *\n * Each connection needs a unique, non-null ID. Pass the name of the column\n * containing these IDs as the `edgeId` argument. If your table is missing\n * an ID column, you can easily create one with `addId()`.\n *\n * The result starts with the `pathId`, `step`, `weight`, and `total`\n * columns, followed by all original columns. Steps start at one and follow\n * the search direction. The `weight` column is the connection cost, and\n * `total` is the sum of those costs up to and including the current step.\n * Without the `weight` option, each connection costs one.\n *\n * If an input column is already named `pathId`, `step`, `weight`, or `total`\n * (regardless of capitalization), the method throws an error. Rename it\n * with `renameColumns()` first.\n *\n * Each row is one connection along a route.\n *\n * Use the `startTimeColumn` or `endTimeColumn` options to follow connections\n * in chronological order. The `minGapMs` option sets the minimum gap between\n * consecutive connections, in milliseconds. With both time columns, gaps are\n * measured from one connection's end to the next connection's start; with one\n * column, between their timestamps. The `strictOrdering` option defaults to\n * `true`, rejecting zero-duration gaps. These options only work with\n * `direction: \"outgoing\"` or `direction: \"incoming\"`.\n *\n * The minimum gap applies only between consecutive connections, not before\n * the first connection.\n *\n * Routes are numbered from zero by comparing their sequences of connection\n * IDs, element by element. Rows are sorted by `pathId`, then `step`.\n *\n * Unknown IDs or nodes with no route between them produce no rows. The\n * start and end must differ. Self-connections are ignored. Weights must\n * be non-null, finite, and non-negative.\n *\n * There is no limit on route length or the number of routes returned.\n * Finding all routes can take a long time and use substantial memory.\n *\n * For the first example, we start with these connections:\n *\n * | edgeId | source | target |\n * | --- | --- | --- |\n * | E1 | A | B |\n * | E2 | A | C |\n * | E3 | B | D |\n * | E4 | C | D |\n *\n * By default, connections are followed from source to target. Both routes\n * from A to D are returned:\n *\n * @example\n * ```ts\n * await connections\n * .paths(\"source\", \"target\", \"edgeId\", \"A\", \"D\")\n * .log();\n * ```\n *\n * | pathId | step | weight | total | edgeId | source | target |\n * | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | 0 | 1 | 1 | 1 | E1 | A | B |\n * | 0 | 2 | 1 | 2 | E3 | B | D |\n * | 1 | 1 | 1 | 1 | E2 | A | C |\n * | 1 | 2 | 1 | 2 | E4 | C | D |\n *\n * For an input without connection IDs, use `addId()` first:\n *\n * | source | target |\n * | --- | --- |\n * | A | B |\n * | B | D |\n *\n * The generated IDs identify the connections in the result:\n *\n * @example\n * ```ts\n * await unnumberedConnections\n * .addId(\"edgeId\", { prefix: \"edge-\" })\n * .paths(\"source\", \"target\", \"edgeId\", \"A\", \"D\")\n * .log();\n * ```\n *\n * | pathId | step | weight | total | source | target | edgeId |\n * | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | 0 | 1 | 1 | 1 | A | B | edge-0 |\n * | 0 | 2 | 1 | 2 | B | D | edge-1 |\n *\n * The next three examples each start with these flights. The direct flight\n * takes ten minutes; the route through B takes three:\n *\n * | flightId | origin | destination | minutes |\n * | --- | --- | --- | ---: |\n * | F1 | A | D | 10 |\n * | F2 | A | B | 1 |\n * | F3 | B | D | 2 |\n *\n * With `weight: \"minutes\"`, both routes are returned with their travel\n * times:\n *\n * @example\n * ```ts\n * await flights\n * .paths(\"origin\", \"destination\", \"flightId\", \"A\", \"D\", {\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | minutes |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | 0 | 1 | 10 | 10 | F1 | A | D | 10 |\n * | 1 | 1 | 1 | 1 | F2 | A | B | 1 |\n * | 1 | 2 | 2 | 3 | F3 | B | D | 2 |\n *\n * Without the `weight` option, the same routes are returned and total\n * counts connections:\n *\n * @example\n * ```ts\n * await flights\n * .paths(\"origin\", \"destination\", \"flightId\", \"A\", \"D\")\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | minutes |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | 0 | 1 | 1 | 1 | F1 | A | D | 10 |\n * | 1 | 1 | 1 | 1 | F2 | A | B | 1 |\n * | 1 | 2 | 1 | 2 | F3 | B | D | 2 |\n *\n * With `direction: \"incoming\"`, the search runs from D to A. Steps follow\n * that direction, while the original origin and destination values stay\n * unchanged:\n *\n * @example\n * ```ts\n * await flights\n * .paths(\"origin\", \"destination\", \"flightId\", \"D\", \"A\", {\n * direction: \"incoming\",\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | minutes |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | 0 | 1 | 10 | 10 | F1 | A | D | 10 |\n * | 1 | 1 | 2 | 2 | F3 | B | D | 2 |\n * | 1 | 2 | 1 | 3 | F2 | A | B | 1 |\n *\n * Chronological routes enforce the connection time between every pair of\n * steps. For the next two examples, the 09:00 flight leaves before F1\n * arrives, while F3 meets the one-hour minimum exactly:\n *\n * | flightId | origin | destination | departureTime | arrivalTime | cost |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 2 |\n * | F2 | B | C | 2025-01-01 09:00 | 2025-01-01 10:00 | 9 |\n * | F3 | B | D | 2025-01-01 11:00 | 2025-01-01 12:00 | 3 |\n *\n * The route from A to D contains F1 and F3:\n *\n * @example\n * ```ts\n * await scheduledFlights\n * .paths(\"origin\", \"destination\", \"flightId\", \"A\", \"D\", {\n * startTimeColumn: \"departureTime\",\n * endTimeColumn: \"arrivalTime\",\n * minGapMs: 60 * 60 * 1000,\n * weight: \"cost\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 2 | 2 | F1 | A | B | 2025-01-01 08:00:00 | 2025-01-01 10:00:00 | 2 |\n * | 0 | 2 | 3 | 5 | F3 | B | D | 2025-01-01 11:00:00 | 2025-01-01 12:00:00 | 3 |\n *\n * Searching backward from D finds the same physical journey. The steps and\n * cumulative totals follow the incoming search from D to A:\n *\n * @example\n * ```ts\n * await scheduledFlights\n * .paths(\"origin\", \"destination\", \"flightId\", \"D\", \"A\", {\n * direction: \"incoming\",\n * startTimeColumn: \"departureTime\",\n * endTimeColumn: \"arrivalTime\",\n * minGapMs: 60 * 60 * 1000,\n * weight: \"cost\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |\n * | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 3 | 3 | F3 | B | D | 2025-01-01 11:00:00 | 2025-01-01 12:00:00 | 3 |\n * | 0 | 2 | 2 | 5 | F1 | A | B | 2025-01-01 08:00:00 | 2025-01-01 10:00:00 | 2 |\n *\n * For the next two examples, `flights` contains these rows, with departure\n * and arrival stored as timestamps on the same day:\n *\n * | flightId | origin | destination | departure | arrival | price |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 09:00 | 2025-01-01 10:00 | 40 |\n * | F2 | B | C | 2025-01-01 12:00 | 2025-01-01 13:00 | 40 |\n * | F3 | A | C | 2025-01-01 09:00 | 2025-01-01 12:00 | 120 |\n *\n * Report elapsed time for every path, including layovers:\n *\n * @example\n * ```ts\n * await flights\n * .paths(\"origin\", \"destination\", \"flightId\", \"A\", \"C\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 1 | 1 | 3600000 | F1 | A | B | 2025-01-01 09:00:00 | 2025-01-01 10:00:00 | 40 |\n * | 0 | 2 | 1 | 2 | 14400000 | F2 | B | C | 2025-01-01 12:00:00 | 2025-01-01 13:00:00 | 40 |\n * | 1 | 1 | 1 | 1 | 10800000 | F3 | A | C | 2025-01-01 09:00:00 | 2025-01-01 12:00:00 | 120 |\n *\n * The route through B takes four hours (14,400,000 milliseconds),\n * including its two-hour layover. The direct flight takes three hours.\n *\n * Add up prices while continuing to report elapsed time for every path:\n *\n * @example\n * ```ts\n * await flights\n * .paths(\"origin\", \"destination\", \"flightId\", \"A\", \"C\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * })\n * .log();\n * ```\n *\n * | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | 0 | 1 | 40 | 40 | 3600000 | F1 | A | B | 2025-01-01 09:00:00 | 2025-01-01 10:00:00 | 40 |\n * | 0 | 2 | 40 | 80 | 14400000 | F2 | B | C | 2025-01-01 12:00:00 | 2025-01-01 13:00:00 | 40 |\n * | 1 | 1 | 120 | 120 | 10800000 | F3 | A | C | 2025-01-01 09:00:00 | 2025-01-01 12:00:00 | 120 |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param edgeId - The name of the column uniquely identifying each connection (edge).\n * @param start - The starting node ID.\n * @param end - The ending node ID, which must differ from `start`.\n * @param options - An optional object with direction, time, and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.weight - The name of the numeric column used as the cost of each connection. If omitted, each connection costs one.\n * @param options.elapsedTime - Whether to add cumulative `elapsedTimeMs` in milliseconds, including connection gaps. Defaults to `false`. Requires both time columns.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n paths(\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n start: string | number | bigint,\n end: string | number | bigint,\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n elapsedTime?: boolean;\n endTimeColumn?: string;\n minGapMs?: number;\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n weight?: string;\n } = {},\n ): SimpleTable {\n return paths(this, sourceColumn, targetColumn, edgeId, start, end, options);\n }\n\n /**\n * Finds all cycles starting and ending at each node in `startNodes`.\n * Pass one node ID or an array of node IDs. A cycle cannot visit the same\n * node twice, except to return to its start, or reuse a connection.\n * Different cycles can share nodes. The `direction` option lets you\n * follow connections from source to target, from target to source, or in\n * either direction. By default, connections are followed from source to\n * target.\n *\n * Each connection needs a unique, non-null ID. Pass the name of the column\n * containing these IDs as the `edgeId` argument. If your table is missing\n * an ID column, you can easily create one with `addId()`.\n *\n * The result starts with the `start`, `pathId`, `step`, `weight`, and\n * `total` columns, followed by all original columns. The `start` column\n * identifies the requested starting node. Steps start at one and follow\n * the search direction. The `weight` column is the connection cost, and\n * `total` is the sum of those costs up to and including the current step.\n * Without the `weight` option, each connection costs one.\n *\n * If an input column is already named `start`, `pathId`, `step`, `weight`,\n * or `total` (regardless of capitalization), the method throws an error.\n * Rename it with `renameColumns()` first.\n *\n * Each row is one connection, including the final connection back to the\n * start. Weights must be non-null, finite, and non-negative.\n *\n * If a cycle can start at several requested nodes, each starting node\n * produces a separate result. The `pathId` starts at zero for each starting\n * node; `start` and `pathId` together identify a cycle. Passing an empty\n * array or duplicate IDs in `startNodes` throws an error. Unknown IDs or\n * starts with no cycles produce no rows.\n *\n * With `direction: \"both\"`, a cycle and its reverse are returned once per\n * starting node, choosing the smaller sequence of connection IDs. Within\n * each start, cycles are numbered by connection-ID sequence. Rows are\n * sorted by `start`, then `pathId`, then `step`.\n *\n * Use the `startTimeColumn` or `endTimeColumn` options to follow connections\n * in chronological order. The `minGapMs` option sets the minimum gap between\n * consecutive connections, in milliseconds. With both time columns, gaps are\n * measured from one connection's end to the next connection's start; with one\n * column, between their timestamps. The `strictOrdering` option defaults to\n * `true`, rejecting zero-duration gaps. These options only work with\n * `direction: \"outgoing\"` or `direction: \"incoming\"`.\n *\n * Time rules are checked from each requested starting node. A cycle may\n * therefore work from one starting node but not another. No gap is checked\n * from the final connection back to the first. Incoming searches follow\n * connections backward in chronological order.\n *\n * A self-connection forms a one-step cycle. With `direction: \"both\"`, two\n * separate connections between the same nodes can form a two-step cycle. A\n * single connection cannot be followed out and back to create a cycle.\n * Cycles using different connections remain separate, even if they visit\n * the same nodes. If there are no cycles, the result has no rows.\n *\n * There is no limit on cycle length or the number of cycles returned.\n * Finding all cycles can take a long time and use substantial memory.\n *\n * The next four examples each start with these connections:\n *\n * | edgeId | source | target |\n * | --- | --- | --- |\n * | E1 | A | B |\n * | E2 | B | C |\n * | E3 | C | A |\n *\n * By default, connections are followed from source to target:\n *\n * @example\n * ```ts\n * await triangle\n * .findCycles(\"source\", \"target\", \"edgeId\", \"A\")\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | edgeId | source | target |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | A | 0 | 1 | 1 | 1 | E1 | A | B |\n * | A | 0 | 2 | 1 | 2 | E2 | B | C |\n * | A | 0 | 3 | 1 | 3 | E3 | C | A |\n *\n * Requesting both A and B returns the cycle separately for each start:\n *\n * @example\n * ```ts\n * await triangle\n * .findCycles(\"source\", \"target\", \"edgeId\", [\"A\", \"B\"])\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | edgeId | source | target |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | A | 0 | 1 | 1 | 1 | E1 | A | B |\n * | A | 0 | 2 | 1 | 2 | E2 | B | C |\n * | A | 0 | 3 | 1 | 3 | E3 | C | A |\n * | B | 0 | 1 | 1 | 1 | E2 | B | C |\n * | B | 0 | 2 | 1 | 2 | E3 | C | A |\n * | B | 0 | 3 | 1 | 3 | E1 | A | B |\n *\n * With `direction: \"incoming\"`, connections are followed from target to\n * source:\n *\n * @example\n * ```ts\n * await triangle\n * .findCycles(\"source\", \"target\", \"edgeId\", \"A\", { direction: \"incoming\" })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | edgeId | source | target |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | A | 0 | 1 | 1 | 1 | E3 | C | A |\n * | A | 0 | 2 | 1 | 2 | E2 | B | C |\n * | A | 0 | 3 | 1 | 3 | E1 | A | B |\n *\n * With `direction: \"both\"`, either direction is allowed. This cycle appears\n * once, in the direction that starts with E1:\n *\n * @example\n * ```ts\n * await triangle\n * .findCycles(\"source\", \"target\", \"edgeId\", \"A\", { direction: \"both\" })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | edgeId | source | target |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | A | 0 | 1 | 1 | 1 | E1 | A | B |\n * | A | 0 | 2 | 1 | 2 | E2 | B | C |\n * | A | 0 | 3 | 1 | 3 | E3 | C | A |\n *\n * Two separate connections between A and B form a cycle with `direction:\n * \"both\"`. The self-connection at C forms another cycle. For this input:\n *\n * | edgeId | source | target | cost |\n * | --- | --- | --- | ---: |\n * | P1 | A | B | 1 |\n * | P2 | A | B | 2 |\n * | L1 | C | C | 4 |\n *\n * @example\n * ```ts\n * await parallelAndLoop\n * .findCycles(\"source\", \"target\", \"edgeId\", [\"A\", \"C\"], {\n * direction: \"both\",\n * weight: \"cost\",\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | edgeId | source | target | cost |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | A | 0 | 1 | 1 | 1 | P1 | A | B | 1 |\n * | A | 0 | 2 | 2 | 3 | P2 | A | B | 2 |\n * | C | 0 | 1 | 4 | 4 | L1 | C | C | 4 |\n *\n * With the `weight` option, total is a running total of the selected\n * values. For these flights:\n *\n * | flightId | origin | destination | minutes |\n * | --- | --- | --- | ---: |\n * | F1 | A | B | 1 |\n * | F2 | B | C | 2 |\n * | F3 | C | A | 3 |\n *\n * @example\n * ```ts\n * await flights\n * .findCycles(\"origin\", \"destination\", \"flightId\", \"A\", {\n * weight: \"minutes\",\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | flightId | origin | destination | minutes |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- | ---: |\n * | A | 0 | 1 | 1 | 1 | F1 | A | B | 1 |\n * | A | 0 | 2 | 2 | 3 | F2 | B | C | 2 |\n * | A | 0 | 3 | 3 | 6 | F3 | C | A | 3 |\n *\n * For an input without connection IDs, use `addId()` first:\n *\n * | source | target |\n * | --- | --- |\n * | A | B |\n * | B | C |\n * | C | A |\n *\n * @example\n * ```ts\n * await unnumberedConnections\n * .addId(\"edgeId\", { prefix: \"edge-\" })\n * .findCycles(\"source\", \"target\", \"edgeId\", \"A\")\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | source | target | edgeId |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- |\n * | A | 0 | 1 | 1 | 1 | A | B | edge-0 |\n * | A | 0 | 2 | 1 | 2 | B | C | edge-1 |\n * | A | 0 | 3 | 1 | 3 | C | A | edge-2 |\n *\n * For these instantaneous events, requesting A and B as starting nodes\n * returns only the cycle B → C → A → B. Starting at A would break\n * chronological order:\n *\n * | flightId | origin | destination | departureTime |\n * | --- | --- | --- | --- |\n * | F1 | B | C | 2025-01-01 09:00 |\n * | F2 | C | A | 2025-01-01 10:00 |\n * | F3 | A | B | 2025-01-01 11:00 |\n *\n * @example\n * ```ts\n * await timedFlights\n * .findCycles(\"origin\", \"destination\", \"flightId\", [\"A\", \"B\"], {\n * startTimeColumn: \"departureTime\",\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | flightId | origin | destination | departureTime |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- | --- |\n * | B | 0 | 1 | 1 | 1 | F1 | B | C | 2025-01-01 09:00:00 |\n * | B | 0 | 2 | 1 | 2 | F2 | C | A | 2025-01-01 10:00:00 |\n * | B | 0 | 3 | 1 | 3 | F3 | A | B | 2025-01-01 11:00:00 |\n *\n * Searching the same events from B in the incoming direction follows\n * connections backward, from the latest to the earliest:\n *\n * @example\n * ```ts\n * await timedFlights\n * .findCycles(\"origin\", \"destination\", \"flightId\", \"B\", {\n * direction: \"incoming\",\n * startTimeColumn: \"departureTime\",\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | flightId | origin | destination | departureTime |\n * | --- | ---: | ---: | ---: | ---: | --- | --- | --- | --- |\n * | B | 0 | 1 | 1 | 1 | F3 | A | B | 2025-01-01 11:00:00 |\n * | B | 0 | 2 | 1 | 2 | F2 | C | A | 2025-01-01 10:00:00 |\n * | B | 0 | 3 | 1 | 3 | F1 | B | C | 2025-01-01 09:00:00 |\n *\n * For the next two examples, `flights` contains these rows, with departure\n * and arrival stored as timestamps on the same day:\n *\n * | flightId | origin | destination | departure | arrival | price |\n * | --- | --- | --- | --- | --- | ---: |\n * | F1 | A | B | 2025-01-01 09:00 | 2025-01-01 10:00 | 40 |\n * | F2 | B | A | 2025-01-01 12:00 | 2025-01-01 13:00 | 60 |\n *\n * Report elapsed time for every cycle, including layovers:\n *\n * @example\n * ```ts\n * await flights\n * .findCycles(\"origin\", \"destination\", \"flightId\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | --- | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | A | 0 | 1 | 1 | 1 | 3600000 | F1 | A | B | 2025-01-01 09:00:00 | 2025-01-01 10:00:00 | 40 |\n * | A | 0 | 2 | 1 | 2 | 14400000 | F2 | B | A | 2025-01-01 12:00:00 | 2025-01-01 13:00:00 | 60 |\n *\n * The return journey takes four hours (14,400,000 milliseconds),\n * including the two-hour layover at B.\n *\n * Add up prices while continuing to report elapsed time for every cycle:\n *\n * @example\n * ```ts\n * await flights\n * .findCycles(\"origin\", \"destination\", \"flightId\", \"A\", {\n * startTimeColumn: \"departure\",\n * endTimeColumn: \"arrival\",\n * minGapMs: 60 * 60 * 1000,\n * elapsedTime: true,\n * weight: \"price\",\n * })\n * .log();\n * ```\n *\n * | start | pathId | step | weight | total | elapsedTimeMs | flightId | origin | destination | departure | arrival | price |\n * | --- | ---: | ---: | ---: | ---: | ---: | --- | --- | --- | --- | --- | ---: |\n * | A | 0 | 1 | 40 | 40 | 3600000 | F1 | A | B | 2025-01-01 09:00:00 | 2025-01-01 10:00:00 | 40 |\n * | A | 0 | 2 | 60 | 100 | 14400000 | F2 | B | A | 2025-01-01 12:00:00 | 2025-01-01 13:00:00 | 60 |\n *\n * @param sourceColumn - The name of the column containing each connection's source node ID.\n * @param targetColumn - The name of the column containing each connection's target node ID.\n * @param edgeId - The name of the column uniquely identifying each connection (edge).\n * @param startNodes - One starting node ID or an array of IDs. Finds cycles that start and end at each requested node.\n * @param options - An optional object with direction, time, cost, and result configuration.\n * @param options.direction - The direction in which to follow connections. Defaults to `\"outgoing\"`.\n * @param options.startTimeColumn - The name of the column containing each connection's start time. Use this or `endTimeColumn` to follow connections in chronological order.\n * @param options.endTimeColumn - The name of the column containing each connection's end time. Use this or `startTimeColumn` to follow connections in chronological order.\n * @param options.minGapMs - The minimum gap between consecutive connections, in milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time column.\n * @param options.strictOrdering - Whether to reject zero-duration gaps between consecutive connections (equal timestamps). Defaults to `true`. Requires a time column.\n * @param options.weight - The name of the numeric column used as the cost of each connection. If omitted, each connection costs one.\n * @param options.elapsedTime - Whether to add cumulative `elapsedTimeMs` in milliseconds, including connection gaps. Defaults to `false`. Requires both time columns.\n * @param options.outputTable - If `true`, stores the result in a new table with a generated name. If a string, uses it as the new table's name. If `false` or omitted, overwrites the current table. Defaults to `false`.\n * @returns The result table, so methods can be chained.\n * @category Graph Operations\n */\n findCycles(\n sourceColumn: string,\n targetColumn: string,\n edgeId: string,\n startNodes: string | number | bigint | (string | number | bigint)[],\n options: {\n direction?: \"outgoing\" | \"incoming\" | \"both\";\n elapsedTime?: boolean;\n endTimeColumn?: string;\n minGapMs?: number;\n outputTable?: string | boolean;\n startTimeColumn?: string;\n strictOrdering?: boolean;\n weight?: string;\n } = {},\n ): SimpleTable {\n return findCycles(this, sourceColumn, targetColumn, edgeId, startNodes, options);\n }\n\n /**\n * Extracts one or more components from a temporal column into new columns.\n * Pass a single part to create a column with that part's name, or pass an\n * object mapping custom new-column names to parts. Existing columns are not\n * overwritten.\n *\n * `dayOfWeek` uses Sunday as `0` through Saturday as `6`. `week` follows\n * ISO week numbering, and `dayOfYear` starts at `1`. DuckDB `DATE`, `TIME`,\n * `TIMESTAMP`, and `TIMESTAMP WITH TIME ZONE` columns are supported when the\n * requested component applies to that type: date parts apply to dates and\n * timestamps, while time parts apply to times and timestamps. `NULL` input\n * values produce `NULL` extracted values. Parts extracted from\n * `TIMESTAMP WITH TIME ZONE` values use UTC.\n *\n * @example\n * ```ts\n * // Add a column named 'year' from the 'publishedAt' timestamp\n * await table.extractDatePart(\"publishedAt\", \"year\").log();\n * ```\n *\n * @example\n * ```ts\n * // Extract multiple components with custom column names\n * await table.extractDatePart(\"publishedAt\", {\n * publicationYear: \"year\",\n * publicationMonth: \"month\",\n * }).log();\n * ```\n * @param column - The temporal column from which to extract components.\n * @param parts - A part to extract using its name as the new column, or an object mapping each custom new-column name to the part it should contain.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n extractDatePart(\n column: string,\n parts:\n | \"year\"\n | \"quarter\"\n | \"month\"\n | \"week\"\n | \"day\"\n | \"dayOfWeek\"\n | \"dayOfYear\"\n | \"hour\"\n | \"minute\"\n | \"second\"\n | {\n [newColumn: string]:\n | \"year\"\n | \"quarter\"\n | \"month\"\n | \"week\"\n | \"day\"\n | \"dayOfWeek\"\n | \"dayOfYear\"\n | \"hour\"\n | \"minute\"\n | \"second\";\n },\n ): this {\n extractDatePart(this, column, parts);\n return this;\n }\n\n /**\n * Adds a new column to the table containing the row number, starting at 0 (like an index).\n *\n * @example\n * ```ts\n * // Add a new column named 'rowNumber' with the row number for each row\n * await table.addRowNumber(\"rowNumber\").log();\n * ```\n *\n * @example\n * ```ts\n * // Add a new column named 'rowNumber' with the row number for each 'category'\n * await table.addRowNumber(\"rowNumber\", { by: \"category\" }).log();\n * ```\n * @param newColumn - The name of the new column that will store the row number.\n * @param options - An optional object with configuration options:\n * @param options.by - A column name or an array of column names to partition by. The row number restarts at 0 within each group.\n * @returns The table, so methods can be chained.\n * @category Column Operations\n */\n addRowNumber(newColumn: string, options: { by?: string | string[] } = {}): this {\n addRowNumber(this, newColumn, options);\n return this;\n }\n\n /**\n * Performs a cross join operation with another table. A cross join returns the Cartesian product of the rows from both tables, meaning all possible pairs of rows will be in the resulting table.\n * This means that if the left table has `n` rows and the right table has `m` rows, the result will have `n * m` rows.\n *\n * @example\n * ```ts\n * // Perform a cross join with 'tableB', overwriting the current table (tableA)\n * await tableA.crossJoin(tableB).log();\n * ```\n *\n * @example\n * ```ts\n * // Perform a cross join with 'tableB' and store the results in a new table with a generated name\n * const tableC = await tableA.crossJoin(tableB, { outputTable: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Perform a cross join with 'tableB' and store the results in a new table named 'tableC'\n * const tableC = await tableA.crossJoin(tableB, { outputTable: \"tableC\" }).log();\n * ```\n * @param rightTable - The SimpleTable instance to cross join with.\n * @param options - An optional object with configuration options:\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the cross-joined data (either the current table or a new table), so methods can be chained.\n * @category Table Operations\n */\n crossJoin(\n rightTable: SimpleTable,\n options: {\n outputTable?: string | boolean;\n } = {},\n ): this {\n return crossJoin(this, rightTable, options) as this;\n }\n\n /**\n * Merges the data of this table (considered the left table) with another table (the right table) based on a common column or multiple columns.\n * Note that the order of rows in the returned data is not guaranteed to be the same as in the original tables.\n * This operation might create temporary files in a `.tmp` folder; consider adding `.tmp` to your `.gitignore`.\n *\n * @example\n * ```ts\n * // Perform a left join with 'tableB' on a common column (auto-detected), overwriting tableA\n * await tableA.join(tableB).log();\n * ```\n *\n * @example\n * ```ts\n * // Perform an inner join with 'tableB' on the 'id' column, storing results in a new table named 'tableC'\n * const tableC = await tableA.join(tableB, { on: \"id\", type: 'inner', outputTable: \"tableC\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Perform a join on multiple columns ('name' and 'category')\n * await tableA.join(tableB, { on: [\"name\", \"category\"] }).log();\n * ```\n * @param rightTable - The SimpleTable instance to be joined with this table.\n * @param options - An optional object with configuration options:\n * @param options.on - The column(s) to join on. If omitted, the method automatically searches for a column name that exists in both tables. Can be a single string or an array of strings for multiple join keys.\n * @param options.type - The type of join operation to perform. Possible values are `\"inner\"`, `\"left\"` (default), `\"right\"`, or `\"full\"`.\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the joined data (either the current table or a new table), so methods can be chained.\n * @category Table Operations\n */\n\n join(\n rightTable: SimpleTable,\n options: {\n on?: string | string[];\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n outputTable?: string | boolean;\n } = {},\n ): this {\n options = {\n ...options,\n on: Array.isArray(options.on) ? [...options.on] : options.on,\n };\n if (options.outputTable === true) {\n options.outputTable = `table${this.sdb.tableIncrement}`;\n this.sdb.tableIncrement += 1;\n }\n return join(this, rightTable, options) as this;\n }\n\n /**\n * Performs a fuzzy left join between this table (considered the left table) and another table\n * (the right table) based on string similarity between two text columns. Uses the\n * [rapidfuzz](https://query.farm/duckdb_extension_rapidfuzz) DuckDB community extension.\n *\n * If a similarity score column is added to the results, the rows will be ordered alphabetically by the left column, and then by descending similarity score within each group of identical left column values. Otherwise, the rows will be order alphabetically by the left column and then by the right column.\n *\n * This operation might create temporary files in a `.tmp` folder; consider adding `.tmp` to your `.gitignore`.\n *\n * @example\n * ```ts\n * // Fuzzy left join tableA with tableB on 'name' (left) and 'standardName' (right) with a threshold of 80\n * // A length-based pre-filter is automatically applied.\n * await tableA.fuzzyJoin(tableB, \"name\", \"standardName\", 80).log();\n * ```\n *\n * @example\n * ```ts\n * // Fuzzy join with a prefix-based pre-filter and a threshold of 80\n * await tableA.fuzzyJoin(tableB, \"name\", \"standardName\", 80, {\n * prefilterPrefixLength: 3, // Must share the same first 3 characters\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Fuzzy join with a custom threshold and method, storing results in a new table\n * const tableC = await tableA.fuzzyJoin(tableB, \"name\", \"standardName\", 90, {\n * method: \"token_sort_ratio\",\n * outputTable: \"tableC\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Fuzzy join with a custom similarity column name and a threshold of 80\n * await tableA.fuzzyJoin(tableB, \"name\", \"standardName\", 80, {\n * similarityColumn: \"matchScore\",\n * }).log();\n * ```\n * @param rightTable - The SimpleTable instance to be joined with this table.\n * @param leftColumn - The name of the column in this (left) table containing the text to compare.\n * @param rightColumn - The name of the column in the right table containing the text to compare.\n * @param threshold - The minimum similarity score (0–100) required for two rows to be joined. For `method: \"ratio\"`, a length-based pre-filter is automatically applied based on the threshold to improve performance without losing accuracy.\n * @param options - An optional object with configuration options:\n * @param options.method - The rapidfuzz similarity algorithm to use. Defaults to `\"ratio\"`.\n * - `\"ratio\"`: Overall similarity (Levenshtein-based).\n * - `\"partial_ratio\"`: Best partial/substring similarity.\n * - `\"token_sort_ratio\"`: Similarity after sorting tokens (words), useful for reordered words.\n * - `\"token_set_ratio\"`: Similarity based on sets of tokens, ignoring duplicates and word order.\n * @param options.similarityColumn - If provided, a column with this name is added to the result containing the similarity score (0–100). If omitted, the score is not included in the output.\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @param options.prefilterPrefixLength - An optional prefix length. Only strings sharing the same first N characters are compared. Note that prefix filtering is lossy (e.g. \"John\" vs. \"Phon\" will not match despite high similarity).\n * @returns A table instance containing the fuzzy-joined data (either the current table or a new table), so methods can be chained.\n * @category Table Operations\n */\n fuzzyJoin(\n rightTable: SimpleTable,\n leftColumn: string,\n rightColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n similarityColumn?: string;\n outputTable?: string | boolean;\n prefilterPrefixLength?: number;\n } = {},\n ): this {\n options = { ...options };\n if (options.outputTable === true) {\n options.outputTable = `table${this.sdb.tableIncrement}`;\n this.sdb.tableIncrement += 1;\n }\n return fuzzyJoin(this, rightTable, leftColumn, rightColumn, threshold, options) as this;\n }\n\n /**\n * Normalizes string values in a column by detecting fuzzy duplicates and replacing them with a single canonical value.\n *\n * Similar strings are grouped into clusters. Matching is transitive: if `\"New York\"` is similar to `\"New Yorke\"` and\n * `\"New Yorke\"` is similar to `\"New Yorkk\"`, all three land in the same cluster even if `\"New York\"` and `\"New Yorkk\"`\n * would not match directly. Each cluster is then collapsed to one representative value based on the `strategy` option.\n *\n * Similarity is computed using the [rapidfuzz](https://query.farm/duckdb_extension_rapidfuzz) DuckDB community extension,\n * which is installed and loaded automatically.\n *\n * @example\n * ```ts\n * // Normalize 'city' into a new 'cityClean' column, keeping the most common string per cluster with a threshold of 80\n * // A length-based pre-filter is automatically applied.\n * await table.fuzzyClean(\"city\", \"cityClean\", 80).log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize with a prefix-based pre-filter and a threshold of 80\n * await table.fuzzyClean(\"city\", \"cityClean\", 80, {\n * prefilterPrefixLength: 5, // Must share the same first 5 characters\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize 'companyName' into a new column using token_sort_ratio and a threshold of 90\n * await table.fuzzyClean(\"companyName\", \"companyNameClean\", 90, { method: \"token_sort_ratio\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize 'category' in-place, keeping the longest string in each cluster and a threshold of 80\n * await table.fuzzyClean(\"category\", \"category\", 80, { strategy: \"longestString\" }).log();\n * ```\n * @param column - The name of the column containing the strings to normalize.\n * @param newColumn - The name of the column to write the normalized values to. Use the same name as `column` to normalize in-place.\n * @param threshold - The minimum similarity score (0–100) for two strings to be considered duplicates. For `method: \"ratio\"`, a length-based pre-filter is automatically applied based on the threshold to improve performance without losing accuracy.\n * @param options - An optional object with configuration options:\n * @param options.method - The rapidfuzz similarity algorithm to use. Defaults to `\"ratio\"`.\n * - `\"ratio\"`: Overall similarity.\n * - `\"partial_ratio\"`: Best partial/substring similarity.\n * - `\"token_sort_ratio\"`: Similarity after sorting tokens (words), useful for reordered words.\n * - `\"token_set_ratio\"`: Similarity based on sets of tokens, ignoring duplicates and word order.\n * @param options.strategy - The strategy for choosing the canonical value within each cluster of similar strings. Defaults to `\"mostCommon\"`.\n * - `\"mostCommon\"`: Keep the value that appears most frequently in the original column.\n * - `\"longestString\"`: Keep the longest string in the cluster.\n * - `\"shortestString\"`: Keep the shortest string in the cluster.\n * - `\"mostCentral\"`: Keep the string with the highest total similarity score to all other cluster members (the most \"central\" string).\n * - `\"maxScore\"`: Keep the string that participates in the single highest-scoring pairwise match within the cluster.\n * @param options.prefilterPrefixLength - An optional prefix length. Only strings sharing the same first N characters are compared. Note that prefix filtering is lossy (e.g. \"John\" vs. \"Phon\" will not match despite high similarity).\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n fuzzyClean(\n column: string,\n newColumn: string,\n threshold: number,\n options: {\n method?: \"ratio\" | \"partial_ratio\" | \"token_sort_ratio\" | \"token_set_ratio\";\n strategy?: \"mostCommon\" | \"longestString\" | \"shortestString\" | \"mostCentral\" | \"maxScore\";\n prefilterPrefixLength?: number;\n } = {},\n ): this {\n fuzzyClean(this, column, newColumn, threshold, options);\n return this;\n }\n\n /**\n * Replaces specified strings in the selected columns.\n * Use `[\"all\"]` to target a column literally named `all`.\n *\n * @example\n * ```ts\n * // Replace all occurrences of \"kilograms\" with \"kg\" in 'column1'\n * await table.replace(\"column1\", { \"kilograms\": \"kg\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace \"kilograms\" with \"kg\" and \"liters\" with \"l\" in 'column1' and 'column2'\n * await table.replace([\"column1\", \"column2\"], { \"kilograms\": \"kg\", \"liters\": \"l\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace only if the entire string in 'column1' is \"kilograms\"\n * await table.replace(\"column1\", { \"kilograms\": \"kg\" }, { entireString: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace any sequence of one or more digits with a hyphen in 'column1' using regex\n * await table.replace(\"column1\", { \"\\d+\": \"-\" }, { regex: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace \"%\" with \"\" in all columns\n * await table.replace(\"all\", { \"%\": \"\" }).log();\n * ```\n * @param columns - The column name, an array of column names, or `\"all\"` to apply the replacement to every column in the table.\n * @param replacements - An object mapping old strings to new strings (e.g., `{ \"oldValue\": \"newValue\" }`).\n * @param options - An optional object with configuration options:\n * @param options.entireString - A boolean indicating whether the entire cell content must match the `oldString` for replacement to occur. Defaults to `false` (replaces substrings).\n * @param options.regex - A boolean indicating whether the `oldString` should be treated as a regular expression for global replacement. Cannot be used with `entireString: true`. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n replace(\n columns: string | string[],\n replacements: { [key: string]: string },\n options: {\n entireString?: boolean;\n regex?: boolean;\n } = {},\n ): this {\n replace(this, columns, replacements, options);\n return this;\n }\n\n /**\n * Converts string values in the specified columns to lowercase.\n *\n * @example\n * ```ts\n * // Convert strings in 'column1' to lowercase\n * await table.lower(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Convert strings in 'column1' and 'column2' to lowercase\n * await table.lower([\"column1\", \"column2\"]).log();\n * ```\n * @param columns - The column name or an array of column names to be converted to lowercase.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n lower(columns: string | string[]): this {\n lower(this, columns);\n return this;\n }\n\n /**\n * Converts string values in the specified columns to uppercase.\n *\n * @example\n * ```ts\n * // Convert strings in 'column1' to uppercase\n * await table.upper(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Convert strings in 'column1' and 'column2' to uppercase\n * await table.upper([\"column1\", \"column2\"]).log();\n * ```\n * @param columns - The column name or an array of column names to be converted to uppercase.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n upper(columns: string | string[]): this {\n upper(this, columns);\n return this;\n }\n\n /**\n * Capitalizes the first letter of each string in the specified columns and converts the rest of the string to lowercase.\n *\n * @example\n * ```ts\n * // Capitalize strings in 'column1' (e.g., \"hello world\" becomes \"Hello world\")\n * await table.capitalize(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Capitalize strings in 'column1' and 'column2'\n * await table.capitalize([\"column1\", \"column2\"]).log();\n * ```\n * @param columns - The column name or an array of column names to be capitalized.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n capitalize(columns: string | string[]): this {\n capitalize(this, columns);\n return this;\n }\n\n /**\n * Truncates string values in a specified column to a maximum number of characters.\n *\n * @example\n * ```ts\n * // Truncate strings in 'description' column to 50 characters\n * await table.truncate(\"description\", 50).log();\n * ```\n *\n * @example\n * ```ts\n * // Truncate strings in 'name' column to 10 characters\n * await table.truncate(\"name\", 10).log();\n * ```\n * @param column - The column name containing strings to be truncated.\n * @param length - The maximum number of characters to keep.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n truncate(column: string, length: number): this {\n truncate(this, column, length);\n return this;\n }\n\n /**\n * Pads the strings in the specified columns to a target length.\n *\n * The columns must contain string (VARCHAR) values. An error is thrown if any\n * column is of a different type. `null` values remain `null`. If any string\n * already exceeds the target length, an error is thrown (no silent truncation).\n *\n * @example\n * ```ts\n * // Left-pad 'id' column to 3 characters with zeros (default)\n * await table.pad(\"id\", 3).log();\n * // Result: '1' -> '001', '23' -> '023', null -> null\n * ```\n *\n * @example\n * ```ts\n * // Right-pad 'code' column to 5 characters with spaces\n * await table.pad(\"code\", 5, { side: \"right\", character: \" \" }).log();\n * // Result: '123' -> '123 ', '45' -> '45 ', null -> null\n * ```\n *\n * @example\n * ```ts\n * // Left-pad multiple columns to 5 characters with dashes\n * await table.pad([\"id\", \"code\"], 5, { side: \"left\", character: \"-\" }).log();\n * // Result: '1' -> '----1', '23' -> '---23'\n * ```\n * @param columns - The column name(s) containing strings to be padded.\n * @param length - The target length of the padded strings.\n * @param options - An optional object with configuration options:\n * @param options.side - Which side to pad. `'left'` (default) or `'right'`.\n * @param options.character - The character to use for padding. Defaults to `'0'`.\n * @returns The table, so methods can be chained.\n * @throws {Error} If any column is not of string (VARCHAR) type.\n * @throws {Error} If any string value exceeds the target length.\n * @category Updating Data\n */\n pad(\n columns: string | string[],\n length: number,\n options: { side?: \"left\" | \"right\"; character?: string } = {},\n ): this {\n pad(this, columns, length, options);\n return this;\n }\n\n /**\n * Splits strings in a specified column by a separator and extracts a substring at a given index, storing the result in a new or existing column.\n * If the index is out of bounds, an empty string will be returned for that row.\n *\n * @example\n * ```ts\n * // Split 'address' by comma and extract the second part (index 1) into a new 'city' column\n * // e.g., \"123 Main St, Anytown, USA\" -> \"Anytown\"\n * await table.splitExtract(\"address\", \",\", 1, \"city\").log();\n * ```\n *\n * @example\n * ```ts\n * // Split 'filename' by dot and extract the first part (index 0), overwriting 'filename'\n * // e.g., \"document.pdf\" -> \"document\"\n * await table.splitExtract(\"filename\", \".\", 0, \"filename\").log();\n * ```\n * @param column - The name of the column containing the strings to be split.\n * @param separator - The substring to use as a delimiter for splitting the strings.\n * @param index - The zero-based index of the substring to extract after splitting. For example, `0` for the first part, `1` for the second, etc.\n * @param newColumn - The name of the column where the extracted substrings will be stored. To overwrite the original column, use the same name as `column`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n splitExtract(column: string, separator: string, index: number, newColumn: string): this {\n splitExtract(this, column, separator, index, newColumn);\n return this;\n }\n\n /**\n * Splits strings in a specified column by a separator and spreads the resulting parts into multiple new columns.\n *\n * Each part of the split string will be stored in a separate column. The number of columns created is determined by the length of the `newColumns` array.\n * If a row has fewer parts than the number of new columns, a warning will be logged and the extra columns will contain empty strings (unless `strict` is set to `false`).\n * If a row has more parts than the number of new columns, an error will be thrown unless `strict` is set to `false`.\n *\n * @example\n * ```ts\n * // Split 'fullName' by comma and spread into 'lastName' and 'firstName'\n * // e.g., \"Shiab, Nael\" -> lastName: \"Shiab\", firstName: \"Nael\"\n * await table.splitSpread(\"fullName\", \",\", [\"lastName\", \"firstName\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Split 'address' by comma and spread into three columns\n * // e.g., \"123 Main St, Anytown, USA\" -> street: \"123 Main St\", city: \"Anytown\", country: \"USA\"\n * await table.splitSpread(\"address\", \",\", [\"street\", \"city\", \"country\"]).log();\n * ```\n *\n * @example\n * ```ts\n * // Skip validation for performance\n * await table.splitSpread(\"data\", \"|\", [\"col1\", \"col2\"], { strict: false }).log();\n * ```\n * @param column - The name of the column containing the strings to be split.\n * @param separator - The substring to use as a delimiter for splitting the strings.\n * @param newColumns - An array of column names for the extracted parts.\n * @param options - Optional configuration.\n * @param options.strict - If `false`, skips all validation checks (both max and min parts). Defaults to `true`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n splitSpread(\n column: string,\n separator: string,\n newColumns: string[],\n options: {\n strict?: boolean;\n } = {},\n ): this {\n splitSpread(this, column, separator, newColumns, options);\n return this;\n }\n\n /**\n * Extracts a specific number of characters from the beginning (left side) of string values in the specified column.\n *\n * @example\n * ```ts\n * // Replace strings in 'productCode' with their first two characters\n * // e.g., \"ABC-123\" becomes \"AB\"\n * await table.firstChars(\"productCode\", 2).log();\n * ```\n * @param column - The name of the column containing the strings to be modified.\n * @param count - The number of characters to extract from the left side of each string.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n firstChars(column: string, count: number): this {\n firstChars(this, column, count);\n return this;\n }\n\n /**\n * Extracts a specific number of characters from the end (right side) of string values in the specified column.\n *\n * @example\n * ```ts\n * // Replace strings in 'productCode' with their last two characters\n * // e.g., \"ABC-123\" becomes \"23\"\n * await table.lastChars(\"productCode\", 2).log();\n * ```\n * @param column - The name of the column containing the strings to be modified.\n * @param count - The number of characters to extract from the right side of each string.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n lastChars(column: string, count: number): this {\n lastChars(this, column, count);\n return this;\n }\n\n /**\n * Replaces `NULL` values in the specified columns with a given value.\n * Use `[\"all\"]` to target a column literally named `all`.\n *\n * @example\n * ```ts\n * // Replace NULL values in 'column1' with 0\n * await table.replaceNulls(\"column1\", 0).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace NULL values in 'columnA' and 'columnB' with the string \"N/A\"\n * await table.replaceNulls([\"columnA\", \"columnB\"], \"N/A\").log();\n * ```\n *\n * @example\n * ```ts\n * // Replace NULL values in 'dateColumn' with a specific date\n * await table.replaceNulls(\"dateColumn\", new Date(\"2023-01-01\")).log();\n * ```\n *\n * @example\n * ```ts\n * // Replace NULL values in all columns with 0\n * await table.replaceNulls(\"all\", 0).log();\n * ```\n * @param columns - The column name, an array of column names, or `\"all\"` to apply the replacement to every column in the table.\n * @param value - The value to replace `NULL` occurrences with.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n replaceNulls(columns: string | string[], value: unknown): this {\n replaceNulls(this, columns, value);\n return this;\n }\n\n /**\n * Concatenates values from specified columns into a new column.\n *\n * @example\n * ```ts\n * // Concatenate 'firstName' and 'lastName' into a new 'fullName' column\n * await table.concatenate([\"firstName\", \"lastName\"], \"fullName\").log();\n * ```\n *\n * @example\n * ```ts\n * // Concatenate 'city' and 'country' into 'location', separated by a comma and space\n * await table.concatenate([\"city\", \"country\"], \"location\", { separator: \", \" }).log();\n * ```\n * @param columns - An array of column names whose values will be concatenated.\n * @param newColumn - The name of the new column to store the concatenated values.\n * @param options - An optional object with configuration options:\n * @param options.separator - The string used to separate concatenated values. Defaults to an empty string (`\"\"`).\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n concatenate(\n columns: string[],\n newColumn: string,\n options: {\n separator?: string;\n } = {},\n ): this {\n concatenate(this, columns, newColumn, options);\n return this;\n }\n\n /**\n * Concatenates values from multiple columns into a new column with labeled rows.\n *\n * This method creates a new column where each value is a concatenation of the specified columns,\n * with each column value prefixed by its column name and a colon, followed by a newline.\n * Column entries are separated by double newlines (\"\\n\\n\").\n *\n * All values must be string, otherwise an error will be thrown. Use the `convert()` method first to convert non-string columns to string.\n *\n * If a column value is `NULL`, it will be replaced by `'Unknown'` in the concatenated result.\n *\n * @example\n * ```ts\n * // Concatenate multiple string columns into a labeled text field\n * await table.rowToText(\n * [\"summary\", \"findings\", \"context\", \"date\", \"quote\"],\n * \"fullText\"\n * ).log();\n * // Result in \"fullText\" will look like:\n * // summary:\n * // [value]\n * //\n * // findings:\n * // [value]\n * //\n * // context:\n * // [value]\n * //\n * // date:\n * // [value]\n * //\n * // quote:\n * // [value]\n * ```\n *\n * @example\n * ```ts\n * // Convert numeric columns to strings first, then concatenate\n * // NULL values will appear as 'Unknown'\n * await table\n * .convert({ age: \"string\", salary: \"string\" })\n * .rowToText([\"name\", \"age\", \"salary\"], \"profile\").log();\n * ```\n * @param columns - An array of column names whose values will be concatenated with labels.\n * @param newColumn - The name of the new column to create with the concatenated values.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n rowToText(columns: string[], newColumn: string): this {\n rowToText(this, columns, newColumn);\n return this;\n }\n\n /**\n * Combines numeric scalar columns into a fixed-size vector. The input\n * column order determines the vector dimension order, and null values remain\n * null vector elements.\n *\n * When all input columns have the same numeric type, that type is preserved.\n * Mixed numeric types require an explicit `type` option. Casting exact\n * decimals or large integers to FLOAT or DOUBLE can lose precision.\n *\n * @example\n * ```ts\n * await table\n * .rowToVector([\"height\", \"weight\"], \"measurements\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * await table\n * .rowToVector([\"count\", \"score\"], \"features\", { type: \"double\" })\n * .log();\n * ```\n * @param columns - Numeric scalar columns to combine, in vector dimension order.\n * @param newColumn - The name of the vector column to create.\n * @param options - Optional vector element type settings.\n * @param options.type - Cast every element to `\"float\"` or `\"double\"`. Required when the input column types differ.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n rowToVector(\n columns: string[],\n newColumn: string,\n options: {\n type?: \"float\" | \"double\";\n } = {},\n ): this {\n rowToVector(this, columns, newColumn, options);\n return this;\n }\n\n /**\n * Normalizes a numeric vector column. By default, each dimension is scaled\n * independently to `[0, 1]` across rows: all first elements together, all\n * second elements together, and so on. With `normalization: \"rowL2\"`, each\n * row is scaled to Euclidean unit length while preserving its direction;\n * zero vectors remain zero.\n *\n * The input may be a numeric LIST or fixed-size ARRAY. The output is a\n * fixed-size DOUBLE ARRAY. Converting large integers and exact decimals to\n * DOUBLE can lose precision. With `\"dimensionMinMax\"`, a dimension whose\n * converted values are all equal cannot be normalized.\n *\n * @example\n * ```ts\n * // Scale each dimension across rows to [0, 1] in a new column.\n * await table\n * .normalizeVector(\"features\", \"scaledFeatures\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Replace each vector with its unit-length version; zero vectors stay zero.\n * await table\n * .normalizeVector(\"features\", \"features\", { normalization: \"rowL2\" })\n * .log();\n * ```\n * @param column - The numeric vector column to normalize.\n * @param newColumn - The output column. Use the source column's name to\n * replace the source column with the normalized DOUBLE vector.\n * @param options - Normalization settings.\n * @param options.normalization - `\"dimensionMinMax\"` scales each dimension\n * across rows; `\"rowL2\"` scales each row to unit length. Defaults to\n * `\"dimensionMinMax\"`.\n * @returns The table, so methods can be chained.\n * @category Vector Operations\n */\n normalizeVector(\n column: string,\n newColumn: string,\n options: { normalization?: \"dimensionMinMax\" | \"rowL2\" } = {},\n ): this {\n normalizeVector(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Measures numeric profile similarity using each row's Mahalanobis distance\n * from a supplied reference point and stores it in a new DOUBLE column.\n * Smaller distances indicate more similar profiles. Optionally adds a\n * dataset-relative similarity score, where larger values mean more similar.\n * Sample covariance (`n - 1`) is estimated from the dataset, independently\n * of the reference point.\n *\n * Accounts for differences in feature scales and correlations between features,\n * making it useful for comparing profiles with measurements in different units.\n *\n * Pass one numeric LIST or ARRAY column, or an array of numeric scalar columns.\n * Reference arrays follow the same dimension order. For scalar columns, a\n * reference object supplies its own finite numeric values by column name; extra\n * fields are ignored. Reference values are captured when this method is called.\n * Inputs are converted privately to DOUBLE, which can lose precision for large\n * integers and exact\n * decimals; source columns and types remain unchanged.\n *\n * Requires more rows than dimensions and finite, non-null, consistent features\n * with invertible, numerically stable covariance. Invalid inputs leave the\n * source unchanged.\n *\n * @example\n * ```ts\n * // Measure distance from a reference height and weight.\n * await table\n * .similarityMahalanobis([\"height\", \"weight\"], [175, 70], \"distance\")\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Compare feature vectors and add a dataset-relative similarity score.\n * await table\n * .similarityMahalanobis(\"features\", [175, 70], \"distance\", {\n * similarityColumn: \"similarity\",\n * })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Compare profiles directly with a row and use the default score column.\n * const reference = await table.getRow(\"name === 'Alex'\");\n * await table\n * .similarityMahalanobis([\"height\", \"weight\"], reference, \"distance\", {\n * similarityColumn: true,\n * })\n * .log();\n * ```\n * @param columns - A numeric vector column, or numeric scalar columns in feature order.\n * @param referencePoint - An array of finite numbers in feature order, or an object with an own finite numeric value for each scalar feature column; may be outside the dataset.\n * @param newColumn - The name of the new DOUBLE distance column.\n * @param options - Optional output settings.\n * @param options.similarityColumn - A custom name, or true for a new DOUBLE column named \"similarity\"; false or omitted adds no score. The dataset-relative\n * score is `1 - distance / maxDistance`. Exact matches score 1 and the farthest\n * rows score 0; if all distances are zero, every score is 1.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n similarityMahalanobis(\n columns: string | string[],\n referencePoint: number[] | { [key: string]: unknown },\n newColumn: string,\n options: { similarityColumn?: string | boolean } = {},\n ): this {\n similarityMahalanobis(this, columns, referencePoint, newColumn, options);\n return this;\n }\n\n /**\n * Unnests (expands) rows by splitting a column's string values into multiple rows based on a separator.\n *\n * Each value in the specified column is split using the provided separator, and a new row is created for each resulting substring. All other column values are duplicated across the newly created rows.\n *\n * @example\n * ```ts\n * // Unnest 'tags' column separated by commas\n * // Before: [{ id: 1, tags: \"red,blue,green\" }]\n * // After: [{ id: 1, tags: \"red\" }, { id: 1, tags: \"blue\" }, { id: 1, tags: \"green\" }]\n * await table.unnest(\"tags\", \",\").log();\n * ```\n *\n * @example\n * ```ts\n * // Unnest 'neighborhoods' column separated by \" / \"\n * // Before: [{ city: \"Montreal\", neighborhoods: \"Old Montreal / Chinatown / Griffintown\" }]\n * // After: [{ city: \"Montreal\", neighborhoods: \"Old Montreal\" },\n * // { city: \"Montreal\", neighborhoods: \"Chinatown\" },\n * // { city: \"Montreal\", neighborhoods: \"Griffintown\" }]\n * await table.unnest(\"neighborhoods\", \" / \").log();\n * ```\n * @param column - The name of the column containing string values to be split and unnested.\n * @param separator - The delimiter string used to split the column values.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n unnest(column: string, separator: string): this {\n unnest(this, column, separator);\n return this;\n }\n\n /**\n * Repeats rows based on the values in a column.\n *\n * If a row has a value of 3 in the specified column, it will be repeated 3 times. If the value is 0 or negative, the row will be removed.\n *\n * @example\n * ```ts\n * // Before: [{ id: 1, count: 2, category: \"A\" }, { id: 2, count: 3, category: \"B\" }]\n * await table.repeatRows(\"count\").log();\n * // After: [{ id: 1, count: 2, category: \"A\" }, { id: 1, count: 2, category: \"A\" },\n * // { id: 2, count: 3, category: \"B\" }, { id: 2, count: 3, category: \"B\" }, { id: 2, count: 3, category: \"B\" }]\n * ```\n *\n * @example\n * ```ts\n * // With an index column\n * await table.repeatRows(\"count\", { index: \"copyId\" }).log();\n * // After: [{ id: 1, count: 2, category: \"A\", copyId: 0 }, { id: 1, count: 2, category: \"A\", copyId: 1 },\n * // { id: 2, count: 3, category: \"B\", copyId: 0 }, { id: 2, count: 3, category: \"B\", copyId: 1 }, { id: 2, count: 3, category: \"B\", copyId: 2 }]\n * ```\n * @param column - The name of the column containing the number of times each row should be repeated.\n * @param options - An optional object with configuration options:\n * @param options.index - The name of a new column to store the index of the repeated row (starting at 0).\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n repeatRows(column: string, options: { index?: string } = {}): this {\n repeatRows(this, column, options);\n return this;\n }\n\n /**\n * Nests (collapses) rows by aggregating a column's values into a single string per group, separated by a delimiter.\n *\n * This is the inverse operation of `unnest()`. Multiple rows are combined into fewer rows by grouping on specified category columns and concatenating the target column values with a separator.\n *\n * @example\n * ```ts\n * // Nest 'neighborhoods' column separated by \" / \" for each city\n * // Before: [{ city: \"Montreal\", neighborhoods: \"Old Montreal\" },\n * // { city: \"Montreal\", neighborhoods: \"Chinatown\" },\n * // { city: \"Montreal\", neighborhoods: \"Griffintown\" }]\n * // After: [{ city: \"Montreal\", neighborhoods: \"Old Montreal / Chinatown / Griffintown\" }]\n * await table.nest(\"neighborhoods\", \" / \", \"city\").log();\n * ```\n *\n * @example\n * ```ts\n * // Nest with multiple category columns\n * // Before: [{ country: \"Canada\", city: \"Montreal\", tags: \"red\" },\n * // { country: \"Canada\", city: \"Montreal\", tags: \"blue\" }]\n * // After: [{ country: \"Canada\", city: \"Montreal\", tags: \"red,blue\" }]\n * await table.nest(\"tags\", \",\", [\"country\", \"city\"]).log();\n * ```\n * @param column - The name of the column whose values will be aggregated and concatenated.\n * @param separator - The delimiter string used to join the column values.\n * @param by - The column name or an array of column names to group by.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n nest(column: string, separator: string, by: string | string[]): this {\n nest(this, column, separator, by);\n return this;\n }\n\n /**\n * Rounds numeric values in specified columns.\n *\n * @example\n * ```ts\n * // Round 'column1' values to the nearest integer\n * await table.round(\"column1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Round 'column1' values to 2 decimal places\n * await table.round(\"column1\", { decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Round 'column1' values down to the nearest integer (floor)\n * await table.round(\"column1\", { method: \"floor\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Round 'columnA' and 'columnB' values to 1 decimal place using ceiling method\n * await table.round([\"columnA\", \"columnB\"], { decimals: 1, method: \"ceiling\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Round 'column1' values to 2 decimal places using the shorthand\n * await table.round(\"column1\", 2).log();\n * ```\n * @param columns - The column name or an array of column names containing numeric values to be rounded.\n * @param options - An optional integer specifying the number of decimal places, or an object with configuration options:\n * @param options.decimals - The number of decimal places to round to. Defaults to `0` (rounds to the nearest integer).\n * @param options.method - The rounding method to use: `\"round\"` (rounds to the nearest integer, with halves rounding up), `\"ceiling\"` (rounds up to the nearest integer), or `\"floor\"` (rounds down to the nearest integer). Defaults to `\"round\"`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n round(\n columns: string | string[],\n options:\n | number\n | {\n decimals?: number;\n method?: \"round\" | \"ceiling\" | \"floor\";\n } = {},\n ): this {\n round(this, columns, options);\n return this;\n }\n\n /**\n * Adds independently generated uniform random noise to numeric values in one or more columns.\n * Each changed value receives an offset between `-max` and `max`. Selected integer and decimal columns become `DOUBLE` columns so fractional noise is retained. This method adds random jitter; it does not provide anonymization or differential privacy guarantees.\n *\n * @example\n * ```ts\n * // Add an offset between -0.01 and 0.01 to every value\n * await table.addNoise(\"measurement\", 0.01).log();\n * ```\n *\n * @example\n * ```ts\n * // Add noise independently to duplicated x values and duplicated y values\n * await table.addNoise([\"x\", \"y\"], 0.1, {\n * onlyDuplicates: true,\n * }).log();\n * ```\n * @param columns - The numeric column name or array of numeric column names to which noise will be added. When multiple columns are provided, each value receives an independent random offset.\n * @param max - The maximum absolute offset, expressed in each column's units. Must be a finite number greater than or equal to `0`.\n * @param options - An optional object with configuration options:\n * @param options.onlyDuplicates - If `true`, adds noise only to values that occur more than once in their column. Each selected column is evaluated independently, and every occurrence of a duplicated value is changed. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n addNoise(\n columns: string | string[],\n max: number,\n options: { onlyDuplicates?: boolean } = {},\n ): this {\n addNoise(this, columns, max, options);\n return this;\n }\n\n /**\n * Updates values in a specified column using a SQL expression.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, expressions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Update 'column1' with the left 5 characters of 'column2'\n * await table.updateColumn(\"column1\", `LEFT(column2, 5)`).log();\n * ```\n *\n * @example\n * ```ts\n * // Double the values in 'price' column\n * await table.updateColumn(\"price\", `price * 2`).log();\n * ```\n *\n * @example\n * ```ts\n * // Set 'status' to 'active' where 'isActive' is true\n * await table.updateColumn(\"status\", `CASE WHEN isActive THEN 'active' ELSE 'inactive' END`).log();\n * ```\n *\n * @example\n * ```ts\n * // Update an existing column with a value from a JSON object using dot notation.\n * await table.loadArray([{ count: 0, details: { count: 3 } }], {\n * columnTypes: { details: \"JSON\" },\n * })\n * .updateColumn(\"count\", \"details.count\")\n * .log();\n * ```\n * @param column - The name of the column to be updated.\n * @param definition - The SQL expression used to set the new values in the column (e.g., `\"column1 * 2\"`, `\"UPPER(column_name)\"`).\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n updateColumn(column: string, definition: string): this {\n updateColumn(this, column, definition);\n return this;\n }\n\n /**\n * Assigns ranks to rows in a new column based on the values of a specified column.\n *\n * @example\n * ```ts\n * // Compute ranks in a new 'rank' column based on 'score' values (ascending)\n * await table.ranks(\"score\", \"rank\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute ranks in a new 'descRank' column based on 'score' values (descending)\n * await table.ranks(\"score\", \"descRank\", { order: \"desc\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute ranks by 'department', based on 'salary' values, without gaps\n * await table.ranks(\"salary\", \"salaryRank\", { by: \"department\", dense: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute ranks by both 'department' and 'city'\n * await table.ranks(\"sales\", \"salesRank\", { by: [\"department\", \"city\"] }).log();\n * ```\n * @param column - The column containing the values to be used for ranking.\n * @param newColumn - The name of the new column where the ranks will be stored.\n * @param options - An optional object with configuration options:\n * @param options.order - The order of values for ranking: `\"asc\"` for ascending (default) or `\"desc\"` for descending.\n * @param options.by - The column name or an array of column names to rank by. Ranks are assigned independently within each group.\n * @param options.dense - A boolean indicating whether to use dense ranking (no gaps). If `true`, ranks will be consecutive integers (e.g., 1, 2, 2, 3). If `false` (default), ranks might have gaps (e.g., 1, 2, 2, 4).\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n ranks(\n column: string,\n newColumn: string,\n options: {\n order?: \"asc\" | \"desc\";\n by?: string | string[];\n dense?: boolean;\n } = {},\n ): this {\n ranks(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Assigns quantiles to rows in a new column based on specified column values.\n *\n * @example\n * ```ts\n * // Assigns a quantile from 1 to 10 for each row in a new 'quantiles' column, based on 'column1' values.\n * await table.quantiles(\"column1\", 10, \"quantiles\").log();\n * ```\n *\n * @example\n * ```ts\n * // Assign quantiles by 'column2', based on 'column1' values.\n * await table.quantiles(\"column1\", 10, \"quantiles\", { by: \"column2\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Assigns quartiles (4 quantiles) to 'sales' data, storing results in 'salesQuartile'\n * await table.quantiles(\"sales\", 4, \"salesQuartile\").log();\n * ```\n * @param column - The column containing values from which quantiles will be assigned.\n * @param count - The number of quantiles to divide the data into (e.g., `4` for quartiles, `10` for deciles).\n * @param newColumn - The name of the new column where the assigned quantiles will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Quantiles are assigned independently within each group.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n quantiles(\n column: string,\n count: number,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n ): this {\n quantiles(this, column, count, newColumn, options);\n return this;\n }\n\n /**\n * Adds numeric start and end columns for bins of the specified interval size.\n * Each bin includes its start and excludes its end: `start <= value < end`.\n * A value exactly on an end boundary belongs to the next bin. Null source\n * values produce null in both output columns.\n *\n * @example\n * ```ts\n * // If the minimum is 5, bins have boundaries 5 and 15, 15 and 25, etc.\n * await table.bins(\"column1\", 10, \"binStart\", \"binEnd\").log();\n * ```\n *\n * @example\n * ```ts\n * // Bins start at 0: a value of 10 has binStart 10 and binEnd 20.\n * await table\n * .bins(\"column1\", 10, \"binStart\", \"binEnd\", { startValue: 0 })\n * .log();\n * ```\n * @param column - The numeric column containing values from which bins will be computed.\n * @param interval - The finite, positive interval size for binning the values.\n * @param startColumn - The required name of the new numeric column containing inclusive bin starts.\n * @param endColumn - The required name of the new numeric column containing exclusive bin ends. Must differ from startColumn.\n * @param options - An optional object with configuration options:\n * @param options.startValue - The finite starting value for binning, no greater than the minimum source value. Defaults to the minimum value in the specified column.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n bins(\n column: string,\n interval: number,\n startColumn: string,\n endColumn: string,\n options: {\n startValue?: number;\n } = {},\n ): this {\n bins(this, column, interval, startColumn, endColumn, options);\n return this;\n }\n\n /**\n * Computes proportions horizontally across specified columns for each row.\n *\n * For example, given a table showing counts of men, women, and non-binary individuals per year:\n *\n * | Year | Men | Women | NonBinary |\n * | :--- | :-- | :---- | :-------- |\n * | 2021 | 564 | 685 | 145 |\n * | 2022 | 354 | 278 | 56 |\n * | 2023 | 856 | 321 | 221 |\n *\n * This method computes the proportion of men, women, and non-binary individuals on each row, adding new columns for these proportions.\n *\n * @example\n * ```ts\n * // Compute horizontal proportions for 'Men', 'Women', and 'NonBinary' columns, rounded to 2 decimal places\n * await table.rowProportions([\"Men\", \"Women\", \"NonBinary\"], { decimals: 2 }).log();\n * ```\n *\n * The table will then look like this:\n *\n * | Year | Men | Women | NonBinary | MenPerc | WomenPerc | NonBinaryPerc |\n * | :--- | :-- | :---- | :-------- | :------ | :-------- | :------------ |\n * | 2021 | 564 | 685 | 145 | 0.4 | 0.49 | 0.10 |\n * | 2022 | 354 | 278 | 56 | 0.51 | 0.4 | 0.08 |\n * | 2023 | 856 | 321 | 221 | 0.61 | 0.23 | 0.16 |\n *\n * By default, the new columns will be named with a suffix of `\"Perc\"`. You can customize this suffix using the `suffix` option.\n *\n * @example\n * ```ts\n * // Compute horizontal proportions with a custom suffix \"Prop\"\n * await table.rowProportions([\"Men\", \"Women\", \"NonBinary\"], { suffix: \"Prop\", decimals: 2 }).log();\n * ```\n *\n * The table will then look like this:\n *\n * | Year | Men | Women | NonBinary | MenProp | WomenProp | NonBinaryProp |\n * | :--- | :-- | :---- | :-------- | :------ | :-------- | :------------ |\n * | 2021 | 564 | 685 | 145 | 0.4 | 0.49 | 0.10 |\n * | 2022 | 354 | 278 | 56 | 0.51 | 0.4 | 0.08 |\n * | 2023 | 856 | 321 | 221 | 0.61 | 0.23 | 0.16 |\n *\n * @example\n * ```ts\n * // Compute percentages that sum to 100 on each row before rounding\n * await table.rowProportions([\"Men\", \"Women\", \"NonBinary\"], { base: 100, decimals: 1 }).log();\n * ```\n *\n * @param columns - An array of column names for which proportions will be computed on each row.\n * @param options - An optional object with configuration options:\n * @param options.suffix - A string suffix to append to the names of the new columns storing the computed proportions. Defaults to `\"Perc\"`.\n * @param options.base - A finite positive value that the proportions in each row sum to before rounding. Defaults to `1`.\n * @param options.decimals - The number of decimal places to round the computed proportions. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n rowProportions(\n columns: string[],\n options: {\n suffix?: string;\n base?: number;\n decimals?: number;\n } = {},\n ): this {\n rowProportions(this, columns, options);\n return this;\n }\n\n /**\n * Selects a ranked numeric value within each row and adds its source column\n * name, its value, or both as new columns.\n *\n * Values are ranked from highest to lowest by default. Null values are\n * ignored. By default, a tie at the requested rank throws an error. Set\n * `options.ties` to `\"first\"` to select the first tied column in the supplied\n * order, or to `\"all\"` to produce one row for each tied column. The `\"all\"`\n * option can therefore increase the table's row count. If null values leave\n * a row without the requested rank, the new columns contain null.\n *\n * @example\n * ```ts\n * // Add the name and value of the highest-scoring party on each row.\n * await table.rowRanks([\"CAQ\", \"PLQ\", \"PQ\"], {\n * nameColumn: \"winner\",\n * valueColumn: \"winningVotes\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Add only the second-lowest value on each row.\n * await table.rowRanks([\"CAQ\", \"PLQ\", \"PQ\"], {\n * valueColumn: \"secondLowestVotes\",\n * rank: 2,\n * order: \"asc\",\n * }).log();\n * ```\n * @param columns - The numeric columns to rank within each row.\n * @param options - The output columns and ranking configuration. At least one of `nameColumn` or `valueColumn` is required.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n rowRanks(\n columns: string[],\n options: (\n | {\n /**\n * The name of a new column containing the selected source column's name.\n *\n * @example\n * ```ts\n * { nameColumn: \"winner\" }\n * ```\n */\n nameColumn: string;\n /**\n * The name of a new column containing the selected source column's value.\n *\n * @example\n * ```ts\n * { valueColumn: \"winningVotes\" }\n * ```\n */\n valueColumn?: string;\n }\n | {\n /**\n * The name of a new column containing the selected source column's name.\n *\n * @example\n * ```ts\n * { nameColumn: \"winner\" }\n * ```\n */\n nameColumn?: string;\n /**\n * The name of a new column containing the selected source column's value.\n *\n * @example\n * ```ts\n * { valueColumn: \"winningVotes\" }\n * ```\n */\n valueColumn: string;\n }\n ) & {\n /**\n * The one-based rank to select. Must not exceed the number of supplied\n * columns. Defaults to `1`.\n *\n * @example\n * ```ts\n * { rank: 2 }\n * ```\n */\n rank?: number;\n /**\n * The ranking order: `\"desc\"` ranks the highest value first and `\"asc\"`\n * ranks the lowest value first. Defaults to `\"desc\"`.\n *\n * @example\n * ```ts\n * { order: \"asc\" }\n * ```\n */\n order?: \"asc\" | \"desc\";\n /**\n * How to handle a tie at the requested rank: `\"strict\"` throws, `\"first\"`\n * selects the first supplied column, and `\"all\"` produces one row per\n * tied column. Defaults to `\"strict\"`.\n *\n * @example\n * ```ts\n * { ties: \"all\" }\n * ```\n */\n ties?: \"strict\" | \"first\" | \"all\";\n },\n ): this {\n rowRanks(this, columns, options);\n return this;\n }\n\n /**\n * Computes proportions vertically over a column's values, relative to the sum of all values in that column or group.\n *\n * @example\n * ```ts\n * // Add a new column 'perc' with each 'column1' value divided by the sum of all 'column1' values\n * await table.columnProportions(\"column1\", \"perc\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute proportions for 'column1' by 'column2', rounded to two decimal places\n * await table.columnProportions(\"column1\", \"perc\", { by: \"column2\", decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute percentages that sum to 100 before rounding\n * await table.columnProportions(\"sales\", \"sales_percentage\", { base: 100, decimals: 1 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute proportions for 'sales' by 'region' and 'product_type'\n * await table.columnProportions(\"sales\", \"sales_proportion\", { by: [\"region\", \"product_type\"] }).log();\n * ```\n * @param column - The column containing values for which proportions will be computed. The proportions are calculated based on the sum of values in the specified column.\n * @param newColumn - The name of the new column where the proportions will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Proportions are calculated independently within each group.\n * @param options.base - A finite positive value that the proportions in the column or each group sum to before rounding. Defaults to `1`.\n * @param options.decimals - The number of decimal places to round the computed proportions. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n columnProportions(\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n base?: number;\n decimals?: number;\n } = {},\n ): this {\n columnProportions(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Creates a summary table from selected columns, optionally grouped by other columns.\n * This method allows you to aggregate data, calculate statistics (e.g., count, mean, sum), and group results by categorical columns.\n *\n * @example\n * ```ts\n * // Summarize all columns with all available statistics, overwriting the current table\n * const columns = await table.getColumns();\n * await table.summarize({ columns }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize all columns and store the results in a new table with a generated name\n * const columns = await table.getColumns();\n * const summaryTable = await table.summarize({ columns, outputTable: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize all columns and store the results in a new table named 'mySummary'\n * const columns = await table.getColumns();\n * const mySummaryTable = await table.summarize({ columns, outputTable: \"mySummary\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize a single column ('sales') with all available statistics\n * await table.summarize({ columns: \"sales\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize multiple columns ('sales' and 'profit') with all available statistics\n * await table.summarize({ columns: [\"sales\", \"profit\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'sales' by 'region' (single category)\n * await table.summarize({ columns: \"sales\", by: \"region\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'sales' by 'region' and 'product_type'\n * await table.summarize({ columns: \"sales\", by: [\"region\", \"product_type\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'sales' by 'region' with a specific statistic (mean)\n * await table.summarize({ columns: \"sales\", by: \"region\", stats: \"mean\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'sales' by 'region' with specific statistics (mean and sum)\n * await table.summarize({ columns: \"sales\", by: \"region\", stats: [\"mean\", \"sum\"] }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'sales' by 'region' with custom named statistics\n * await table.summarize({ columns: \"sales\", by: \"region\", stats: { averageSales: \"mean\", totalSales: \"sum\" } }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'price' and 'cost', rounding aggregated columns to 2 decimal places\n * await table.summarize({ columns: [\"price\", \"cost\"], decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Summarize 'timestamp_column' by converting to milliseconds first\n * await table.summarize({ columns: \"timestamp_column\", datesToMs: true, stats: \"mean\" }).log();\n * ```\n * @param options - An object with configuration options for summarization:\n * @param options.columns - The column name or an array of column names to summarize. If omitted, only the row count is returned.\n * @param options.by - The column name or an array of column names to group by.\n * @param options.stats - The statistics to compute. Can be a single statistic (e.g., `\"mean\"`), an array (e.g., `[\"min\", \"max\"]`), or an object mapping output column names to statistics (e.g., `{ avgSalary: \"mean\" }`). Supported statistics are `\"count\"`, `\"countDistinct\"`, `\"countNull\"`, `\"min\"`, `\"max\"`, `\"mean\"`, `\"median\"`, `\"sum\"`, `\"skew\"`, `\"stdDev\"`, and `\"variance\"`.\n * @param options.decimals - The number of decimal places to round the summarized columns. Defaults to `undefined` (no rounding).\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @param options.datesToMs - If `true`, timestamps, dates, and times will be converted to milliseconds before summarizing. This is useful when summarizing mixed data types (numbers and dates) as columns must be of the same type for aggregation.\n * @returns A table instance containing the summarized data (either the current table or a new table), so methods can be chained. When summarizing more than one column, a `column` column identifies which input column each row summarizes.\n * @category Analyzing Data\n */\n summarize(\n options: {\n columns?: string | string[];\n by?: string | string[];\n stats?:\n | (\n | \"count\"\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\"\n )\n | (\n | \"count\"\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\"\n )[]\n | {\n [key: string]:\n | \"count\"\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\";\n };\n decimals?: number;\n outputTable?: string | boolean;\n datesToMs?: boolean;\n } = {},\n ): this {\n return summarize(this, options) as this;\n }\n\n /**\n * Adds one or more summary rows to the table. Each row is calculated from\n * the original rows before any summary rows are added. This is useful for\n * preparing totals and other statistics before exporting tabular data.\n *\n * Passing `\"all\"` selects every numeric column. Columns that are neither\n * summarized nor used for labels contain `NULL` in the added rows. A stat\n * string is also used as its row label; pass an object to customize that\n * label. If `options.stats` is omitted, every supported stat is added.\n *\n * @example\n * ```ts\n * // Add a total row for every numeric column, labelled \"sum\" in \"region\".\n * await table.addSummaryRows(\"all\", \"region\", { stats: \"sum\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Add two summary rows with default labels.\n * await table.addSummaryRows([\"sales\", \"expenses\"], \"region\", {\n * stats: [\"sum\", \"mean\"],\n * position: \"top\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Customize the labels written to the label column.\n * await table.addSummaryRows(\"all\", \"region\", {\n * stats: [\n * { stat: \"sum\", label: \"Total\" },\n * { stat: \"mean\", label: \"Average\" },\n * ],\n * }).log();\n * ```\n * @param columns - The numeric column name, an array of numeric column names, or `\"all\"` to summarize every numeric column.\n * @param labelColumn - The existing string column in which stat row labels will be written.\n * @param options - An optional object with configuration options:\n * @param options.stats - A stat, stat configuration, or array of either. Supported stats are `\"countDistinct\"`, `\"countNull\"`, `\"min\"`, `\"max\"`, `\"mean\"`, `\"median\"`, `\"sum\"`, `\"skew\"`, `\"stdDev\"`, and `\"variance\"`. An object's `label` defaults to its `stat`. If omitted, all supported stats are added.\n * @param options.position - Whether to add the summary rows at the `\"top\"` or `\"bottom\"` of the table. Defaults to `\"bottom\"`.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n addSummaryRows(\n columns: string | string[],\n labelColumn: string,\n options: {\n stats?:\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\"\n | {\n stat:\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\";\n label?: string;\n }\n | (\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\"\n | {\n stat:\n | \"countDistinct\"\n | \"countNull\"\n | \"min\"\n | \"max\"\n | \"mean\"\n | \"median\"\n | \"sum\"\n | \"skew\"\n | \"stdDev\"\n | \"variance\";\n label?: string;\n }\n )[];\n position?: \"top\" | \"bottom\";\n } = {},\n ): this {\n addSummaryRows(this, columns, labelColumn, options);\n return this;\n }\n\n /**\n * Computes the cumulative sum of values in a column. For this method to work properly, ensure your data is sorted first.\n *\n * @example\n * ```ts\n * // Compute the cumulative sum of 'sales' in a new 'cumulativeSales' column\n * // Ensure the table is sorted by a relevant column (e.g., date) before calling this method.\n * await table.accumulate(\"sales\", \"cumulativeSales\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the cumulative sum of 'orders' by 'customer_id'\n * // Ensure the table is sorted by 'customer_id' and then by a relevant order column (e.g., order_date).\n * await table.accumulate(\"orders\", \"cumulativeOrders\", { by: \"customer_id\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the cumulative sum of 'revenue' by 'region' and 'product_category'\n * await table.accumulate(\"revenue\", \"cumulativeRevenue\", { by: [\"region\", \"product_category\"] }).log();\n * ```\n * @param column - The name of the column storing the values to be accumulated.\n * @param newColumn - The name of the new column in which the computed cumulative values will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Accumulation is performed independently within each group.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n accumulate(\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n ): this {\n accumulate(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Computes rolling aggregations (e.g., rolling average, min, max) over a specified column.\n * For rows without enough preceding or following rows to form a complete window, `NULL` will be returned.\n * For this method to work properly, ensure your data is sorted by the relevant column(s) first.\n *\n * @example\n * ```ts\n * // Compute a 7-day rolling average of 'sales' with 3 preceding and 3 following rows\n * // (total window size of 7: 3 preceding + current + 3 following)\n * await table.rolling(\"sales\", \"rollingAvgSales\", \"mean\", 3, 3).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute a rolling sum of 'transactions' by 'customer_id'\n * await table.rolling(\"transactions\", \"rollingSumTransactions\", \"sum\", 5, 0, { by: \"customer_id\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute a rolling maximum of 'temperature' rounded to 1 decimal place\n * await table.rolling(\"temperature\", \"rollingMaxTemp\", \"max\", 2, 2, { decimals: 1 }).log();\n * ```\n * @param column - The name of the column storing the values to be aggregated.\n * @param newColumn - The name of the new column in which the computed rolling values will be stored.\n * @param stat - The aggregation function to apply: `\"min\"`, `\"max\"`, `\"mean\"`, `\"median\"`, or `\"sum\"`.\n * @param preceding - The number of preceding rows to include in the rolling window.\n * @param following - The number of following rows to include in the rolling window.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Rolling statistics are computed independently within each group.\n * @param options.decimals - The number of decimal places to round the aggregated values. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n rolling(\n column: string,\n newColumn: string,\n stat: \"min\" | \"max\" | \"mean\" | \"median\" | \"sum\",\n preceding: number,\n following: number,\n options: {\n by?: string | string[];\n decimals?: number;\n } = {},\n ): this {\n rolling(this, column, newColumn, stat, preceding, following, options);\n return this;\n }\n\n /**\n * Calculates correlations between columns. If no `x` and `y` columns are specified, the method computes the correlations for all numeric column combinations.\n * Note that correlation is symmetrical: the correlation of `x` with `y` is the same as `y` with `x`.\n *\n * @example\n * ```ts\n * // Compute correlations between all numeric columns, overwriting the current table\n * await table.correlations().log();\n * ```\n *\n * @example\n * ```ts\n * // Compute correlations between 'column1' and all other numeric columns\n * await table.correlations({ x: \"column1\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the correlation between 'column1' and 'column2'\n * await table.correlations({ x: \"column1\", y: \"column2\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute correlations within 'categoryColumn' and store results in a new table\n * const correlationTable = await table.correlations({ by: \"categoryColumn\", outputTable: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute correlations, rounded to 2 decimal places\n * await table.correlations({ decimals: 2 }).log();\n * ```\n * @param options - An optional object with configuration options:\n * @param options.x - The name of the column for the x-values. If omitted, correlations will be computed for all numeric columns.\n * @param options.y - The name of the column for the y-values. It can be provided only when `options.x` is also set. If both are omitted, correlations will be computed for all numeric column pairs.\n * @param options.by - The column name or an array of column names to group by. Correlations are calculated independently within each group.\n * @param options.decimals - The number of decimal places to round the correlation values. Defaults to `undefined` (no rounding).\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the correlation results (either the current table or a new table), so methods can be chained.\n * @category Analyzing Data\n */\n correlations(\n options: {\n x?: string;\n y?: string;\n by?: string | string[];\n decimals?: number;\n outputTable?: string | boolean;\n } = {},\n ): this {\n return correlations(this, options) as this;\n }\n\n /**\n * Performs linear regression analysis. The results include the slope, the y-intercept, and the R-squared value.\n * If no `x` and `y` columns are specified, the method computes linear regression analysis for all numeric column permutations.\n * Note that linear regression analysis is asymmetrical: the linear regression of `x` over `y` is not the same as `y` over `x`.\n *\n * @example\n * ```ts\n * // Compute all linear regressions between all numeric columns, overwriting the current table\n * await table.linearRegressions().log();\n * ```\n *\n * @example\n * ```ts\n * // Compute linear regressions with 'column1' as the independent variable and all other numeric columns as dependent variables\n * await table.linearRegressions({ x: \"column1\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the linear regression of 'sales' (y) over 'advertising' (x)\n * await table.linearRegressions({ x: \"advertising\", y: \"sales\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute linear regressions by 'region' and store results in a new table\n * const regressionTable = await table.linearRegressions({ by: \"region\", outputTable: true }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute linear regressions, rounded to 3 decimal places\n * await table.linearRegressions({ decimals: 3 }).log();\n * ```\n * @param options - An optional object with configuration options:\n * @param options.x - The name of the column for the independent variable (x-values). If omitted, linear regressions will be computed for all numeric columns as x.\n * @param options.y - The name of the column for the dependent variable (y-values). It can be provided only when `options.x` is also set. If both are omitted, linear regressions will be computed for all numeric column permutations.\n * @param options.by - The column name or an array of column names to group by. Linear regressions are calculated independently within each group.\n * @param options.decimals - The number of decimal places to round the regression values (slope, intercept, r-squared). Defaults to `undefined` (no rounding).\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the linear regression results (either the current table or a new table), so methods can be chained.\n * @category Analyzing Data\n */\n linearRegressions(\n options: {\n x?: string;\n y?: string;\n by?: string | string[];\n decimals?: number;\n outputTable?: string | boolean;\n } = {},\n ): this {\n return linearRegressions(this, options) as this;\n }\n\n /**\n * Identifies outliers in a specified column using the Interquartile Range (IQR) method.\n *\n * @example\n * ```ts\n * // Look for outliers in the 'age' column and store results in a new 'isOutlier' column\n * await table.outliersIQR(\"age\", \"isOutlier\").log();\n * ```\n *\n * @example\n * ```ts\n * // Look for outliers in 'salary' by 'gender'\n * await table.outliersIQR(\"salary\", \"salaryOutlier\", { by: \"gender\" }).log();\n * ```\n * @param column - The name of the column in which outliers will be identified.\n * @param newColumn - The name of the new column where the boolean results (`TRUE` for outlier, `FALSE` otherwise) will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Outliers are detected independently within each group.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n outliersIQR(\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n } = {},\n ): this {\n outliersIQR(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Computes the Z-score for values in a specified column.\n *\n * @example\n * ```ts\n * // Calculate the Z-score for 'age' values and store results in a new 'ageZScore' column\n * await table.zScore(\"age\", \"ageZScore\").log();\n * ```\n *\n * @example\n * ```ts\n * // Calculate Z-scores for 'salary' by 'department'\n * await table.zScore(\"salary\", \"salaryZScore\", { by: \"department\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Calculate Z-scores for 'score', rounded to 2 decimal places\n * await table.zScore(\"score\", \"scoreZScore\", { decimals: 2 }).log();\n * ```\n * @param column - The name of the column for which Z-scores will be calculated.\n * @param newColumn - The name of the new column where the computed Z-scores will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Z-scores are calculated independently within each group.\n * @param options.decimals - The number of decimal places to round the Z-score values. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n zScore(\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n decimals?: number;\n } = {},\n ): this {\n zScore(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Normalizes the values in a column using min-max normalization.\n *\n * @example\n * ```ts\n * // Normalize the values in 'column1' and store them in a new 'normalizedColumn1' column\n * await table.normalize(\"column1\", \"normalizedColumn1\").log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize 'value' by 'group'\n * await table.normalize(\"value\", \"normalizedValue\", { by: \"group\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize 'data' values, rounded to 2 decimal places\n * await table.normalize(\"data\", \"normalizedData\", { decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Normalize 'score' values to a range from 0 to 10\n * await table.normalize(\"score\", \"scaledScore\", { range: [0, 10] }).log();\n * ```\n * @param column - The name of the column in which values will be normalized.\n * @param newColumn - The name of the new column where normalized values will be stored.\n * @param options - An optional object with configuration options:\n * @param options.by - The column name or an array of column names to partition by. Normalization is performed independently within each group.\n * @param options.decimals - The number of decimal places to round the normalized values. Defaults to `undefined` (no rounding).\n * @param options.range - The inclusive range to scale normalized values to, as `[minimum, maximum]`. Both values must be finite and the minimum must be less than the maximum. Defaults to `[0, 1]`.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n normalize(\n column: string,\n newColumn: string,\n options: {\n by?: string | string[];\n decimals?: number;\n range?: [number, number];\n } = {},\n ): this {\n normalize(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Indexes a numeric column by dividing each value by a reference value and multiplying the result by a base value.\n *\n * The reference can be calculated from the indexed column with a statistic, read from exactly one row selected by another column's value, or read from the unique row where another column reaches its minimum or maximum. With `options.by`, references are calculated or selected independently within each group. Null values in the indexed column remain null when their group has a valid reference. The operation throws when a group has no unique selected row or its reference value is null or zero.\n *\n * Exact temporal references are compared at their full DuckDB precision. JavaScript `Date` objects only have millisecond precision and always represent an instant. Construct them with an explicit timezone, such as `new Date(\"2001-01-01T00:00:00Z\")`; date-time strings without `Z` or an offset use the user's local timezone.\n *\n * @example\n * ```ts\n * // Index each country's average home price to its January 2001 value.\n * await table.indexValues(\n * \"homePrice\",\n * \"homePriceIndexed\",\n * {\n * column: \"date\",\n * equals: new Date(\"2001-01-01T00:00:00Z\"),\n * },\n * {\n * by: \"country\",\n * base: 100,\n * decimals: 1,\n * },\n * ).log();\n * ```\n *\n * @example\n * ```ts\n * // Index each value against the mean of its group.\n * await table.indexValues(\"homePrice\", \"homePriceIndexed\", { stat: \"mean\" }, {\n * by: \"country\",\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Index each country's average home price to its earliest value.\n * // This throws if multiple rows share the earliest date in a country.\n * await table.indexValues(\"homePrice\", \"homePriceIndexed\", {\n * column: \"date\",\n * at: \"min\",\n * }, { by: \"country\" }).log();\n * ```\n * @param column - The numeric column containing the values to index.\n * @param newColumn - The name of the new column where indexed values will be stored.\n * @param reference - A statistic calculated from `column`, a column and exact non-null `equals` value selecting a row, or a column and `at` set to `min` or `max` selecting its unique extreme row. The selected row's `column` value becomes the reference.\n * @param reference.stat - The statistic used to calculate the reference directly from the indexed column.\n * @param reference.column - The column used to select an exact reference row or its unique minimum or maximum row.\n * @param reference.equals - The non-null value used to select an exact reference row. Its JavaScript type must be compatible with the reference column's DuckDB type; string, numeric, boolean, and temporal values are not coerced across type families. Date values should be constructed with an explicit timezone.\n * @param reference.at - Selects the unique row where `reference.column` reaches its minimum or maximum.\n * @param options - An optional object with configuration options.\n * @param options.by - A column name or an array of column names to partition by. The reference is calculated independently within each group.\n * @param options.base - The finite positive value assigned to the reference. Defaults to `100`.\n * @param options.decimals - A finite non-negative integer specifying the number of decimal places to retain. By default, values are not rounded.\n * @returns The table, so methods can be chained.\n * @category Analyzing Data\n */\n indexValues(\n column: string,\n newColumn: string,\n reference:\n | {\n stat: \"min\" | \"max\" | \"mean\" | \"median\";\n column?: never;\n equals?: never;\n at?: never;\n }\n | {\n column: string;\n equals: string | number | bigint | boolean | Date;\n stat?: never;\n at?: never;\n }\n | {\n column: string;\n at: \"min\" | \"max\";\n stat?: never;\n equals?: never;\n },\n options: {\n by?: string | string[];\n base?: number;\n decimals?: number;\n } = {},\n ): this {\n indexValues(this, column, newColumn, reference, options);\n return this;\n }\n\n /**\n * Updates data in the table using a JavaScript function. The function receives the existing rows as an array of objects and must return the modified rows as an array of objects.\n * This method offers high flexibility for data manipulation but can be slow for large tables as it involves transferring data between DuckDB and JavaScript.\n * Before writing a JavaScript callback, check for an existing SDA method that\n * performs the same operation; it will usually be faster and more efficient.\n * Existing integer and enum columns retain their types. Fractional or\n * out-of-range integers and unknown enum members throw when written. The\n * original table is replaced after all callback results have been converted\n * successfully.\n *\n * If the table has geometry columns, the callback can read and modify their\n * GeoJSON geometry objects directly. Extra properties added to these objects\n * are ignored; create new columns on the returned rows to store additional\n * attributes. All geometry columns must use EPSG:4326; use reproject() first\n * if needed.\n *\n * @example\n * ```ts\n * // Double the value in each row with a JavaScript callback.\n * await table.loadArray([{ value: 1 }, { value: 2 }])\n * .updateWithJS((rows) => rows.map((row) => ({\n * value: Number(row.value) * 2,\n * })))\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Process two rows per callback to limit how many rows are handled at once.\n * await table.loadArray([{ value: 1 }, { value: 2 }, { value: 3 }])\n * .updateWithJS((rows) => rows.map((row) => ({\n * value: Number(row.value) * 2,\n * })), { batchSize: 2 })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Add a JSON object column to keep related attributes together.\n * await table.loadArray([{ name: \"Station\" }])\n * .updateWithJS((rows) => rows.map((row) => ({\n * ...row, details: { active: true, category: \"weather\" },\n * })), { columnTypes: { details: \"JSON\" } })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Add a three-element float vector, such as an embedding.\n * await table.loadArray([{ name: \"Station\" }])\n * .updateWithJS((rows) => rows.map((row) => ({\n * ...row, embedding: [0.25, 0.5, 0.75],\n * })), { columnTypes: { embedding: \"FLOAT[3]\" } })\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Move each point slightly east by editing its longitude.\n * await sdb.newTable().loadArray([{\n * geom: { type: \"Point\", coordinates: [-73, 45] },\n * }], { columnTypes: { geom: \"GEOMETRY('EPSG:4326')\" } })\n * .updateWithJS((rows) => rows.map((row) => {\n * // This example loads only Points. Narrow the type for coordinate access.\n * const geom = row.geom as { type: \"Point\"; coordinates: number[] } | null;\n * if (geom !== null) geom.coordinates[0] += 0.01;\n * return row;\n * })).log();\n * ```\n *\n * @example\n * ```ts\n * // Create a geometry column from longitude and latitude values.\n * await sdb.newTable().loadArray([{ longitude: -73, latitude: 45 }])\n * .updateWithJS((rows) => rows.map((row) => ({\n * ...row, geom: { type: \"Point\", coordinates: [row.longitude, row.latitude] },\n * })), { columnTypes: { geom: \"GEOMETRY('EPSG:4326')\" } }).log();\n * ```\n * @param dataModifier - A synchronous or asynchronous function that takes the existing rows (as an array of objects) and returns the modified rows (as an array of objects).\n * @param options - An optional object with configuration options:\n * @param options.batchSize - If provided, rows are processed in batches of this size instead of all at once, so large tables don't have to be materialized entirely in memory. This limits input rows per batch, but does not eliminate conversion work or bound geometry size or callback output expansion. The modifier function is called once per batch. Tables with a column named `rowid` or `__sda_rowid` (case-insensitive) are rejected before the modifier runs; rename the column or omit batchSize.\n * @param options.columnTypes - Explicit types for newly added columns, following loadArray's columnTypes contract. Declare geometry as GEOMETRY('EPSG:4326'); geometry is never inferred from object shape. Existing columns cannot be redeclared.\n * @returns The table, so methods can be chained.\n * @category Updating Data\n */\n updateWithJS(\n dataModifier:\n | ((\n rows: {\n [key: string]: unknown;\n }[],\n ) => Promise<\n {\n [key: string]: unknown;\n }[]\n >)\n | ((\n rows: {\n [key: string]: unknown;\n }[],\n ) => {\n [key: string]: unknown;\n }[]),\n options: {\n batchSize?: number;\n columnTypes?: { [key: string]: string };\n } = {},\n ): this {\n updateWithJS(this, dataModifier, options);\n return this;\n }\n\n /**\n * Returns the schema of the table, including column names and their data types.\n *\n * @example\n * ```ts\n * // Get the schema of the table\n * const schema = await table.getSchema();\n * console.table(schema); // Log the schema in a readable table format\n * ```\n * @returns A promise that resolves to an array of objects, where each object represents a column with its name and data type.\n * @category Getting Data\n */\n async getSchema(): Promise<\n {\n [key: string]: string | null;\n }[]\n > {\n return await getSchema(this);\n }\n\n /**\n * Returns descriptive statistical information about the columns, including details like data types, number of null values, and distinct values.\n *\n * @example\n * ```ts\n * // Get and log descriptive information about the table's columns\n * const description = await table.getDescription();\n * console.table(description);\n * ```\n * @returns A promise that resolves to an array of objects, each representing descriptive statistics for a column.\n * @category Getting Data\n */\n async getDescription(): Promise<\n {\n [key: string]: unknown;\n }[]\n > {\n return await getDescription(this);\n }\n\n /**\n * Returns the name of the table.\n *\n * @example\n * ```ts\n * // Get the table name\n * const tableName = table.getName();\n * console.log(tableName); // e.g., \"employees\"\n * ```\n * @returns The name of the table as a string.\n * @category Getting Data\n */\n getName(): string {\n return this.name;\n }\n\n /**\n * Returns a list of all column names in the table.\n *\n * @example\n * ```ts\n * // Get all column names from the table\n * const columns = await table.getColumns();\n * console.log(columns); // e.g., [\"id\", \"name\", \"age\"]\n * ```\n * @returns A promise that resolves to an array of strings, where each string is a column name.\n * @category Getting Data\n */\n async getColumns(): Promise<string[]> {\n return await getColumns(this);\n }\n\n /**\n * Normalizes string values in a column by:\n * 1. Stripping accents\n * 2. Optionally stripping punctuation (default: true)\n * 3. Converting to lowercase\n * 4. Normalizing whitespace (multiple spaces/tabs/newlines → single space)\n * 5. Trimming leading/trailing whitespace\n *\n * Produces identical output to `journalism-format`'s `normalizeString()` function\n * for all common cases including accented Latin characters.\n *\n * @example\n * ```ts\n * // Normalize text column and store in new column\n * await table.normalizeString(\"recipeName\", \"recipeNameNormalized\").log();\n * // \"Épicerie Parisienne!\" → \"epicerie parisienne\"\n * ```\n *\n * @example\n * ```ts\n * // Keep punctuation for emails and URLs\n * await table.normalizeString(\"email\", \"emailNormalized\", { stripPunctuation: false }).log();\n * // \"User@Example.com\" → \"user@example.com\"\n * await table.normalizeString(\"url\", \"urlNormalized\", { stripPunctuation: false }).log();\n * // \"https://Example.com/path\" → \"https://example.com/path\"\n * ```\n *\n * @param column The column containing the text to normalize\n * @param newColumn The column to store the normalized results\n * @param options Configuration options\n * @param options.stripPunctuation Strip punctuation and underscores (default: true)\n *\n * @returns The table, so methods can be chained.\n * @category Text Processing\n */\n normalizeString(\n column: string,\n newColumn: string,\n options: { stripPunctuation?: boolean } = {},\n ): this {\n normalizeString(this, column, newColumn, options);\n return this;\n }\n\n /**\n * Returns the number of columns in the table.\n *\n * @example\n * ```ts\n * // Get the number of columns in the table\n * const columnCount = await table.getColumnCount();\n * console.log(columnCount); // e.g., 3\n * ```\n * @returns A promise that resolves to a number representing the total count of columns.\n * @category Getting Data\n */\n async getColumnCount(): Promise<number> {\n const result = (await getColumns(this)).length;\n return result;\n }\n\n /**\n * Adds a new column containing the number of characters in each string in the specified column.\n * Counts are based on Unicode code points, not grapheme clusters. A user-perceived character composed of multiple code points, such as some emoji or decomposed accented letters, counts as multiple characters.\n * `NULL` input values produce `NULL` counts.\n *\n * @example\n * ```ts\n * // Add a character count for each value in the 'name' column\n * await table.addCharacterCount(\"name\", \"nameCharacterCount\").log();\n * ```\n * @param column - The name of the column containing the strings to count.\n * @param newColumn - The name of the new column where the character counts will be stored.\n * @returns The table, so methods can be chained.\n * @category Text Processing\n */\n addCharacterCount(column: string, newColumn: string): this {\n addCharacterCount(this, column, newColumn);\n return this;\n }\n\n /**\n * Adds a new column containing the word count for each string in the specified column.\n * A word is any contiguous sequence of non-whitespace characters. Spaces, tabs, and line breaks separate words. Punctuation is not removed, so a standalone punctuation sequence counts as a word. Text without whitespace counts as one word, regardless of language. Empty or whitespace-only strings produce `0`, and `NULL` input values produce `NULL` counts.\n *\n * @example\n * ```ts\n * // Add a word count for each value in the 'article' column\n * await table.addWordCount(\"article\", \"wordCount\").log();\n * ```\n * @param column - The name of the column containing the strings to count.\n * @param newColumn - The name of the new column where the word counts will be stored.\n * @returns The table, so methods can be chained.\n * @category Text Processing\n */\n addWordCount(column: string, newColumn: string): this {\n addWordCount(this, column, newColumn);\n return this;\n }\n\n /**\n * Returns the total number of characters in a column storing strings.\n * Counts are based on Unicode code points, not grapheme clusters. A user-perceived character composed of multiple code points, such as some emoji or decomposed accented letters, counts as multiple characters.\n *\n * @example\n * ```ts\n * // Get the total number of characters in the 'name' column\n * const totalChars = await table.getCharacterCount(\"name\");\n * console.log(totalChars); // e.g., 523\n * ```\n * @param column - The name of the string column to count characters from.\n * @returns A promise that resolves to the total number of characters across all rows in the specified column.\n * @category Getting Data\n */\n async getCharacterCount(column: string): Promise<number> {\n return await getCharacterCount(this, column);\n }\n\n /**\n * Returns the number of rows in the table.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Get the number of rows in the table\n * const rowCount = await table.getRowCount();\n * console.log(rowCount); // e.g., 100\n * ```\n *\n * @example\n * ```ts\n * // Get the number of rows where 'category' is 'Book'\n * const bookCount = await table.getRowCount({ conditions: \"category = 'Book'\" });\n * console.log(bookCount);\n * ```\n * @param options - An optional object with configuration options:\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Book'\"`).\n * @returns A promise that resolves to a number representing the total count of rows.\n * @category Getting Data\n */\n async getRowCount(options: { conditions?: string } = {}): Promise<number> {\n return await getRowCount(this, options);\n }\n\n /**\n * Returns the total number of values in the table (number of columns multiplied by the number of rows).\n *\n * @example\n * ```ts\n * // Get the total number of values in the table\n * const valueCount = await table.getValueCount();\n * console.log(valueCount); // e.g., 300 (if 3 columns and 100 rows)\n * ```\n * @returns A promise that resolves to a number representing the total count of values.\n * @category Getting Data\n */\n async getValueCount(): Promise<number> {\n const result = (await this.getColumnCount()) * (await this.getRowCount());\n return result;\n }\n\n /**\n * Returns the data types of all columns in the table.\n *\n * @example\n * ```ts\n * // Get the data types of all columns\n * const dataTypes = await table.getTypes();\n * console.log(dataTypes);\n * ```\n * @returns A promise that resolves to an object where keys are column names and values are their corresponding data types (e.g., `{ \"id\": \"BIGINT\", \"name\": \"VARCHAR\" }`).\n * @category Getting Data\n */\n async getTypes(): Promise<{\n [key: string]: string;\n }> {\n return await getTypes(this);\n }\n\n /**\n * Returns a deterministic hash of the table's ordered schema and contents.\n * Pending operations are executed before the hash is calculated. Computing\n * the hash scans the complete table inside DuckDB without transferring its\n * rows to JavaScript.\n *\n * @example\n * ```ts\n * const hash = await table.getHash();\n * console.log(hash); // e.g., \"8f14e45fceea...\"\n * ```\n * @returns A promise that resolves to a SHA-256 hash string.\n * @category Getting Data\n */\n async getHash(): Promise<string> {\n return await getHash(this);\n }\n\n /**\n * Returns all values from a specific column.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get all values from the 'productName' column\n * const productNames = await table.getValues(\"productName\");\n * console.log(productNames); // e.g., [\"Laptop\", \"Mouse\", \"Keyboard\"]\n * ```\n * @param column - The name of the column from which to retrieve values.\n * @returns A promise that resolves to an array containing all values from the specified column.\n * @category Getting Data\n */\n async getValues(column: string): Promise<unknown[]> {\n return await getValues(this, column);\n }\n\n /**\n * Returns the minimum value from a specific column.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the minimum value from the 'price' column\n * const minPrice = await table.getMin(\"price\");\n * console.log(minPrice); // e.g., 10.50\n * ```\n * @param column - The name of the column from which to retrieve the minimum value.\n * @returns A promise that resolves to the minimum value of the specified column.\n * @category Getting Data\n */\n async getMin(column: string): Promise<unknown> {\n return await getMin(this, column);\n }\n\n /**\n * Returns the maximum value from a specific column.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the maximum value from the 'price' column\n * const maxPrice = await table.getMax(\"price\");\n * console.log(maxPrice); // e.g., 99.99\n * ```\n * @param column - The name of the column from which to retrieve the maximum value.\n * @returns A promise that resolves to the maximum value of the specified column.\n * @category Getting Data\n */\n async getMax(column: string): Promise<unknown> {\n return await getMax(this, column);\n }\n\n /**\n * Returns the extent (minimum and maximum values) of a specific column as an array.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the extent of the 'temperature' column\n * const tempExtent = await table.getExtent(\"temperature\");\n * console.log(tempExtent); // e.g., [15.2, 30.1]\n * ```\n * @param column - The name of the column from which to retrieve the extent.\n * @returns A promise that resolves to an array `[min, max]` containing the minimum and maximum values of the specified column.\n * @category Getting Data\n */\n async getExtent(column: string): Promise<[unknown, unknown]> {\n return [await this.getMin(column), await this.getMax(column)];\n }\n\n /**\n * Returns the mean (average) value from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the mean of the 'age' column\n * const meanAge = await table.getMean(\"age\");\n * console.log(meanAge); // e.g., 35.75\n * ```\n *\n * @example\n * ```ts\n * // Get the mean of the 'salary' column, rounded to 2 decimal places\n * const meanSalary = await table.getMean(\"salary\", { decimals: 2 });\n * console.log(meanSalary); // e.g., 55000.23\n * ```\n * @param column - The name of the numeric column from which to retrieve the mean value.\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the mean value of the specified column.\n * @category Getting Data\n */\n async getMean(\n column: string,\n options: {\n decimals?: number;\n } = {},\n ): Promise<number> {\n return await getMean(this, column, options);\n }\n\n /**\n * Returns the median value from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the median of the 'age' column\n * const medianAge = await table.getMedian(\"age\");\n * console.log(medianAge); // e.g., 30\n * ```\n *\n * @example\n * ```ts\n * // Get the median of the 'salary' column, rounded to 2 decimal places\n * const medianSalary = await table.getMedian(\"salary\", { decimals: 2 });\n * console.log(medianSalary); // e.g., 50000.00\n * ```\n * @param column - The name of the numeric column from which to retrieve the median value.\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the median value of the specified column.\n * @category Getting Data\n */\n async getMedian(\n column: string,\n options: {\n decimals?: number;\n } = {},\n ): Promise<number> {\n return await getMedian(this, column, options);\n }\n\n /**\n * Returns the sum of values from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the sum of the 'quantity' column\n * const totalQuantity = await table.getSum(\"quantity\");\n * console.log(totalQuantity); // e.g., 1250\n * ```\n * @param column - The name of the numeric column from which to retrieve the sum.\n * @returns A promise that resolves to the sum of values in the specified column.\n * @category Getting Data\n */\n async getSum(column: string): Promise<number> {\n return await getSum(this, column);\n }\n\n /**\n * Returns the skewness of values from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the skewness of the 'data' column\n * const dataSkew = await table.getSkew(\"data\");\n * console.log(dataSkew); // e.g., 0.5\n * ```\n *\n * @example\n * ```ts\n * // Get the skewness of the 'values' column, rounded to 2 decimal places\n * const valuesSkew = await table.getSkew(\"values\", { decimals: 2 });\n * console.log(valuesSkew); // e.g., -0.25\n * ```\n * @param column - The name of the numeric column from which to retrieve the skewness.\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the skewness value of the specified column.\n * @category Getting Data\n */\n async getSkew(\n column: string,\n options: {\n decimals?: number;\n } = {},\n ): Promise<number> {\n return await getSkew(this, column, options);\n }\n\n /**\n * Returns the standard deviation of values from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the standard deviation of the 'height' column\n * const heightStdDev = await table.getStdDev(\"height\");\n * console.log(heightStdDev); // e.g., 5.2\n * ```\n *\n * @example\n * ```ts\n * // Get the standard deviation of the 'score' column, rounded to 3 decimal places\n * const scoreStdDev = await table.getStdDev(\"score\", { decimals: 3 });\n * console.log(scoreStdDev); // e.g., 12.345\n * ```\n * @param column - The name of the numeric column from which to retrieve the standard deviation.\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the standard deviation value of the specified column.\n * @category Getting Data\n */\n async getStdDev(\n column: string,\n options: {\n decimals?: number;\n } = {},\n ): Promise<number> {\n return await getStdDev(this, column, options);\n }\n\n /**\n * Returns the variance of values from a specific numeric column.\n *\n * @example\n * ```ts\n * // Get the variance of the 'data' column\n * const dataVariance = await table.getVariance(\"data\");\n * console.log(dataVariance); // e.g., 25.5\n * ```\n *\n * @example\n * ```ts\n * // Get the variance of the 'values' column, rounded to 2 decimal places\n * const valuesVariance = await table.getVariance(\"values\", { decimals: 2 });\n * console.log(valuesVariance); // e.g., 10.23\n * ```\n * @param column - The name of the numeric column from which to retrieve the variance.\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the variance value of the specified column.\n * @category Getting Data\n */\n async getVariance(\n column: string,\n options: {\n decimals?: number;\n } = {},\n ): Promise<number> {\n return await getVariance(this, column, options);\n }\n\n /**\n * Returns the value of a specific quantile from the values in a given numeric column.\n *\n * @example\n * ```ts\n * // Get the first quartile (25th percentile) of 'column1'\n * const firstQuartile = await table.getQuantile(\"column1\", 0.25);\n * console.log(firstQuartile); // e.g., 15.7\n * ```\n *\n * @example\n * ```ts\n * // Get the 90th percentile of 'score' values, rounded to 2 decimal places\n * const ninetiethPercentile = await table.getQuantile(\"score\", 0.9, { decimals: 2 });\n * console.log(ninetiethPercentile); // e.g., 88.55\n * ```\n * @param column - The name of the numeric column from which to calculate the quantile.\n * @param quantile - The quantile to calculate, expressed as a number between 0 and 1 (e.g., `0.25` for the first quartile, `0.5` for the median, `0.75` for the third quartile).\n * @param options - An optional object with configuration options:\n * @param options.decimals - The number of decimal places to round the result to. Defaults to `undefined` (no rounding).\n * @returns A promise that resolves to the quantile value of the specified column.\n * @category Getting Data\n */\n async getQuantile(\n column: string,\n quantile: number,\n options: { decimals?: number } = {},\n ): Promise<number> {\n return await getQuantile(this, column, quantile, options);\n }\n\n /**\n * Returns unique values from a specific column. The values are returned in ascending order.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get unique values from the 'category' column\n * const uniqueCategories = await table.getUniques(\"category\");\n * console.log(uniqueCategories); // e.g., [\"Books\", \"Clothing\", \"Electronics\"]\n * ```\n * @param column - The name of the column from which to retrieve unique values.\n * @returns A promise that resolves to an array containing the unique values from the specified column, sorted in ascending order.\n * @category Getting Data\n */\n async getUniques(column: string): Promise<unknown[]> {\n return await getUniques(this, column);\n }\n\n /**\n * Returns the first row of the table, optionally filtered by SQL conditions.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the very first row of the table\n * const firstRow = await table.getFirstRow();\n * console.log(firstRow);\n * ```\n *\n * @example\n * ```ts\n * // Get the first row where the 'category' is 'Book'\n * const firstRowBooks = await table.getFirstRow({ conditions: `category === 'Book'` }); // Using JS syntax\n * console.log(firstRowBooks);\n * ```\n * @param options - An optional object with configuration options:\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Book'\"`).\n * @returns A promise that resolves to an object representing the first row, or `null` if no rows match the conditions.\n * @category Getting Data\n */\n async getFirstRow(\n options: {\n conditions?: string;\n } = {},\n ): Promise<{\n [key: string]: unknown;\n } | null> {\n return await getFirstRow(this, options);\n }\n\n /**\n * Returns the last row of the table, optionally filtered by SQL conditions.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the very last row of the table\n * const lastRow = await table.getLastRow();\n * console.log(lastRow);\n * ```\n *\n * @example\n * ```ts\n * // Get the last row where the 'category' is 'Book'\n * const lastRowBooks = await table.getLastRow({ conditions: `category === 'Book'` }); // Using JS syntax\n * console.log(lastRowBooks);\n * ```\n * @param options - An optional object with configuration options:\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Book'\"`).\n * @returns A promise that resolves to an object representing the last row, or `null` if no rows match the conditions.\n * @category Getting Data\n */\n async getLastRow(\n options: {\n conditions?: string;\n } = {},\n ): Promise<{\n [key: string]: unknown;\n } | null> {\n return await getLastRow(this, options);\n }\n\n /**\n * Returns the top `n` rows of the table, optionally filtered by SQL conditions.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the first 10 rows of the table\n * const top10 = await table.getTop(10);\n * console.log(top10);\n * ```\n *\n * @example\n * ```ts\n * // Get the first 5 rows where the 'category' is 'Books'\n * const top5Books = await table.getTop(5, { conditions: `category === 'Books'` }); // Using JS syntax\n * console.log(top5Books);\n * ```\n * @param count - The number of rows to return from the top of the table.\n * @param options - An optional object with configuration options:\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Books'\"`).\n * @returns A promise that resolves to an array of objects representing the top `n` rows.\n * @category Getting Data\n */\n async getTop(\n count: number,\n options: {\n conditions?: string;\n } = {},\n ): Promise<\n {\n [key: string]: unknown;\n }[]\n > {\n return await getTop(this, count, options);\n }\n\n /**\n * Returns the bottom `n` rows of the table, optionally filtered by SQL conditions.\n * By default, the last row will be returned first. To preserve the original order, use the `originalOrder` option.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get the last 10 rows (last row first)\n * const bottom10 = await table.getBottom(10);\n * console.log(bottom10);\n * ```\n *\n * @example\n * ```ts\n * // Get the last 10 rows in their original order\n * const bottom10OriginalOrder = await table.getBottom(10, { originalOrder: true });\n * console.log(bottom10OriginalOrder);\n * ```\n *\n * @example\n * ```ts\n * // Get the last 5 rows where the 'category' is 'Books' (using JS syntax)\n * const bottom5Books = await table.getBottom(5, { conditions: `category === 'Books'` });\n * console.log(bottom5Books);\n * ```\n * @param count - The number of rows to return from the bottom of the table.\n * @param options - An optional object with configuration options:\n * @param options.originalOrder - A boolean indicating whether the rows should be returned in their original order (`true`) or in reverse order (last row first, `false`). Defaults to `false`.\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Books'\"`).\n * @returns A promise that resolves to an array of objects representing the bottom `n` rows.\n * @category Getting Data\n */\n async getBottom(\n count: number,\n options: {\n originalOrder?: boolean;\n conditions?: string;\n } = {},\n ): Promise<\n {\n [key: string]: unknown;\n }[]\n > {\n return await getBottom(this, count, options);\n }\n\n /**\n * Returns a single row that matches the specified conditions. Always throws if no row matches. By default, also throws if more than one row matches.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values use the same JavaScript representations as `getData()`.\n *\n * @example\n * ```ts\n * // Get a row where 'name' is 'John'\n * const johnsRow = await table.getRow(`name = 'John'`);\n * console.log(johnsRow);\n * ```\n *\n * @example\n * ```ts\n * // Get a row where 'id' is 123 (using JS syntax)\n * const rowById = await table.getRow(`id === 123`);\n * console.log(rowById);\n * ```\n *\n * @example\n * ```ts\n * // Get the first matching row when multiple rows may match\n * const flexibleRow = await table.getRow(`status = 'pending'`, { strict: false });\n * console.log(flexibleRow);\n * ```\n * @param conditions - The conditions to match, specified as a SQL `WHERE` clause.\n * @param options - Optional settings:\n * @param options.strict - If `false`, returns the first row when multiple rows match. A missing match always throws. Defaults to `true`.\n * @returns A promise that resolves to an object representing the matched row.\n * @throws {Error} If no row matches, or if `strict` is `true` and more than one row matches the conditions.\n * @category Getting Data\n */\n async getRow(\n conditions: string,\n options: { strict?: boolean } = {},\n ): Promise<{\n [key: string]: unknown;\n }> {\n return await getRow(this, conditions, options);\n }\n\n /**\n * Returns the data from the table as an array of objects, optionally filtered by SQL conditions.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * Top-level DuckDB `DATE` and `TIMESTAMP` columns are returned as JavaScript\n * `Date` objects interpreted in UTC. `TIMESTAMP WITH TIME ZONE` values are\n * returned as UTC strings, preserving DuckDB's microsecond precision;\n * JavaScript `Date` supports only milliseconds.\n *\n * Top-level `BIGINT`, `UBIGINT`, `HUGEINT`, and `UHUGEINT` columns are\n * returned as JavaScript numbers. Values outside `Number.MIN_SAFE_INTEGER`\n * through `Number.MAX_SAFE_INTEGER` throw instead of losing precision.\n * Use `convert({ columnName: \"string\" })` before `getData()` to retrieve\n * their exact digits as strings.\n *\n * SQL arrays and lists, including float vectors, return their actual elements\n * as JavaScript arrays. Null cells and null elements remain null.\n *\n * Nested SQL lists and structs become JavaScript arrays and objects. Within\n * them, `BIGINT`, `UBIGINT`, `HUGEINT`, `UHUGEINT`, and `DECIMAL` values remain\n * strings to preserve precision, even for small integers.\n *\n * @example\n * ```ts\n * // Get all data from the table\n * const allData = await table.getData();\n * console.log(allData);\n * ```\n *\n * @example\n * ```ts\n * // Get data filtered by a condition (using JS or SQL syntax)\n * const booksData = await table.getData({ conditions: `category === 'Book'` });\n * console.log(booksData);\n * ```\n *\n * @example\n * ```ts\n * // Get data filtered by a condition and specific columns\n * const booksData = await table.getData({ columns: [\"title\", \"author\"], conditions: `category === 'Book'` });\n * console.log(booksData);\n * ```\n *\n * @example\n * ```ts\n * // Return at most two rows.\n * const preview = await table.getData({ limit: 2 });\n * ```\n *\n * @example\n * ```ts\n * // Read nested integers without losing digits. SQL creates the nested types.\n * await sdb.customQuery(`CREATE TABLE nested_example AS SELECT\n * [42::BIGINT, 9007199254740993::BIGINT] AS ids,\n * {'count': 2::INTEGER, 'amount': 123.450::DECIMAL(6,3)} AS details`);\n * const nested = sdb.newTable(\"nested_example\");\n * const rows = await nested.getData();\n * // [{ ids: [\"42\", \"9007199254740993\"], details: { count: 2, amount: \"123.450\" } }]\n * await nested.log();\n * ```\n * @param options - An optional object with configuration options:\n * @param options.columns - An array of column names to include in the result. If omitted, all columns will be included.\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Book'\"`).\n * @param options.limit - The maximum number of rows to return. Must be an integer greater than or equal to `0`.\n * @returns A promise that resolves to an array of objects, where each object represents a row in the table.\n * @category Getting Data\n */\n async getData(\n options: {\n columns?: string | string[];\n conditions?: string;\n limit?: number;\n } = {},\n ): Promise<\n {\n [key: string]: unknown;\n }[]\n > {\n return await getData(this, options);\n }\n\n /**\n * Streams the table rows one by one as an async iterator, without\n * materializing the whole table in memory. Values are converted to\n * JavaScript types the same way as `getData()`.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * The underlying DuckDB result is streamed chunk by chunk, so tables\n * larger than the available memory can be iterated. Avoid running other\n * queries on the same database while iterating.\n *\n * @example\n * ```ts\n * // Stream all rows\n * for await (const row of table.stream()) {\n * console.log(row);\n * }\n * ```\n *\n * @example\n * ```ts\n * // Stream specific columns and rows\n * for await (const row of table.stream({ columns: \"temperature\", conditions: `temperature > 20` })) {\n * console.log(row);\n * }\n * ```\n * @param options - An optional object with configuration options:\n * @param options.columns - The column name or an array of column names to include. If omitted, all columns are streamed.\n * @param options.conditions - A SQL `WHERE` clause condition to filter the rows.\n * @returns An async generator yielding one row object at a time.\n * @category Getting Data\n */\n stream(\n options: {\n columns?: string | string[];\n conditions?: string;\n } = {},\n ): AsyncGenerator<{ [key: string]: unknown }, void, undefined> {\n return stream(this, options);\n }\n\n /**\n * Returns the data from the table as a CSV string, optionally filtered by SQL conditions.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Temporal values are first converted as they are in `getData()`, then\n * serialized using UTC date and timestamp text.\n *\n * @example\n * ```ts\n * // Get all data from the table as CSV\n * const allDataCSV = await table.getDataAsCSV();\n * console.log(allDataCSV);\n * ```\n *\n * @example\n * ```ts\n * // Get data filtered by a condition (using JS syntax or SQL syntax) as CSV\n * const booksDataCSV = await table.getDataAsCSV({ conditions: `category === 'Book'` });\n * console.log(booksDataCSV);\n * ```\n *\n * @example\n * ```ts\n * // Get data filtered by a condition and specific columns as CSV\n * const booksDataCSV = await table.getDataAsCSV({ columns: [\"title\", \"author\"], conditions: `category === 'Book'` });\n * console.log(booksDataCSV);\n * ```\n * @param options - An optional object with configuration options:\n * @param options.columns - An array of column names to include in the CSV. If omitted, all columns will be included.\n * @param options.conditions - The filtering conditions specified as a SQL `WHERE` clause (e.g., `\"category = 'Book'\"`).\n * @returns A promise that resolves to a CSV-formatted string representation of the table data.\n * @category Getting Data\n */\n async getDataAsCSV(\n options: {\n columns?: string | string[];\n conditions?: string;\n } = {},\n ): Promise<string> {\n const data = await this.getData(options);\n return csvFormat(data);\n }\n\n // GEOSPATIAL\n\n /**\n * Creates point geometries from latitude (y) and longitude (x) columns.\n *\n * @example\n * ```ts\n * // Create point geometries in a new 'geom' column using latitude (y) and longitude (x) columns.\n * // The resulting coordinates are ordered as [longitude, latitude], or [x, y].\n * // The projection is assumed to be EPSG:4326 (WGS84).\n * await table.createPoints(\"lat\", \"lon\", \"geom\").log();\n * ```\n *\n * @example\n * ```ts\n * // Create point geometries from coordinates in a projected coordinate system\n * await table.createPoints(\"y\", \"x\", \"geom\", { projection: \"EPSG:3347\" }).log();\n * ```\n * @param latColumn - The name of the column storing the latitude (y-coordinate) values.\n * @param lonColumn - The name of the column storing the longitude (x-coordinate) values.\n * @param newColumn - The name of the new column where the point geometries will be stored.\n * @param options - An optional object with configuration options:\n * @param options.projection - The projection of the coordinates. Defaults to EPSG:4326 (WGS84), passed as `\"EPSG:4326\"`.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n createPoints(\n latColumn: string,\n lonColumn: string,\n newColumn: string,\n options: { projection?: string } = {},\n ): this {\n createPoints(this, latColumn, lonColumn, newColumn, options);\n return this;\n }\n\n /**\n * Adds a column with boolean values indicating the validity of geometries.\n *\n * @example\n * ```ts\n * // Check if geometries are valid and store results in a new 'isValid' column\n * // The method will automatically detect the geometry column.\n * await table.addGeoValidity(\"isValid\").log();\n * ```\n *\n * @example\n * ```ts\n * // Check validity of geometries in a specific column named 'myGeom'\n * await table.addGeoValidity(\"isValidMyGeom\", { column: \"myGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the boolean results (`TRUE` for valid, `FALSE` for invalid) will be stored.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries to be checked. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addGeoValidity(newColumn: string, options: { column?: string } = {}): this {\n addGeoValidity(this, newColumn, options);\n return this;\n }\n\n /**\n * Adds a column with the number of vertices (points) in each geometry.\n *\n * @example\n * ```ts\n * // Add a new column 'vertexCount' with the number of vertices for each geometry\n * // The method will automatically detect the geometry column.\n * await table.addVertexCount(\"vertexCount\").log();\n * ```\n *\n * @example\n * ```ts\n * // Add vertex counts for geometries in a specific column named 'myGeom'\n * await table.addVertexCount(\"myGeomVertices\", { column: \"myGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the vertex counts will be stored.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addVertexCount(newColumn: string, options: { column?: string } = {}): this {\n addVertexCount(this, newColumn, options);\n return this;\n }\n\n /**\n * Attempts to make invalid geometries valid without removing any vertices.\n *\n * @example\n * ```ts\n * // Fix invalid geometries in the default geometry column\n * await table.fixGeo().log();\n * ```\n *\n * @example\n * ```ts\n * // Fix invalid geometries in a specific column named 'myGeom'\n * await table.fixGeo(\"myGeom\").log();\n * ```\n * @param column - The name of the column storing the geometries to be fixed. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n fixGeo(column?: string): this {\n fixGeo(this, column);\n return this;\n }\n\n /**\n * Adds a column with boolean values indicating whether geometries are closed (e.g., polygons) or open (e.g., linestrings).\n *\n * @example\n * ```ts\n * // Check if geometries are closed and store results in a new 'isClosed' column\n * await table.addGeoClosedStatus(\"isClosed\").log();\n * ```\n *\n * @example\n * ```ts\n * // Check closed status of geometries in a specific column named 'boundaryGeom'\n * await table.addGeoClosedStatus(\"boundaryClosed\", { column: \"boundaryGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the boolean results (`TRUE` for closed, `FALSE` for open) will be stored.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addGeoClosedStatus(newColumn: string, options: { column?: string } = {}): this {\n addGeoClosedStatus(this, newColumn, options);\n return this;\n }\n\n /**\n * Adds a column with the geometry type (e.g., `\"POINT\"`, `\"LINESTRING\"`, `\"POLYGON\"`) for each geometry.\n *\n * @example\n * ```ts\n * // Add a new column 'geometryType' with the type of each geometry\n * await table.addGeoType(\"geometryType\").log();\n * ```\n *\n * @example\n * ```ts\n * // Get the geometry type for geometries in a specific column named 'featureGeom'\n * await table.addGeoType(\"featureType\", { column: \"featureGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the geometry types will be stored.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addGeoType(newColumn: string, options: { column?: string } = {}): this {\n addGeoType(this, newColumn, options);\n return this;\n }\n\n /**\n * Flips the coordinate order of geometries in a specified column (e.g., from `[longitude (x), latitude (y)]` to `[latitude (y), longitude (x)]` or vice-versa).\n * **Warning:** This method should be used with caution as it directly manipulates coordinate order and can affect the accuracy of geospatial operations if not used correctly.\n *\n * @example\n * ```ts\n * // Flip coordinates in the default geometry column\n * await table.flipCoordinates().log();\n * ```\n *\n * @example\n * ```ts\n * // Flip coordinates in a specific column named 'myGeom'\n * await table.flipCoordinates(\"myGeom\").log();\n * ```\n * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n flipCoordinates(column?: string): this {\n flipCoordinates(this, column);\n return this;\n }\n\n /**\n * Moves EPSG:4326 point geometries to random locations within a maximum great-circle distance of their original positions.\n *\n * Points are sampled uniformly within the requested distance using the spherical direct geodesic (destination-point) formula and the same spherical Earth model as DuckDB's `ST_Distance_Sphere()`. This accounts for longitude scale changing with latitude. This method adds random jitter; it does not provide anonymization or differential privacy guarantees.\n *\n * This method supports only `POINT` geometries in `EPSG:4326`. Null and empty geometries are preserved.\n *\n * @example\n * ```ts\n * // Move every point by no more than 500 metres\n * await table.addGeoNoise(500).log();\n * ```\n *\n * @example\n * ```ts\n * // Separate duplicated points by up to 0.1 kilometres\n * await table.addGeoNoise(0.1, {\n * column: \"geom\",\n * unit: \"km\",\n * onlyDuplicates: true,\n * }).log();\n * ```\n * @param maxDistance - The maximum great-circle displacement in the selected unit. Must be a finite number greater than or equal to `0` and no greater than half Earth's circumference.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the EPSG:4326 point geometry column. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.unit - The unit of `maxDistance`: `\"m\"` for metres or `\"km\"` for kilometres. Defaults to `\"m\"`.\n * @param options.onlyDuplicates - If `true`, moves only points whose complete original geometry occurs more than once in the selected geometry column. Every point in a duplicated group is moved. Defaults to `false`.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addGeoNoise(\n maxDistance: number,\n options: {\n column?: string;\n unit?: \"m\" | \"km\";\n onlyDuplicates?: boolean;\n } = {},\n ): this {\n addGeoNoise(this, maxDistance, options);\n return this;\n }\n\n /**\n * Reduces the precision of geometries in a specified column to a given number of decimal places.\n *\n * @example\n * ```ts\n * // Reduce the precision of geometries in the default column to 3 decimal places\n * await table.reducePrecision(3).log();\n * ```\n *\n * @example\n * ```ts\n * // Reduce the precision of geometries in a specific column named 'myGeom' to 2 decimal places\n * await table.reducePrecision(2, { column: \"myGeom\" }).log();\n * ```\n * @param decimals - The number of decimal places to keep in the coordinates of the geometries.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n reducePrecision(decimals: number, options: { column?: string } = {}): this {\n reducePrecision(this, decimals, options);\n return this;\n }\n\n /**\n * Reprojects the geometries in a specified column to another Spatial Reference System (SRS).\n *\n * @example\n * ```ts\n * // Reproject geometries in the default column to EPSG:3347 (NAD83/Statistics Canada Lambert)\n * await table.reproject(\"EPSG:3347\").log();\n * ```\n *\n * @example\n * ```ts\n * // Reproject geometries in a specific column named 'myGeom' to EPSG:3347\n * await table.reproject(\"EPSG:3347\", { column: \"myGeom\" }).log();\n * ```\n * @param crs - The target SRS (e.g., `\"EPSG:3347\"`, or `\"EPSG:4326\"` for EPSG:4326 (WGS84)).\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n reproject(crs: string, options: { column?: string } = {}): this {\n reproject(this, crs, options);\n return this;\n }\n\n /**\n * Computes the area of geometries in square meters (`\"m2\"`) or optionally square kilometers (`\"km2\"`).\n * The input geometry is assumed to be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Compute the area of geometries in square meters and store in 'area_m2'\n * await table.area(\"area_m2\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the area of geometries in square kilometers and store in 'area_km2'\n * await table.area(\"area_km2\", { unit: \"km2\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute areas in square kilometers rounded to two decimal places\n * await table.area(\"area_km2\", { unit: \"km2\", decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the area of geometries in a specific column named 'myGeom'\n * await table.area(\"myGeomArea\", { column: \"myGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the computed areas will be stored.\n * @param options - An optional object with configuration options:\n * @param options.unit - The unit for the computed area: `\"m2\"` (square meters) or `\"km2\"` (square kilometers). Defaults to `\"m2\"`.\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.decimals - The number of decimal places to round the computed areas. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n area(\n newColumn: string,\n options: {\n unit?: \"m2\" | \"km2\";\n column?: string;\n decimals?: number;\n } = {},\n ): this {\n area(this, newColumn, options);\n return this;\n }\n\n /**\n * Computes the length of line geometries in meters (`\"m\"`) or optionally kilometers (`\"km\"`).\n * The input geometry is assumed to be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Compute the length of line geometries in meters and store in 'length_m'\n * await table.length(\"length_m\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the length of line geometries in kilometers and store in 'length_km'\n * await table.length(\"length_km\", { unit: \"km\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute lengths in kilometers rounded to two decimal places\n * await table.length(\"length_km\", { unit: \"km\", decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the length of geometries in a specific column named 'routeGeom'\n * await table.length(\"routeLength\", { column: \"routeGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the computed lengths will be stored.\n * @param options - An optional object with configuration options:\n * @param options.unit - The unit for the computed length: `\"m\"` (meters) or `\"km\"` (kilometers). Defaults to `\"m\"`.\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.decimals - The number of decimal places to round the computed lengths. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n length(\n newColumn: string,\n options: {\n unit?: \"m\" | \"km\";\n column?: string;\n decimals?: number;\n } = {},\n ): this {\n length(this, newColumn, options);\n return this;\n }\n\n /**\n * Computes the perimeter of polygon geometries in meters (`\"m\"`) or optionally kilometers (`\"km\"`).\n * The input geometry is assumed to be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Compute the perimeter of polygon geometries in meters and store in 'perimeter_m'\n * await table.perimeter(\"perimeter_m\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the perimeter of polygon geometries in kilometers and store in 'perimeter_km'\n * await table.perimeter(\"perimeter_km\", { unit: \"km\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute perimeters in kilometers rounded to two decimal places\n * await table.perimeter(\"perimeter_km\", { unit: \"km\", decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the perimeter of geometries in a specific column named 'landParcelGeom'\n * await table.perimeter(\"landParcelPerimeter\", { column: \"landParcelGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the computed perimeters will be stored.\n * @param options - An optional object with configuration options:\n * @param options.unit - The unit for the computed perimeter: `\"m\"` (meters) or `\"km\"` (kilometers). Defaults to `\"m\"`.\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.decimals - The number of decimal places to round the computed perimeters. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n perimeter(\n newColumn: string,\n options: {\n unit?: \"m\" | \"km\";\n column?: string;\n decimals?: number;\n } = {},\n ): this {\n perimeter(this, newColumn, options);\n return this;\n }\n\n /**\n * Computes a buffer (a polygon representing a specified distance around a geometry) for geometries in a specified column.\n * The distance is in the Spatial Reference System (SRS) unit of the input geometries.\n *\n * @example\n * ```ts\n * // Create a buffer of 1 unit around geometries in the default column, storing results in 'bufferedGeom'\n * await table.buffer(\"bufferedGeom\", 1).log();\n * ```\n *\n * @example\n * ```ts\n * // Create a buffer of 10 units around geometries in a specific column named 'pointsGeom'\n * await table.buffer(\"pointsBuffer\", 10, { column: \"pointsGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the buffered geometries will be stored.\n * @param distance - The distance for the buffer. This value is in the units of the geometry's SRS.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n buffer(newColumn: string, distance: number, options: { column?: string } = {}): this {\n buffer(this, newColumn, distance, options);\n return this;\n }\n\n /**\n * Merges the data of this table (considered the left table) with another table (the right table) based on a spatial relationship.\n * Note that the order of rows in the returned data is not guaranteed to be the same as in the original tables.\n * This operation might create temporary files in a `.tmp` folder; consider adding `.tmp` to your `.gitignore`.\n *\n * @example\n * ```ts\n * // Merge data based on intersecting geometries, overwriting tableA\n * await tableA.joinGeo(tableB, \"intersect\").log();\n * ```\n *\n * @example\n * ```ts\n * // Merge data where geometries in tableA are inside geometries in tableB\n * await tableA.joinGeo(tableB, \"inside\").log();\n * ```\n *\n * @example\n * ```ts\n * // Join using both geometries without copying them into the result\n * await tableA.joinGeo(tableB, \"intersect\", {\n * excludeLeftGeometry: true,\n * excludeRightGeometry: true,\n * }).log();\n * ```\n *\n * @example\n * ```ts\n * // Merge data where geometries in tableA are within 10 units (SRS) of geometries in tableB\n * await tableA.joinGeo(tableB, \"withinDistance\", { distance: 10 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Merge data where geometries in tableA are within 10 kilometers (Haversine) of geometries in tableB\n * // Input geometries must be in EPSG:4326 (WGS84).\n * await tableA.joinGeo(tableB, \"withinDistance\", { distance: 10, distanceMethod: \"haversine\", unit: \"km\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Merge data with specific geometry columns and an inner join type, storing results in a new table\n * const tableC = await tableA.joinGeo(tableB, \"intersect\", {\n * leftColumn: \"geometriesA\",\n * rightColumn: \"geometriesB\",\n * type: \"inner\",\n * outputTable: true,\n * }).log();\n * ```\n * @param rightTable - The SimpleTable instance to be joined with this table.\n * @param method - The spatial join method to use: `\"intersect\"` (geometries overlap), `\"inside\"` (geometries of the left table are entirely within geometries of the right table), or `\"withinDistance\"` (geometries of the left table are within a specified distance of geometries in the right table).\n * @param options - An optional object with configuration options:\n * @param options.leftColumn - The name of the column storing geometries in the left table (this table). If omitted, the method attempts to find one.\n * @param options.rightColumn - The name of the column storing geometries in the right table. If omitted, the method attempts to find one.\n * @param options.type - The type of join operation to perform: `\"inner\"`, `\"left\"` (default), `\"right\"`, or `\"full\"`. For some types (like `\"inside\"`), the table order is important.\n * @param options.distance - Required if `method` is `\"withinDistance\"`. The target distance for the spatial join. The unit depends on `distanceMethod`.\n * @param options.distanceMethod - The method for distance calculations: `\"srs\"` (default, uses the SRS unit), `\"haversine\"` (uses meters, requires EPSG:4326 (WGS84) input), or `\"spheroid\"` (uses meters, requires EPSG:4326 (WGS84) input, most accurate but slowest).\n * @param options.excludeLeftGeometry - Whether to exclude the selected `leftColumn` geometry from the result. Defaults to `false`.\n * @param options.excludeRightGeometry - Whether to exclude the selected `rightColumn` geometry from the result. Defaults to `false`.\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the spatially joined data (either the current table or a new table), so methods can be chained.\n * @category Geospatial\n */\n joinGeo(\n rightTable: SimpleTable,\n method: \"intersect\" | \"inside\" | \"withinDistance\",\n options: {\n leftColumn?: string;\n rightColumn?: string;\n type?: \"inner\" | \"left\" | \"right\" | \"full\";\n distance?: number;\n distanceMethod?: \"srs\" | \"haversine\" | \"spheroid\";\n excludeLeftGeometry?: boolean;\n excludeRightGeometry?: boolean;\n outputTable?: string | boolean;\n } = {},\n ): this {\n options = { ...options };\n if (options.outputTable === true) {\n options.outputTable = `table${this.sdb.tableIncrement}`;\n this.sdb.tableIncrement += 1;\n }\n return joinGeo(this, method, rightTable, options) as this;\n }\n\n /**\n * Computes the intersection of two sets of geometries, creating new geometries where they overlap.\n *\n * @example\n * ```ts\n * // Compute the intersection of geometries in 'geomA' and 'geomB' columns, storing results in 'intersectGeom'\n * await table.intersection(\"geomA\", \"geomB\", \"intersectGeom\").log();\n * ```\n * @param column1 - The name of the first column storing geometries.\n * @param column2 - The name of the second column storing geometries. Both columns must have the same projection.\n * @param newColumn - The name of the new column where the computed intersection geometries will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n intersection(column1: string, column2: string, newColumn: string): this {\n intersection(this, column1, column2, newColumn);\n return this;\n }\n\n /**\n * Computes the geometric difference between two geometries, returning the portion of the first geometry that does not intersect the second.\n *\n * @example\n * ```ts\n * // Subtract 'geomB' from 'geomA', storing the result in 'geomA_minus_geomB'\n * await table.difference(\"geomA\", \"geomB\", \"geomA_minus_geomB\").log();\n * ```\n * @param column1 - The name of the column storing the geometries from which the second geometries will be subtracted.\n * @param column2 - The name of the column storing the geometries to subtract. Both columns must have the same projection.\n * @param newColumn - The name of the new column where the geometric differences will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n difference(column1: string, column2: string, newColumn: string): this {\n difference(this, column1, column2, newColumn);\n return this;\n }\n\n /**\n * Fills holes in polygon geometries.\n *\n * @example\n * ```ts\n * // Fill holes in geometries in the default geometry column\n * await table.fillHoles().log();\n * ```\n *\n * @example\n * ```ts\n * // Fill holes in geometries in a specific column named 'polygonGeom'\n * await table.fillHoles(\"polygonGeom\").log();\n * ```\n * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n fillHoles(column?: string): this {\n fillHoles(this, column);\n return this;\n }\n\n /**\n * Returns `TRUE` if two geometries intersect (overlap in any way), and `FALSE` otherwise.\n *\n * @example\n * ```ts\n * // Check if geometries in 'geomA' and 'geomB' intersect, storing results in 'doIntersect'\n * await table.intersects(\"geomA\", \"geomB\", \"doIntersect\").log();\n * ```\n * @param column1 - The name of the first column storing geometries.\n * @param column2 - The name of the second column storing geometries. Both columns must have the same projection.\n * @param newColumn - The name of the new column where the boolean results (`TRUE` for intersection, `FALSE` otherwise) will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n intersects(column1: string, column2: string, newColumn: string): this {\n intersects(this, column1, column2, newColumn);\n return this;\n }\n\n /**\n * Returns `TRUE` if every point of a geometry in `column` is covered by a geometry in `containerColumn`, including their boundaries, and `FALSE` otherwise.\n *\n * @example\n * ```ts\n * // Check if geometries in 'pointGeom' are covered by 'polygonGeom', storing results in 'isCovered'\n * await table.coveredBy(\"pointGeom\", \"polygonGeom\", \"isCovered\").log();\n * ```\n * @param column - The name of the column storing the geometries to be tested for containment.\n * @param containerColumn - The name of the column storing the geometries to be tested as containers. Both columns must have the same projection.\n * @param newColumn - The name of the new column where the boolean results (`TRUE` when covered, `FALSE` otherwise) will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n coveredBy(column: string, containerColumn: string, newColumn: string): this {\n coveredBy(this, column, containerColumn, newColumn);\n return this;\n }\n\n /**\n * Computes the union of two geometries, creating a new geometry that represents the merged area of both.\n *\n * @example\n * ```ts\n * // Compute the union of geometries in 'geomA' and 'geomB', storing results in 'unionGeom'\n * await table.union(\"geomA\", \"geomB\", \"unionGeom\").log();\n * ```\n * @param column1 - The name of the first column storing geometries.\n * @param column2 - The name of the second column storing geometries. Both columns must have the same projection.\n * @param newColumn - The name of the new column where the computed union geometries will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n union(column1: string, column2: string, newColumn: string): this {\n union(this, column1, column2, newColumn);\n return this;\n }\n\n /**\n * Extracts the latitude (y) and longitude (x) coordinates from point geometries.\n * The input geometry is assumed to be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Extract latitude (y) and longitude (x) from 'geom' into new 'lat' and 'lon' columns.\n * await table.extractLatLon(\"geom\", \"lat\", \"lon\").log();\n * ```\n * @param column - The name of the column storing the point geometries.\n * @param latColumn - The name of the new column where the extracted latitude (y-coordinate) values will be stored.\n * @param lonColumn - The name of the new column where the extracted longitude (x-coordinate) values will be stored.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n extractLatLon(column: string, latColumn: string, lonColumn: string): this {\n extractLatLon(this, column, latColumn, lonColumn);\n return this;\n }\n\n /**\n * Simplifies geometries while preserving their overall coverage. A higher tolerance results in more significant simplification.\n *\n * @example\n * ```ts\n * // Simplify geometries in the default column with a tolerance of 0.1\n * await table.simplify(0.1).log();\n * ```\n *\n * @example\n * ```ts\n * // Simplify geometries in 'myGeom' column, preserving the boundary\n * await table.simplify(0.05, { column: \"myGeom\", simplifyBoundary: false }).log();\n * ```\n * @param tolerance - A numeric value representing the simplification tolerance. A higher value leads to greater simplification.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.simplifyBoundary - If `true` (default), the boundary of the geometries will also be simplified. If `false`, only the interior of the geometries will be simplified, preserving the original boundary.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n simplify(tolerance: number, options: { column?: string; simplifyBoundary?: boolean } = {}): this {\n simplify(this, tolerance, options);\n return this;\n }\n\n /**\n * Computes the centroid of geometries.\n * The values are returned in the SRS unit of the input geometries.\n *\n * @example\n * ```ts\n * // Compute the centroid of geometries in the default column, storing results in 'centerPoint'\n * await table.centroid(\"centerPoint\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute the centroid of geometries in a specific column named 'areaGeom'\n * await table.centroid(\"areaCentroid\", { column: \"areaGeom\" }).log();\n * ```\n * @param newColumn - The name of the new column where the computed centroid geometries will be stored.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n centroid(newColumn: string, options: { column?: string } = {}): this {\n centroid(this, newColumn, options);\n return this;\n }\n\n /**\n * Generates a random point within the geometries of a specified column.\n *\n * @example\n * ```ts\n * // Generate a random point for each geometry in the default column, trying 100 points\n * await table.randomPoint(\"randomPoint\", 100).log();\n * ```\n *\n * @example\n * ```ts\n * // Generate a random point for each geometry in a specific column named 'areaGeom', trying 50 points\n * await table.randomPoint(\"pointInArea\", 50, { column: \"areaGeom\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Generate a random point for each geometry, but don't throw if some points cannot be generated\n * await table.randomPoint(\"pointInArea\", 1, { strict: false }).log();\n * ```\n * @param newColumn - The name of the new column where the random points will be stored.\n * @param tries - The number of points to generate within the bounding box of each geometry to find one that is within the geometry itself.\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries within which the random points will be generated. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.strict - If `false`, the method will not throw an error if some points cannot be generated. Corresponding rows will have `NULL` in the new column. Defaults to `true`.\n */\n randomPoint(\n newColumn: string,\n tries: number,\n options: { column?: string; strict?: boolean } = {},\n ): this {\n randomPoint(this, newColumn, tries, options);\n return this;\n }\n\n /**\n * Computes the distance between geometries in two specified columns.\n * By default, the distance is calculated in the Spatial Reference System (SRS) unit of the input geometries.\n * You can optionally specify `\"spheroid\"` or `\"haversine\"` methods to get results in meters or kilometers.\n * If using `\"spheroid\"` or `\"haversine\"`, the input geometries must be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Compute distance between 'geomA' and 'geomB' in SRS units, store in 'distance_srs'\n * await table.distance(\"geomA\", \"geomB\", \"distance_srs\").log();\n * ```\n *\n * @example\n * ```ts\n * // Compute Haversine distance in meters between 'point1' and 'point2', store in 'distance_m'\n * // Input geometries must be in EPSG:4326 (WGS84).\n * await table.distance(\"point1\", \"point2\", \"distance_m\", { method: \"haversine\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute Haversine distance in kilometers, rounded to 2 decimal places\n * // Input geometries must be in EPSG:4326 (WGS84).\n * await table.distance(\"point1\", \"point2\", \"distance_km\", { method: \"haversine\", unit: \"km\", decimals: 2 }).log();\n * ```\n *\n * @example\n * ```ts\n * // Compute Spheroid distance in kilometers\n * // Input geometries must be in EPSG:4326 (WGS84).\n * await table.distance(\"area1\", \"area2\", \"distance_spheroid_km\", { method: \"spheroid\", unit: \"km\" }).log();\n * ```\n * @param column1 - The name of the first column storing geometries.\n * @param column2 - The name of the second column storing geometries.\n * @param newColumn - The name of the new column where the computed distances will be stored.\n * @param options - An optional object with configuration options:\n * @param options.method - The method to use for distance calculations: `\"srs\"` (default, uses SRS unit), `\"haversine\"` (meters, requires EPSG:4326 (WGS84)), or `\"spheroid\"` (meters, requires EPSG:4326 (WGS84), most accurate but slowest).\n * @param options.unit - If `method` is `\"spheroid\"` or `\"haversine\"`, you can choose between `\"m\"` (meters, default) or `\"km\"` (kilometers).\n * @param options.decimals - The number of decimal places to round the distance values. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n distance(\n column1: string,\n column2: string,\n newColumn: string,\n options: {\n unit?: \"m\" | \"km\";\n method?: \"srs\" | \"haversine\" | \"spheroid\";\n decimals?: number;\n } = {},\n ): this {\n distance(this, column1, column2, newColumn, options);\n return this;\n }\n\n /**\n * Unnests geometries recursively, transforming multi-part geometries (e.g., MultiPolygon) into individual single-part geometries (e.g., Polygon).\n *\n * @example\n * ```ts\n * // Unnest geometries in the default column\n * await table.unnestGeo().log();\n * ```\n *\n * @example\n * ```ts\n * // Unnest geometries in a specific column named 'multiGeom'\n * await table.unnestGeo(\"multiGeom\").log();\n * ```\n * @param column - The name of the column storing the geometries to be unnested. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n unnestGeo(column?: string): this {\n unnestGeo(this, column);\n return this;\n }\n\n /**\n * Adds the bounding box coordinates of geometries in a specified column as four new columns: `minLon`, `minLat`, `maxLon`, and `maxLat`.\n *\n * @example\n * ```ts\n * // Compute the bounding box for geometries in the default column\n * await table.addBoundingBox().log();\n * // The table now has minLon, minLat, maxLon, and maxLat columns.\n * ```\n *\n * @example\n * ```ts\n * // Compute the bounding box for geometries in 'geom' column and round coordinates to 2 decimal places\n * await table.addBoundingBox({ column: \"geom\", decimals: 2 }).log();\n * // The table now has minLon, minLat, maxLon, and maxLat columns with values rounded to 2 decimal places.\n * ```\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries for which the bounding box will be computed. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.decimals - The number of decimal places to round the bounding box coordinates. Defaults to `undefined` (no rounding).\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n addBoundingBox(\n options: {\n column?: string;\n decimals?: number;\n } = {},\n ): this {\n addBoundingBox(this, options);\n return this;\n }\n\n /**\n * Aggregates geometries in a specified column based on a chosen aggregation method.\n *\n * @example\n * ```ts\n * // Aggregate all geometries in the default column into a single union geometry\n * await table.aggregateGeo(\"union\").log();\n * ```\n *\n * @example\n * ```ts\n * // Aggregate geometries by 'country' and compute their union\n * await table.aggregateGeo(\"union\", { by: \"country\" }).log();\n * ```\n *\n * @example\n * ```ts\n * // Aggregate geometries in 'regions' column into their intersection, storing results in a new table\n * const intersectionTable = await table.aggregateGeo(\"intersection\", { column: \"regions\", outputTable: true }).log();\n * ```\n * @param method - The aggregation method to apply: `\"union\"` (combines all geometries into a single multi-geometry) or `\"intersection\"` (computes the intersection of all geometries).\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries to be aggregated. If omitted, the method will automatically attempt to find a geometry column.\n * @param options.by - The column name or an array of column names to group by. Geometries are aggregated independently within each group.\n * @param options.outputTable - If `true`, the results will be stored in a new table with a generated name. If a string, it will be used as the name for the new table. If `false` or omitted, the current table will be overwritten. Defaults to `false`.\n * @returns A table instance containing the aggregated geometries (either the current table or a new table), so methods can be chained.\n * @category Geospatial\n */\n aggregateGeo(\n method: \"union\" | \"intersection\",\n options: {\n column?: string;\n by?: string | string[];\n outputTable?: string | boolean;\n } = {},\n ): this {\n return aggregateGeo(this, method, options) as this;\n }\n\n /**\n * Transforms closed linestring geometries into polygon geometries.\n *\n * @example\n * ```ts\n * // Transform closed linestrings in the default geometry column into polygons\n * await table.linesToPolygons().log();\n * ```\n *\n * @example\n * ```ts\n * // Transform closed linestrings in a specific column named 'routeLines' into polygons\n * await table.linesToPolygons(\"routeLines\").log();\n * ```\n * @param column - The name of the column storing the linestring geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns The table, so methods can be chained.\n * @category Geospatial\n */\n linesToPolygons(column?: string): this {\n linesToPolygons(this, column);\n return this;\n }\n\n /**\n * Returns the bounding box of geometries in `[minLon, minLat, maxLon, maxLat]` order.\n * By default, the method will try to find the column with the geometries. The input geometry is assumed to be in EPSG:4326 (WGS84).\n *\n * @example\n * ```ts\n * // Get the bounding box of geometries in the default column\n * const bbox = await table.getBoundingBox();\n * console.log(bbox); // e.g., [-75.0, 45.0, -73.0, 46.0]\n * ```\n *\n * @example\n * ```ts\n * // Get the bounding box of geometries in a specific column named 'areaGeom'\n * const areaBbox = await table.getBoundingBox(\"areaGeom\");\n * console.log(areaBbox);\n * ```\n * @param column - The name of the column storing geometries. If omitted, the method will automatically attempt to find a geometry column.\n * @returns A promise that resolves to an array `[minLon, minLat, maxLon, maxLat]` representing the bounding box.\n * @category Geospatial\n */\n async getBoundingBox(column?: string): Promise<[number, number, number, number]> {\n return await getBoundingBox(this, column);\n }\n\n /**\n * Returns the table's geospatial data as a GeoJSON FeatureCollection.\n * Each row becomes a Feature: the selected geometry column becomes its geometry,\n * and the remaining columns become its properties.\n * If the table has multiple geometry columns, you must specify which one to use.\n *\n * @example\n * ```ts\n * // Get GeoJSON data from the default geometry column\n * const geojson = await table.getGeoData();\n * console.log(geojson);\n * ```\n *\n * @example\n * ```ts\n * // Get GeoJSON data from a specific geometry column named 'myGeometries'\n * const myGeomJson = await table.getGeoData({ column: \"myGeometries\" });\n * console.log(myGeomJson);\n * ```\n *\n * @example\n * ```ts\n * // Get GeoJSON data and rewind polygon coordinates for D3.js compatibility\n * const rewoundGeojson = await table.getGeoData({ rewind: true });\n * console.log(rewoundGeojson);\n * ```\n * @param options - An optional object with configuration options:\n * @param options.column - The name of the column storing the geometries. If omitted, the table must have exactly one geometry column, which will be selected automatically.\n * @param options.rewind - If `true`, rewinds the coordinates of polygons to follow the spherical winding order (important for D3.js). Defaults to `false`.\n * @returns A promise that resolves to a GeoJSON object representing the table's geospatial data.\n * @category Getting Data\n */\n async getGeoData(options: { column?: string; rewind?: boolean } = {}): Promise<{\n type: string;\n features: unknown[];\n }> {\n let column = options.column;\n if (column === undefined) {\n column = await findGeoColumn(this, \"getGeoData()\");\n }\n\n return await getGeoData(this, column, options);\n }\n\n /**\n * Writes the table's data to a file in various formats (CSV, JSON, Parquet, DuckDB, SQLite).\n * Tables with geometry columns must use `writeGeoData()` instead.\n * If the specified path does not exist, it will be created.\n *\n * @example\n * ```ts\n * // Write data to a CSV file\n * await table.writeData(\"./output.csv\");\n * ```\n *\n * @example\n * ```ts\n * // Write data to a JSON file with GZIP compression.\n * // The output file will be named output.json.gz.\n * await table.writeData(\"./output.json\", { compression: true });\n * ```\n *\n * @example\n * ```ts\n * // Write data to a Parquet file\n * await table.writeData(\"./output.parquet\");\n * ```\n *\n * @example\n * ```ts\n * // Write data to a DuckDB database file\n * await table.writeData(\"./my_database.db\");\n * ```\n *\n * @example\n * ```ts\n * // Write data to a SQLite database file\n * await table.writeData(\"./my_database.sqlite\");\n * ```\n *\n * @example\n * ```ts\n * // Write JSON data with dates formatted as ISO strings\n * await table.writeData(\"./output_dates.json\", { formatDates: true });\n * ```\n * @param file - The absolute path to the output file (e.g., `\"./output.csv\"`, `\"./output.json\"`).\n * @param options - An optional object with configuration options:\n * @param options.compression - A boolean indicating whether to compress the output file. If `true`, CSV and JSON files will be compressed with GZIP, while Parquet files will use ZSTD. Defaults to `false`.\n * @param options.dataAsArrays - For JSON files only. If `true`, JSON files are written as a single object with arrays for each column (e.g., `{ \"col1\": [v1, v2], \"col2\": [v3, v4] }`) instead of an array of objects. This can reduce file size for web projects. You can use the `arraysToData` function from the [journalism-format library](https://nshiab.github.io/journalism-format/functions/arraysToData.html) to convert it back.\n * @param options.formatDates - For CSV and JSON files only. If `true`, date and timestamp columns will be formatted as ISO 8601 strings (e.g., `\"2025-01-01T01:00:00.000Z\"`). Defaults to `false`.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category File Operations\n */\n async writeData(\n file: string,\n options: {\n compression?: boolean;\n dataAsArrays?: boolean;\n formatDates?: boolean;\n } = {},\n ): Promise<this> {\n await writeData(this, file, options);\n return this;\n }\n\n /**\n * Writes the table's geospatial data to a file in GeoJSON, GeoParquet, or Shapefile format.\n * If the specified path does not exist, it will be created.\n *\n * @example\n * ```ts\n * // Write geospatial data to a GeoJSON file\n * await table.writeGeoData(\"./output.geojson\");\n * ```\n *\n * @example\n * ```ts\n * // Write geospatial data to a ZSTD-compressed GeoParquet file\n * await table.writeGeoData(\"./output.geoparquet\", { compression: true });\n * ```\n *\n * @example\n * ```ts\n * // Write geospatial data to a Shapefile with all relevant files in the same folder\n * await table.writeGeoData(\"./shapefile-folder/output.shp\");\n * ```\n *\n * @example\n * ```ts\n * // Write a Shapefile and its related files to output.shp.zip\n * await table.writeGeoData(\"./output.shp.zip\");\n * ```\n *\n * @example\n * ```ts\n * // Write GeoJSON with specific precision and metadata\n * await table.writeGeoData(\"./output_high_precision.geojson\", {\n * precision: 6,\n * metadata: { source: \"SimpleDataAnalysis\" },\n * });\n * ```\n * @param file - The absolute path to the output file (e.g., `\"./output.geojson\"`, `\"./output.geoparquet\"`, `\"./shapefile-folder/output.shp\"`, `\"./output.shp.zip\"`). A `.shp.zip` extension writes a ZIP archive using fast DEFLATE compression. Creating the archive temporarily requires enough disk space for both the uncompressed Shapefile and the ZIP, and ZIP archives are limited to 4 GB.\n * @param options - An optional object with configuration options:\n * @param options.precision - For GeoJSON, the maximum number of figures after the decimal separator to write in coordinates. Defaults to `undefined` (full precision).\n * @param options.compression - For GeoParquet, if `true`, uses ZSTD compression; otherwise, uses DuckDB's default SNAPPY compression. SNAPPY prioritizes faster compression, while ZSTD typically produces smaller files but takes longer to write. Read performance depends on the data and storage because smaller files can reduce I/O. This option is not supported for GeoJSON or Shapefiles. Defaults to `false`.\n * @param options.rewind - For GeoJSON, if `true`, rewinds the coordinates of polygons to follow the right-hand rule (RFC 7946). Defaults to `false`.\n * @param options.metadata - For GeoJSON, an object to be added as top-level metadata to the GeoJSON output.\n * @param options.formatDates - For GeoJSON, if `true`, formats date and timestamp columns to ISO 8601 strings. Defaults to `false`.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category File Operations\n */\n async writeGeoData(\n file: string,\n options: {\n precision?: number;\n compression?: boolean;\n rewind?: boolean;\n metadata?: unknown;\n formatDates?: boolean;\n } = {},\n ): Promise<this> {\n await writeGeoData(this, file, options);\n return this;\n }\n\n /**\n * Caches the results of computations in `./.sda-cache`.\n * You should add `./.sda-cache` to your `.gitignore` file.\n *\n * Callback code and function/class inputs ignore comments, indentation, and\n * line wrapping where safe.\n *\n * `cache()` automatically tracks whether earlier SDA operations changed the\n * table. It also records every other already registered `SimpleTable` read\n * through `SimpleTable` methods while `compute` runs and invalidates the\n * cached step when any of their generations change. Tables created inside\n * `compute` are part of the computation itself and are not dependencies.\n *\n * Inside `compute`, you may modify the table being cached and create or\n * modify temporary tables, provided you remove them before the callback\n * finishes. Other tables that already existed may be read but not modified,\n * renamed, or removed. `customQuery()` bypasses enforcement of these rules.\n *\n * `SimpleDB.customQuery()` bypasses this tracking. Reading or changing a\n * table with `customQuery()` can therefore return stale cached data. Include\n * a value that identifies the custom query's dependencies in `options.inputs`\n * (such as a table content hash), or use tracked `SimpleTable` methods.\n *\n * Cache entries are stored as DuckDB database files. Full-text search (FTS)\n * indexes are persisted in the cache file and restored directly on a cache\n * hit. Vector similarity search (VSS/HNSW) indexes are not persisted in the\n * cache file; their definitions are stored as metadata and used to rebuild\n * the indexes on every cache hit. If loading the entry or restoring its\n * indexes fails, the computation runs again and replaces the cache entry.\n *\n * @example\n * ```ts\n * // Computations are re-run if the callback changes or earlier operations modify the table\n * const sdb = new SimpleDB();\n * const items = await sdb.newTable(\"items\").cache((table) => {\n * table\n * .loadData(\"items.csv\")\n * .summarize({\n * columns: \"price\",\n * by: \"department\",\n * stats: [\"min\", \"max\", \"mean\"],\n * });\n * });\n * await items.log();\n *\n * // It's important to call close() on the SimpleDB instance to clean up the cache.\n * // This prevents the cache from growing indefinitely.\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Cache with a Time-To-Live (TTL) of 60 seconds\n * // The computations will be re-run if the cached data is older than 1 minute, the callback changes, or the table changes.\n * const sdb = new SimpleDB();\n * const table = await sdb.newTable().cache((table) => {\n * table\n * .loadData(\"items.csv\")\n * .summarize({\n * columns: \"price\",\n * by: \"department\",\n * stats: [\"min\", \"max\", \"mean\"],\n * });\n * }, { ttl: 60 });\n * await table.log();\n *\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Enable verbose logging for cache operations via SimpleDB instance\n * const sdb = new SimpleDB({ cacheVerbose: true });\n * const table = await sdb.newTable().cache((table) => {\n * table\n * .loadData(\"items.csv\")\n * .summarize({\n * columns: \"price\",\n * by: \"department\",\n * stats: [\"min\", \"max\", \"mean\"],\n * });\n * });\n * await table.log();\n *\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Read-only table dependencies are tracked automatically. Other captured values go in inputs.\n * const year = 2026;\n * const summary = await sdb.newTable(\"summary\").cache(async (table) => {\n * table.loadArray(\n * await fires.getData({ conditions: `year = ${year}` }),\n * );\n * }, { inputs: [year] });\n * await summary.log();\n * ```\n * @param compute - A function wrapping the computations to be cached. It receives the table on which `cache()` was called. This function will be executed on the first run or if the cached data is invalid/expired.\n * @param options - An optional object with configuration options:\n * @param options.inputs - An ordered array of additional values captured by `compute` that affect its result. Each position is compared structurally across runs, so adding, removing, moving, or changing an input invalidates the cache. Functions and class constructors are compared by source. `SimpleTable` dependencies read by `compute` are tracked automatically, and the table being cached is already tracked, so neither needs to be included here.\n * @param options.ttl - Cache lifetime in seconds. Omit for no expiration, use `0` to refresh the matching cache entry immediately, or provide a positive value to refresh once the entry reaches that age. The cache is also invalidated when the `compute` function, the table, or an input changes.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category Caching\n */\n async cache(\n compute: (table: this) => void | Promise<void>,\n options: {\n inputs?: readonly unknown[];\n ttl?: number;\n } = {},\n ): Promise<this> {\n await cache(this, compute, { ...options, verbose: this.sdb.cacheVerbose });\n return this;\n }\n\n /**\n * Logs up to a specified number of rows from the table to the console. By default, the first 10 rows are logged.\n * You can optionally log the column types and filter the data based on conditions.\n * The footer reports the total number of matching rows and, only when some rows\n * are omitted, the number actually shown (for example, `100 rows in total / showing 15 rows`).\n * SQL dates and timestamps retain their native precision for display, including\n * temporal infinities. Lists and objects are stringified using the same nested\n * representations as `getData()`, then truncated according to `charsToLog`.\n * Unsafe top-level large integers throw, just as with `getData()`.\n * Type annotations describe the SQL type and the JavaScript extraction type\n * before display formatting; nulls do not determine the column's annotation.\n * Colors reflect the SQL value's meaning, so exact decimal strings use numeric\n * coloring. Column width is independent of the content truncation budget.\n *\n * With the default `SimpleDB.expressionSyntax: \"js\"`, conditions support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n *\n * @example\n * ```ts\n * // Log the first 10 rows (default behavior)\n * await table.log();\n * ```\n *\n * @example\n * ```ts\n * // Log the first 50 rows\n * await table.log(50);\n * ```\n *\n * @example\n * ```ts\n * // Log all rows\n * await table.log(\"all\");\n * ```\n *\n * @example\n * ```ts\n * // Log the first 20 rows and include column types\n * await table.log({ count: 20, types: true });\n * ```\n *\n * @example\n * ```ts\n * // Log rows where 'status' is 'active' (using JS syntax for conditions)\n * await table.log({ conditions: `status === 'active'` });\n * ```\n * @param options - Either the number of rows to log (a specific number or `\"all\"`) or an object with configuration options:\n * @param options.count - The maximum number of rows to log. Defaults to 10 or the value set in the SimpleDB instance. Use `\"all\"` to log all rows.\n * @param options.types - Whether to log the column types along with the data. Defaults to the value set in the SimpleDB instance.\n * @param options.conditions - A SQL `WHERE` clause condition to filter the data before logging. Defaults to no condition.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category Logging\n */\n async log(\n options:\n | \"all\"\n | number\n | {\n count?: number | \"all\";\n types?: boolean;\n conditions?: string;\n } = {},\n ): Promise<this> {\n await log(this, options);\n return this;\n }\n\n /**\n * Generates and logs a histogram of a numeric column to the console.\n *\n * @example\n * // Basic histogram of the 'temperature' column\n * ```typescript\n * await table.logHistogram(\"temperature\")\n * ```\n *\n * @example\n * // Histogram with 20 bins and custom label formatting\n * ```typescript\n * await table.logHistogram(\"age\", {\n * bins: 20,\n * formatLabels: (min, max) => `${min}-${max} years`,\n * });\n * ```\n * @param values - The name of the numeric column for which to generate the histogram.\n * @param options - An optional object with configuration options:\n * @param options.bins - The number of bins (intervals) to use for the histogram. Defaults to 10.\n * @param options.formatLabels - A function to format the labels for the histogram bins. It receives the lower and upper bounds of each bin as arguments.\n * @param options.compact - If `true`, the histogram will be displayed in a more compact format. Defaults to `false`.\n * @param options.width - The maximum width of the histogram bars in characters.\n * @returns A promise that resolves when the histogram has been logged to the console.\n * @category Dataviz\n */\n /**\n * Logs descriptive information about the columns in the table to the console. This includes details such as data types, number of null values, and number of distinct values for each column.\n * It internally calls the `getDescription` method to retrieve the descriptive statistics.\n *\n * @example\n * ```ts\n * // Log descriptive information for all columns in the table\n * await table.logDescription();\n * ```\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category Logging\n */\n async logDescription(): Promise<this> {\n await this.run();\n if (this.connection === undefined || !(await this.sdb.hasTable(this.name))) {\n console.log(`\\nTable ${this.name}: no data`);\n } else {\n console.log(`\\nTable ${this.name}:`);\n logData(null, await getDescription(this), this.charsToLog);\n }\n return this;\n }\n\n /**\n * Retrieves the projection of a specified geospatial column.\n *\n * @example\n * ```ts\n * // Get the projection of the 'geom' column\n * const projection = await table.getProjection(\"geom\");\n * ```\n * @param column - The name of the geospatial column for which to retrieve the projection.\n * @returns A promise that resolves to the projection of the specified column.\n * @category Geospatial\n */\n async getProjection(column: string): Promise<string> {\n const res = (\n (await this.sdb.customQuery(\n `SELECT ST_CRS(${quoteIdentifier(column)}) AS proj FROM ${quoteIdentifier(\n this.name,\n )} LIMIT 1;`,\n { returnData: true },\n )) as { proj: string | null }[]\n )[0];\n const proj = res && res.proj !== \"null\" ? res.proj : null;\n\n return `GEOMETRY${proj ? `('${proj}')` : \"\"}`;\n }\n\n /**\n * Logs the projections of the geospatial data (if any) to the console.\n *\n * @example\n * ```ts\n * // Log the geospatial projections of the table\n * await table.logProjections();\n * ```\n * @returns A promise that resolves to the SimpleTable instance after logging the projections.\n * @category Logging\n */\n async logProjections(): Promise<this> {\n console.log(`\\nTable ${this.name} projections:`);\n const types = await this.getTypes();\n const geoColumns = Object.entries(types)\n .filter(([, type]) => type.toLowerCase().includes(\"geometry\"))\n .map(([column]) => column);\n\n if (geoColumns.length === 0) {\n console.log(\"No geometry columns found.\");\n } else {\n for (const column of geoColumns) {\n const projection = types[column];\n console.log(`- Column ${quoteIdentifier(column)}: ${projection}`);\n }\n }\n\n return this;\n }\n\n /**\n * Logs the types of all columns in the table to the console.\n *\n * @example\n * ```ts\n * // Log the data types of all columns in the table\n * await table.logTypes();\n * ```\n * @returns A promise that resolves to the SimpleTable instance after logging the column types.\n * @category Logging\n */\n async logTypes(): Promise<this> {\n console.log(`\\nTable ${this.name} types:`);\n console.log(await this.getTypes());\n return this;\n }\n\n /**\n * Logs unique values for a specified column to the console. By default, a maximum of 100 values are logged (depending on your runtime).\n * You can optionally stringify the values to see them all.\n *\n * @example\n * ```ts\n * // Logs unique values for the column \"name\"\n * await table.logUniques(\"name\");\n * ```\n *\n * @example\n * ```ts\n * // Logs unique values for the column \"name\" and stringifies them\n * await table.logUniques(\"name\", { stringify: true });\n * ```\n * @param column - The name of the column from which to retrieve and log unique values.\n * @param options - An optional object with configuration options:\n * @param options.stringify - If `true`, converts the unique values to a JSON string before logging. Defaults to `false`.\n * @returns A promise that resolves to the SimpleTable instance after logging the unique values.\n * @category Logging\n */\n async logUniques(column: string, options: { stringify?: boolean } = {}): Promise<this> {\n const values = await this.getUniques(column);\n console.log(`\\nTable ${this.name} — unique values in ${column}:`);\n if (options.stringify) {\n console.log(JSON.stringify(values, null, 2));\n } else {\n console.log(values);\n }\n return this;\n }\n\n /**\n * Logs the columns in the table to the console. You can optionally include their data types.\n *\n * @example\n * ```ts\n * // Log only the column names\n * await table.logColumns();\n * ```\n *\n * @example\n * ```ts\n * // Log column names along with their types\n * await table.logColumns({ types: true });\n * ```\n * @param options - An optional object with configuration options:\n * @param options.types - If `true`, logs the column names along with their data types. Defaults to `false`.\n * @returns A promise that resolves to the SimpleTable instance after logging the columns.\n * @category Logging\n */\n async logColumns(options: { types?: boolean } = {}): Promise<this> {\n console.log(`\\nTable ${this.name} columns:`);\n if (options.types) {\n console.log(await this.getTypes());\n } else {\n console.log(await this.getColumns());\n }\n\n return this;\n }\n\n /**\n * Logs the total number of rows in the table to the console.\n *\n * @example\n * ```ts\n * // Log the total number of rows in the table\n * await table.logRowCount();\n * ```\n * @returns A promise that resolves to the SimpleTable instance after logging the row count.\n * @category Logging\n */\n async logRowCount(): Promise<this> {\n const rowCount = await this.getRowCount();\n console.log(`\\nTable ${this.name}: ${formatNumber(rowCount)} rows.`);\n return this;\n }\n\n /**\n * Logs the bottom `n` rows of the table to the console. By default, the last row will be returned first. To preserve the original order, use the `originalOrder` option.\n *\n * Uses the same precision-preserving temporal display, nested stringification,\n * numeric coloring, and `charsToLog` truncation as `log()`. Unsafe top-level\n * large integers throw, just as with `getData()`.\n *\n * @example\n * ```ts\n * // Log bottom rows with default count (uses table's rowsToLog option)\n * await table.logBottom();\n * ```\n *\n * @example\n * ```ts\n * // Log the last 10 rows (displayed with last row first)\n * await table.logBottom(10);\n * ```\n *\n * @example\n * ```ts\n * // Log the last 5 rows in original order (top to bottom)\n * await table.logBottom(5, { originalOrder: true });\n * ```\n * @param count - The number of rows to log from the bottom of the table. Defaults to the table's `rowsToLog` option if not specified.\n * @param options - An optional object with logging preferences.\n * @param options.originalOrder - If true, the rows are displayed in their original order (top to bottom). Defaults to false.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category Logging\n */\n async logBottom(count?: number, options: { originalOrder?: boolean } = {}): Promise<this> {\n await logBottom(this, count, options);\n return this;\n }\n\n /**\n * Logs the extent (minimum and maximum values) of a numeric column to the console.\n *\n * @example\n * ```ts\n * // Log the extent of the 'price' column\n * await table.logExtent(\"price\");\n * ```\n * @param column - The name of the numeric column for which to log the extent.\n * @returns A promise that resolves to the table, so methods can be chained.\n * @category Logging\n */\n async logExtent(column: string): Promise<this> {\n const extent = await this.getExtent(column);\n console.log(`\\nTable ${this.name} (${column} extent):`);\n console.log(extent);\n return this;\n }\n}\n","import { readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\n\nexport default function cleanCache(sdb: SimpleDB, log: (message: string) => void = console.log) {\n if (sdb.cacheSourcesUsed.length > 0) {\n const cacheSources: unknown = JSON.parse(readFileSync(\".sda-cache/sources.json\", \"utf8\"));\n if (cacheSources === null || typeof cacheSources !== \"object\" || Array.isArray(cacheSources)) {\n throw new Error(\"Invalid SDA table cache metadata.\");\n }\n for (const [cacheId, source] of Object.entries(cacheSources)) {\n if (!isFileSource(source)) throw new Error(\"Invalid SDA cache file metadata.\");\n if (!sdb.cacheSourcesUsed.includes(cacheId)) {\n if (source.file !== null) {\n if (sdb.cacheVerbose) {\n log(`Removing unused file from cache: ${source.file}`);\n }\n unlinkSync(source.file);\n }\n Reflect.deleteProperty(cacheSources, cacheId);\n }\n }\n writeFileSync(\".sda-cache/sources.json\", JSON.stringify(cacheSources));\n }\n}\n\nfunction isFileSource(value: unknown): value is { file: string | null } {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"file\" in value &&\n (value.file === null || typeof value.file === \"string\")\n );\n}\n","import mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\n\nexport default async function getTableNames(simpleDB: SimpleDB) {\n const queryResult = await queryDB(\n simpleDB,\n `SHOW TABLES`,\n mergeOptions(simpleDB, {\n returnData: true,\n table: null,\n method: \"getTables\",\n parameters: {},\n }),\n );\n\n if (!queryResult) {\n throw new Error(\"The query did not return a result.\");\n }\n\n const tables = queryResult.map((d) => d.name) as string[];\n\n return tables.sort();\n}\n","import { extname } from \"node:path\";\n\nexport default function getDbFileType(file: string): \"duckdb\" | \"sqlite\" {\n const extension = extname(file).slice(1).toLowerCase();\n if (extension === \"db\" || extension === \"duckdb\") return \"duckdb\";\n if (extension === \"sqlite\") return \"sqlite\";\n throw new Error(\n `The extension ${extension} is not supported. Please use .db, .duckdb or .sqlite instead.`,\n );\n}\n","import queryDbFile from \"./queryDbFile.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\n\nexport default async function getCurrentDatabase(sdb: SimpleDB): Promise<string> {\n const rows = await queryDbFile(sdb, \"SELECT current_database() AS name;\", {\n returnData: true,\n });\n return rows![0].name as string;\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\n\nexport default function getDbIndexes(sdb: SimpleDB): Record<string, IndexDefinition[]> {\n return Object.fromEntries(\n sdb\n .getTables()\n .filter((table) => table.indexes.length > 0)\n .map((table) => [table.name, structuredClone(table.indexes)]),\n );\n}\n","import queryDbFile from \"./queryDbFile.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport quoteIdentifier from \"./quoteIdentifier.ts\";\nimport parseValue from \"./parseValue.ts\";\n\nexport default async function writeDbMetadata(\n sdb: SimpleDB,\n database: string,\n indexes: Record<string, IndexDefinition[]>,\n): Promise<void> {\n const catalog = quoteIdentifier(database);\n await queryDbFile(\n sdb,\n `CREATE SCHEMA IF NOT EXISTS ${catalog}.__sda;\n CREATE OR REPLACE TABLE ${catalog}.__sda.metadata AS\n SELECT 1 AS version, ${parseValue(JSON.stringify(indexes))}::VARCHAR AS indexes;`,\n );\n}\n","import queryDbFile from \"./queryDbFile.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport parseValue from \"./parseValue.ts\";\n\nexport default async function prepareDbExtensions(\n sdb: SimpleDB,\n database: string,\n indexes: Record<string, IndexDefinition[]>,\n): Promise<void> {\n const definitions = Object.values(indexes).flat();\n const physicalIndexes = await queryDbFile(\n sdb,\n `SELECT sql FROM duckdb_indexes() WHERE database_name = ${parseValue(database)};`,\n { returnData: true },\n );\n if (\n definitions.some((index) => index.kind === \"vss\") ||\n physicalIndexes!.some((index) => /\\bUSING\\s+HNSW\\b/i.test(String(index.sql)))\n ) {\n await queryDbFile(\n sdb,\n \"INSTALL vss; LOAD vss; SET hnsw_enable_experimental_persistence = true;\",\n );\n }\n const ftsSchemas = await queryDbFile(\n sdb,\n `SELECT schema_name FROM duckdb_schemas() WHERE database_name = ${parseValue(\n database,\n )} AND starts_with(schema_name, 'fts_');`,\n { returnData: true },\n );\n if (definitions.some((index) => index.kind === \"fts\") || ftsSchemas!.length > 0) {\n await queryDbFile(sdb, \"INSTALL fts; LOAD fts;\");\n }\n if (!sdb.spatialLoaded) {\n const geometryColumns = await queryDbFile(\n sdb,\n `SELECT column_name FROM duckdb_columns()\n WHERE database_name = ${parseValue(database)} AND data_type ILIKE '%GEOMETRY%' LIMIT 1;`,\n { returnData: true },\n );\n if (geometryColumns!.length > 0) {\n await queryDbFile(sdb, \"INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\");\n sdb.spatialLoaded = true;\n }\n }\n}\n","import type SimpleDB from \"../class/SimpleDB.ts\";\nimport type { IndexDefinition } from \"./indexDefinitions.ts\";\nimport { markTableChanged } from \"./tableGeneration.ts\";\nimport { registerTable } from \"./tableRegistry.ts\";\n\nexport default async function setDbProps(\n simpleDB: SimpleDB,\n indexes: { [table: string]: IndexDefinition[] },\n) {\n for (const table of await simpleDB.getTableNames()) {\n if (!simpleDB.getTables().some((registered) => registered.name === table)) {\n const instance = new simpleDB.tableClass(table, simpleDB, {\n rowsToLog: simpleDB.rowsToLog,\n charsToLog: simpleDB.charsToLog,\n typesToLog: simpleDB.typesToLog,\n });\n registerTable(simpleDB, instance);\n markTableChanged(instance);\n }\n }\n\n for (const table of simpleDB.getTables()) {\n if (indexes[table.name]) {\n table.indexes = structuredClone(indexes[table.name]);\n }\n }\n\n while (simpleDB.getTables().some((table) => table.name === `table${simpleDB.tableIncrement}`)) {\n simpleDB.tableIncrement++;\n }\n}\n","import { assertCacheTableMutation } from \"../helpers/cacheTableDependencies.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport SimpleTable from \"../class/SimpleTable.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport { retainRegisteredTables } from \"../helpers/tableRegistry.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\n\nexport default async function removeTables(\n simpleDB: SimpleDB,\n tables: SimpleTable | string | (SimpleTable | string)[],\n) {\n const tablesToBeRemoved =\n tables === \"all\" ? [...simpleDB.getTables()] : Array.isArray(tables) ? tables : [tables];\n assertSameDatabase(\n simpleDB,\n tablesToBeRemoved.filter((table): table is SimpleTable => table instanceof SimpleTable),\n \"removeTables()\",\n );\n\n const names = tablesToBeRemoved.map((table) =>\n (table instanceof SimpleTable ? table.name : table).toLowerCase(),\n );\n for (const table of simpleDB.getTables()) {\n if (names.includes(table.name.toLowerCase())) {\n assertCacheTableMutation(table);\n }\n }\n\n await queryDB(\n simpleDB,\n tablesToBeRemoved\n .map((d) => `DROP TABLE ${quoteIdentifier(d instanceof SimpleTable ? d.name : d)};`)\n .join(\"\\n\"),\n mergeOptions(simpleDB, {\n table: null,\n method: \"removeTable()\",\n parameters: {},\n }),\n );\n\n const tablesNamesToBeRemoved = tablesToBeRemoved.map((t) =>\n t instanceof SimpleTable ? t.name : t,\n );\n retainRegisteredTables(simpleDB, (table) => !tablesNamesToBeRemoved.includes(table.name));\n}\n","import quoteIdentifier from \"./quoteIdentifier.ts\";\n\n/**\n * Formats a missing-table error with the requested and available table names.\n *\n * @example\n * ```ts\n * const message = formatMissingTables(\n * \"getTable()\",\n * [\"missing\"],\n * [\"votes\", \"districts\"],\n * );\n * ```\n *\n * @param method - The SDA method looking up the tables.\n *\n * @param missingTables - The requested table names that were not found.\n *\n * @param availableTables - The table names currently available.\n *\n * @returns An actionable missing-table error message.\n */\nexport default function formatMissingTables(\n method: string,\n missingTables: string[],\n availableTables: string[],\n): string {\n const missing = [...missingTables].sort();\n const available = [...availableTables].sort();\n const missingDescription =\n missing.length === 1\n ? `table ${quoteIdentifier(missing[0])}`\n : `tables ${missing.map(quoteIdentifier).join(\", \")}`;\n const availableDescription =\n available.length === 0\n ? \"No tables are currently available.\"\n : `Available tables: ${available.map(quoteIdentifier).join(\", \")}.`;\n return `${method} could not find ${missingDescription}. ${availableDescription}`;\n}\n","import { assertCacheTableMutation } from \"../helpers/cacheTableDependencies.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport SimpleTable from \"../class/SimpleTable.ts\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport { retainRegisteredTables } from \"../helpers/tableRegistry.ts\";\nimport assertSameDatabase from \"../helpers/assertSameDatabase.ts\";\nimport formatMissingTables from \"../helpers/formatMissingTables.ts\";\n\nexport default async function selectTables(\n simpleDB: SimpleDB,\n tables: SimpleTable | string | (SimpleTable | string)[],\n) {\n const selected = Array.isArray(tables) ? tables : [tables];\n assertSameDatabase(\n simpleDB,\n selected.filter((table): table is SimpleTable => table instanceof SimpleTable),\n \"selectTables()\",\n );\n const tablesToBeSelected = selected.map((t) => (t instanceof SimpleTable ? t.name : t));\n\n for (const table of simpleDB.getTables()) {\n if (!tablesToBeSelected.includes(table.name)) {\n assertCacheTableMutation(table);\n }\n }\n\n const existingTables = await simpleDB.getTableNames();\n const missingTables = tablesToBeSelected.filter((table) => !existingTables.includes(table));\n if (missingTables.length > 0) {\n throw new Error(formatMissingTables(\"selectTables()\", missingTables, existingTables));\n }\n\n const tablesToBeRemoved = simpleDB\n .getTables()\n .filter((t) => !tablesToBeSelected.includes(t.name));\n\n await queryDB(\n simpleDB,\n tablesToBeRemoved\n .map((d) => `DROP TABLE ${quoteIdentifier(d instanceof SimpleTable ? d.name : d)};`)\n .join(\"\\n\"),\n mergeOptions(simpleDB, {\n table: null,\n method: \"removeTable()\",\n parameters: {},\n }),\n );\n\n const tablesNamesToBeRemoved = tablesToBeRemoved.map((t) =>\n t instanceof SimpleTable ? t.name : t,\n );\n retainRegisteredTables(simpleDB, (table) => !tablesNamesToBeRemoved.includes(table.name));\n}\n","import queryDbFile from \"../helpers/queryDbFile.ts\";\nimport { existsSync } from \"node:fs\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport cleanPath from \"../helpers/cleanPath.ts\";\nimport getDbFileType from \"../helpers/getDbFileType.ts\";\nimport getCurrentDatabase from \"../helpers/getCurrentDatabase.ts\";\nimport getDbIndexes from \"../helpers/getDbIndexes.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport prepareDbExtensions from \"../helpers/prepareDbExtensions.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport readDbMetadata from \"../helpers/readDbMetadata.ts\";\nimport setDbProps from \"../helpers/setDbProps.ts\";\nimport writeDbMetadata from \"../helpers/writeDbMetadata.ts\";\n\nexport default async function loadDB(sdb: SimpleDB, file: string) {\n const type = getDbFileType(file);\n if (!existsSync(file)) throw new Error(`The file ${file} does not exist.`);\n if (sdb.readOnly) {\n throw new Error(\"loadDB() cannot import into a read-only database.\");\n }\n\n const destination = await getCurrentDatabase(sdb);\n const target = quoteIdentifier(destination);\n const name = `__sda_import_${crypto.randomUUID().replaceAll(\"-\", \"\")}`;\n const source = quoteIdentifier(name);\n if (type === \"sqlite\") await queryDbFile(sdb, \"INSTALL sqlite; LOAD sqlite;\");\n await queryDbFile(sdb, `ATTACH '${cleanPath(file)}' AS ${source} (TYPE ${type}, READ_ONLY);`);\n\n try {\n const indexes = type === \"duckdb\" ? await readDbMetadata(sdb, name) : {};\n await readDbMetadata(sdb, destination);\n await prepareDbExtensions(sdb, name, indexes);\n const conflicts = await queryDbFile(\n sdb,\n `SELECT incoming.table_schema, incoming.table_name\n FROM information_schema.tables incoming\n JOIN information_schema.tables existing\n ON lower(incoming.table_schema) = lower(existing.table_schema)\n AND lower(incoming.table_name) = lower(existing.table_name)\n WHERE incoming.table_catalog = ${parseValue(name)}\n AND existing.table_catalog = ${parseValue(destination)}\n AND incoming.table_schema <> '__sda';`,\n { returnData: true },\n );\n // Also protect registered table handles that have no physical table yet.\n const incoming = await queryDbFile(\n sdb,\n `SELECT table_name FROM information_schema.tables\n WHERE table_catalog = ${parseValue(name)} AND table_schema = 'main';`,\n { returnData: true },\n );\n const registered = new Set(sdb.getTables().map((table) => table.name.toLowerCase()));\n const names = new Set([\n ...conflicts!.map((row) => `${String(row.table_schema)}.${String(row.table_name)}`),\n ...incoming!\n .filter((row) => registered.has(String(row.table_name).toLowerCase()))\n .map((row) => `main.${String(row.table_name)}`),\n ]);\n if (names.size > 0) {\n throw new Error(`loadDB() cannot import existing tables: ${[...names].join(\", \")}.`);\n }\n const mergedIndexes = { ...getDbIndexes(sdb), ...indexes };\n await queryDbFile(\n sdb,\n `DROP TABLE IF EXISTS ${target}.__sda.metadata;\n COPY FROM DATABASE ${source} TO ${target};`,\n );\n await writeDbMetadata(sdb, destination, mergedIndexes);\n await setDbProps(sdb, indexes);\n } finally {\n await queryDbFile(sdb, `DETACH ${source};`);\n }\n}\n","import queryDbFile from \"../helpers/queryDbFile.ts\";\nimport {\n existsSync,\n linkSync,\n lstatSync,\n mkdtempSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport type SimpleDB from \"../class/SimpleDB.ts\";\nimport cleanPath from \"../helpers/cleanPath.ts\";\nimport createDirectory from \"../helpers/createDirectory.ts\";\nimport getCurrentDatabase from \"../helpers/getCurrentDatabase.ts\";\nimport getDbFileType from \"../helpers/getDbFileType.ts\";\nimport getDbIndexes from \"../helpers/getDbIndexes.ts\";\nimport parseValue from \"../helpers/parseValue.ts\";\nimport prepareDbExtensions from \"../helpers/prepareDbExtensions.ts\";\nimport quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport readDbMetadata from \"../helpers/readDbMetadata.ts\";\nimport writeDbMetadata from \"../helpers/writeDbMetadata.ts\";\n\nexport default async function writeDB(\n sdb: SimpleDB,\n file: string,\n options: { overwrite?: boolean; metadata?: boolean } = {},\n) {\n const type = getDbFileType(file);\n const output = resolve(file);\n assertDestination(output, options.overwrite ?? false);\n const database = await getCurrentDatabase(sdb);\n const source = quoteIdentifier(database);\n const databases = await queryDbFile(\n sdb,\n \"SELECT path FROM duckdb_databases() WHERE path IS NOT NULL;\",\n { returnData: true },\n );\n for (const { path } of databases!) {\n if (typeof path !== \"string\" || !existsSync(path)) continue;\n const original = statSync(path);\n const target = existsSync(output) ? statSync(output) : undefined;\n if (\n resolve(path) === output ||\n (target?.dev === original.dev && target?.ino === original.ino)\n ) {\n throw new Error(\n \"writeDB() cannot replace an open database file. Export to a different path.\",\n );\n }\n }\n\n const indexes = getDbIndexes(sdb);\n await readDbMetadata(sdb, database);\n await prepareDbExtensions(sdb, database, indexes);\n if (type === \"sqlite\") await queryDbFile(sdb, \"INSTALL sqlite; LOAD sqlite;\");\n createDirectory(output);\n const directory = mkdtempSync(join(dirname(output), \".sda-export-\"));\n const temporary = join(directory, \"snapshot.db\");\n const name = `__sda_export_${crypto.randomUUID().replaceAll(\"-\", \"\")}`;\n const target = quoteIdentifier(name);\n let attached = false;\n try {\n await queryDbFile(\n sdb,\n `ATTACH '${cleanPath(temporary)}' AS ${target} (TYPE ${type}, READ_WRITE);`,\n );\n attached = true;\n if (type === \"duckdb\") {\n await queryDbFile(sdb, `COPY FROM DATABASE ${source} TO ${target};`);\n await writeDbMetadata(sdb, name, options.metadata === false ? {} : indexes);\n await queryDbFile(sdb, `CHECKPOINT ${target};`);\n } else {\n // SQLite is an interchange format: materialize main-schema relations,\n // without DuckDB extension schemas, indexes, or SDA metadata.\n const tables = await queryDbFile(\n sdb,\n `SELECT table_name FROM information_schema.tables\n WHERE table_catalog = ${parseValue(database)} AND table_schema = 'main';`,\n { returnData: true },\n );\n for (const { table_name } of tables!) {\n const table = quoteIdentifier(String(table_name));\n await queryDbFile(\n sdb,\n `CREATE TABLE ${target}.${table} AS SELECT * FROM ${source}.main.${table};`,\n );\n }\n }\n await queryDbFile(sdb, `DETACH ${target};`);\n attached = false;\n assertDestination(output, options.overwrite ?? false);\n if (options.overwrite) {\n // Do not fall back to unlinking the original if atomic replacement fails.\n renameSync(temporary, output);\n } else {\n // An exclusive link also protects a destination created during the export.\n linkSync(temporary, output);\n }\n } finally {\n try {\n if (attached) await queryDbFile(sdb, `DETACH ${target};`);\n } finally {\n rmSync(directory, { recursive: true, force: true });\n }\n }\n}\n\nfunction assertDestination(file: string, overwrite: boolean): void {\n let existing: ReturnType<typeof lstatSync>;\n try {\n existing = lstatSync(file);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n if (!existing.isFile()) {\n throw new Error(\n `The output path ${file} must be a regular file, not a directory or symbolic link.`,\n );\n }\n if (!overwrite) {\n throw new Error(`The file ${file} already exists. Set overwrite to true to replace it.`);\n }\n}\n","import quoteIdentifier from \"../helpers/quoteIdentifier.ts\";\nimport { DuckDBInstance } from \"@duckdb/node-api\";\nimport runQuery from \"../helpers/runQuery.ts\";\nimport SimpleTable from \"./SimpleTable.ts\";\nimport cleanCache from \"../helpers/cleanCache.ts\";\nimport prettyDuration from \"../helpers/prettyDuration.ts\";\nimport Simple from \"./Simple.ts\";\nimport queryDB from \"../helpers/queryDB.ts\";\nimport mergeOptions from \"../helpers/mergeOptions.ts\";\nimport getTableNames from \"../methods/getTableNames.ts\";\nimport { existsSync, rmSync } from \"node:fs\";\nimport createDirectory from \"../helpers/createDirectory.ts\";\nimport getDbFileType from \"../helpers/getDbFileType.ts\";\nimport getCurrentDatabase from \"../helpers/getCurrentDatabase.ts\";\nimport getDbIndexes from \"../helpers/getDbIndexes.ts\";\nimport readDbMetadata from \"../helpers/readDbMetadata.ts\";\nimport writeDbMetadata from \"../helpers/writeDbMetadata.ts\";\nimport prepareDbExtensions from \"../helpers/prepareDbExtensions.ts\";\nimport setDbProps from \"../helpers/setDbProps.ts\";\nimport queryDbFile from \"../helpers/queryDbFile.ts\";\nimport removeTables from \"../methods/removeTables.ts\";\nimport selectTables from \"../methods/selectTables.ts\";\nimport loadDB from \"../methods/loadDB.ts\";\nimport writeDB from \"../methods/writeDB.ts\";\nimport flushAllTables, { runExemptFromFlush } from \"../helpers/flushAllTables.ts\";\nimport { discardAllPending } from \"../helpers/queueOp.ts\";\nimport {\n initializeTableRegistry,\n listRegisteredTables,\n registerTable,\n} from \"../helpers/tableRegistry.ts\";\nimport formatMissingTables from \"../helpers/formatMissingTables.ts\";\n\n/**\n * Manages a DuckDB database instance, providing a simplified interface for database operations.\n *\n * @example\n * ```ts\n * // Create an in-memory database instance\n * const sdb = new SimpleDB();\n * // Create a table, load a CSV file, and log its first few rows\n * const employees = await sdb\n * .newTable(\"employees\")\n * .loadData(\"./employees.csv\")\n * .log();\n * // Close the database connection and clean up resources\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Open or create a persistent DuckDB database. Changes persist in this file.\n * const sdb = new SimpleDB({ file: \"./my_database.db\" });\n * // Perform database operations...\n * // Execute pending work, save SDA metadata, and close the database connection\n * await sdb.close();\n * ```\n *\n * @example\n * ```ts\n * // Create a database instance with custom options\n * const sdb = new SimpleDB({\n * logSQL: true, // Log SQL immediately before it runs\n * rowsToLog: 20 // Set the number of rows to log by default\n * });\n * ```\n */\n\nexport default class SimpleDB<Table extends SimpleTable = SimpleTable> extends Simple {\n /**\n * The operator syntax used by expressions and custom queries in this database.\n * `\"js\"` translates JavaScript-style operators (`&&`, `||`, `==`, `===`,\n * `!==`) and null comparisons within SQL expressions. It does not evaluate\n * arbitrary JavaScript. `||` remains concatenation when string literals, list\n * literals, explicit text casts, or `concat()` results make that intent clear.\n * Otherwise `||` becomes OR; column types are not inferred. Use `concat()`\n * when concatenation would otherwise be ambiguous, such as `first || last`.\n * `\"sql\"` passes SQL through unchanged, including `||` and null comparisons.\n * Choose the syntax when constructing the database; it applies to all tables.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"js\" }); // The default mode\n * // || becomes SQL OR: keep rows where at least one condition is true.\n * await sdb.newTable().loadArray([{ active: true, admin: false }])\n * .filter(\"active || admin\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"js\" });\n * // && becomes SQL AND: both conditions must be true.\n * // === becomes SQL =: compare the age with 18.\n * await sdb.newTable().loadArray([{ active: true, age: 18 }])\n * .filter(\"active && age === 18\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"js\" });\n * // SQL AND and OR also work in JS mode; they pass through unchanged.\n * // Keep active adults, or anyone who is an admin.\n * await sdb.newTable().loadArray([{ active: true, age: 18, admin: false }])\n * .filter(\"(active AND age >= 18) OR admin\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"js\" });\n * // Bare column names do not establish concatenation. Use concat() explicitly.\n * await sdb.newTable().loadArray([{ first: \"Jane\", last: \"Doe\" }])\n * .addColumn(\"name\", \"string\", \"concat(first, ' ', last)\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB(); // JS mode is the default\n * // The string literal ' ' makes concatenation clear, so both || stay unchanged.\n * await sdb.newTable().loadArray([{ first: \"Jane\", last: \"Doe\" }])\n * .addColumn(\"name\", \"string\", \"first || ' ' || last\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"sql\" });\n * // SQL mode preserves || as concatenation: the name becomes \"Jane Doe\".\n * await sdb.newTable().loadArray([{ first: \"Jane\", last: \"Doe\" }])\n * .addColumn(\"name\", \"string\", \"first || ' ' || last\").log();\n * ```\n * @example\n * ```ts\n * const sdb = new SimpleDB({ expressionSyntax: \"sql\" });\n * // Use SQL AND and OR for logical conditions; && and || are not translated.\n * // Both active and adult must be true, unless admin is true.\n * await sdb.newTable().loadArray([{ active: true, age: 18, admin: false }])\n * .filter(\"(active AND age >= 18) OR admin\").log();\n * ```\n *\n * @defaultValue `\"js\"`\n * @category Properties\n */\n readonly expressionSyntax: \"js\" | \"sql\";\n /**\n * Whether to log each SQL statement immediately before execution.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({ logSQL: true });\n * ```\n *\n * @defaultValue `false`\n * @category Properties\n */\n logSQL: boolean;\n /**\n * Whether to log DuckDB query plans before supported statements execute.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({ explainSQL: true });\n * ```\n *\n * @defaultValue `false`\n * @category Properties\n */\n explainSQL: boolean;\n /**\n * An array of paths to the data sources used in the cache.\n *\n * @defaultValue `[]`\n * @category Properties\n */\n cacheSourcesUsed: string[];\n /**\n * A timestamp marking the start of a duration measurement.\n *\n * @defaultValue `undefined`\n * @category Properties\n */\n durationStart: number | undefined;\n /**\n * A counter for incrementing default table names.\n *\n * @defaultValue `1`\n * @category Properties\n */\n tableIncrement: number;\n /**\n * A flag indicating whether to log the total execution duration.\n *\n * @defaultValue `false`\n * @category Properties\n */\n logDuration: boolean;\n /**\n * Whether to log cache hits and misses, code and input changes, TTL status,\n * and cache read/write timing.\n *\n * @defaultValue `false`\n * @category Properties\n */\n cacheVerbose: boolean;\n /**\n * The total time saved by using the cache, in milliseconds.\n *\n * @defaultValue `0`\n * @category Properties\n */\n cacheTimeSaved: number;\n /**\n * The total time spent writing to the cache, in milliseconds.\n *\n * @defaultValue `0`\n * @category Properties\n */\n cacheTimeWriting: number;\n /**\n * A flag indicating whether to display a progress bar for long-running operations.\n *\n * @defaultValue `false`\n * @category Properties\n */\n progressBar: boolean;\n /**\n * The in-flight flush of the pending chains, if one is running. Concurrent\n * observers await it instead of reading mid-flush state. This is for\n * internal use only.\n *\n * @defaultValue `null`\n * @internal\n */\n flushPromise: Promise<void> | null;\n #closePromise: Promise<SimpleDB> | null = null;\n #startPromise: Promise<SimpleDB> | null = null;\n #initialized = false;\n /**\n * The database lifecycle state. This is for internal use only.\n *\n * @internal\n */\n lifecycleState: \"open\" | \"closing\" | \"closed\";\n /**\n * The number of queued operations across all tables, so query execution\n * points skip the flush entirely when nothing is pending. This is for\n * internal use only.\n *\n * @defaultValue `0`\n * @internal\n */\n pendingCount: number;\n /**\n * A counter stamping queued operations with their position in program\n * order across all tables, so flushes replay them in the order they were\n * queued. This is for internal use only.\n *\n * @defaultValue `0`\n * @internal\n */\n opSequence: number;\n /**\n * A flag indicating that the spatial extension has been loaded on this\n * connection, so it's only loaded once. This is for internal use only.\n *\n * @defaultValue `false`\n * @internal\n */\n spatialLoaded: boolean;\n /**\n * A flag indicating whether to use DuckDB's external file cache.\n *\n * @defaultValue `false`\n * @category Properties\n */\n duckDbCache: boolean | null;\n /**\n * The maximum amount of memory DuckDB is allowed to use (e.g., `'4GB'`). Defaults to 80% of system RAM.\n *\n * @defaultValue `undefined`\n * @category Properties\n */\n memoryLimit: string | undefined;\n /**\n * The path to the directory used for temporary files when data exceeds the memory limit (e.g., `'/tmp/duckdb_swap'`). Defaults to `.tmp` for in-memory databases or `<file>.tmp` for file-based databases. Temporary directories are automatically removed when calling `close()`.\n *\n * @defaultValue `undefined`\n * @category Properties\n */\n tempDir: string | undefined;\n /**\n * The path to the persistent DuckDB database, opened or created on first use.\n * If not provided, an in-memory database is used. Imports and exports do not change this path.\n *\n * @defaultValue `:memory:`\n * @category Properties\n */\n file: string;\n /**\n * Whether to replace an existing DuckDB file on first use instead of opening it.\n *\n * @defaultValue `false`\n * @category Properties\n */\n overwrite: boolean;\n /**\n * Whether the persistent DuckDB file is opened read-only. Requires an existing\n * file and cannot be combined with `overwrite`. DuckDB rejects writes to it.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({ file: \"./archive.duckdb\", readOnly: true });\n * const table = await sdb.getTable(\"employees\");\n * await table.log();\n * await sdb.close();\n * ```\n *\n * @defaultValue `false`\n * @category Properties\n */\n readOnly: boolean;\n /**\n * The class used to create table instances. Defaults to `SimpleTable`.\n * Override this property when subclassing to ensure all table-creating\n * methods (e.g., `newTable()`, `clone()`) return instances of your\n * custom table class.\n *\n * @example\n * ```ts\n * class MyTable extends SimpleTable {\n * customMethod() { return \"hello\"; }\n * }\n *\n * class MyDB extends SimpleDB {\n * constructor(options?: SimpleDBOptions) {\n * super(options);\n * this.tableClass = MyTable;\n * }\n * }\n *\n * const db = new MyDB();\n * const table = db.newTable(\"myTable\");\n * console.log(table.customMethod()); // \"hello\"\n * ```\n *\n * @defaultValue `SimpleTable`\n * @category Properties\n */\n tableClass: new (\n name: string,\n sdb: SimpleDB,\n options?: {\n rowsToLog?: number;\n charsToLog?: number;\n typesToLog?: boolean;\n },\n ) => Table = SimpleTable as new (\n name: string,\n sdb: SimpleDB,\n options?: {\n rowsToLog?: number;\n charsToLog?: number;\n typesToLog?: boolean;\n },\n ) => Table;\n\n /**\n * Creates a new SimpleDB instance.\n *\n * DuckDB sessions use UTC so temporal parsing, extraction, and returned\n * `TIMESTAMP WITH TIME ZONE` strings are consistent across environments.\n *\n * Existing tables and SDA index metadata are restored on first use. The\n * `__sda` schema is reserved for versioned SDA metadata. SQLite files can be\n * imported with `loadDB()` but cannot be used as the persistent database.\n *\n * @example\n * ```ts\n * const sdb = new SimpleDB({\n * logSQL: true,\n * explainSQL: true,\n * });\n * ```\n *\n * @param options - Configuration options for the SimpleDB instance.\n * @param options.file - A `.db` or `.duckdb` file to open or create. Defaults to an in-memory database.\n * @param options.overwrite - If true, replaces an existing file on first use. Defaults to false, which opens the existing file.\n * @param options.readOnly - Opens an existing DuckDB file read-only. Defaults to false. Requires a file and cannot be combined with overwrite.\n * @param options.logDuration - A flag indicating whether to log the total execution duration.\n * @param options.rowsToLog - The number of rows to display when logging a table.\n * @param options.charsToLog - The maximum characters to display for text and stringified nested cells, including truncation markers (default: 75). Independent of column width. Use Infinity for unlimited text.\n * @param options.typesToLog - A flag indicating whether to include data types when logging a table.\n * @param options.cacheVerbose - Whether to log cache hits and misses, code and input changes, TTL status, and cache read/write timing.\n * @param options.expressionSyntax - Operator syntax for expressions and custom queries: `\"js\"` (default) translates JavaScript-style operators in SQL expressions; `\"sql\"` preserves SQL unchanged.\n * @param options.logSQL - A flag indicating whether to log SQL immediately before execution.\n * @param options.explainSQL - A flag indicating whether to log DuckDB query plans for supported statements.\n * @param options.duckDbCache - A flag indicating whether to use DuckDB's external file cache.\n * @param options.progressBar - A flag indicating whether to display a progress bar for long-running operations.\n * @param options.memoryLimit - The maximum amount of memory DuckDB is allowed to use (e.g., `'4GB'`). Defaults to 80% of system RAM.\n * @param options.tempDir - The path to the directory used for temporary files when data exceeds the memory limit (e.g., `'/tmp/duckdb_swap'`). Defaults to `.tmp` for in-memory databases or `<file>.tmp` for file-based databases. Automatically removed when calling `close()`.\n * @category Constructor\n */\n constructor(\n options: {\n file?: string;\n overwrite?: boolean;\n readOnly?: boolean;\n logDuration?: boolean;\n rowsToLog?: number;\n charsToLog?: number;\n typesToLog?: boolean;\n cacheVerbose?: boolean;\n expressionSyntax?: \"js\" | \"sql\";\n logSQL?: boolean;\n explainSQL?: boolean;\n duckDbCache?: boolean | null;\n progressBar?: boolean;\n memoryLimit?: string;\n tempDir?: string;\n } = {},\n ) {\n super(options);\n if (\n options.expressionSyntax !== undefined &&\n ![\"js\", \"sql\"].includes(options.expressionSyntax)\n ) {\n throw new Error('expressionSyntax must be \"js\" or \"sql\".');\n }\n this.expressionSyntax = options.expressionSyntax ?? \"js\";\n this.file = options.file ?? \":memory:\";\n this.logSQL = options.logSQL ?? false;\n this.explainSQL = options.explainSQL ?? false;\n this.overwrite = options.overwrite ?? false;\n this.readOnly = options.readOnly ?? false;\n this.logDuration = options.logDuration ?? false;\n this.tableIncrement = 1;\n initializeTableRegistry(this);\n this.cacheSourcesUsed = [];\n this.cacheVerbose = options.cacheVerbose ?? false;\n this.cacheTimeSaved = 0;\n this.cacheTimeWriting = 0;\n this.progressBar = options.progressBar ?? false;\n this.duckDbCache = options.duckDbCache === undefined ? false : options.duckDbCache;\n this.memoryLimit = options.memoryLimit;\n this.tempDir = options.tempDir;\n this.flushPromise = null;\n this.lifecycleState = \"open\";\n this.pendingCount = 0;\n this.opSequence = 0;\n this.spatialLoaded = false;\n this.runQuery = runQuery;\n if (this.cacheVerbose || this.logDuration) {\n this.durationStart = Date.now();\n }\n }\n\n /**\n * Initializes the DuckDB database instance and connection.\n *\n * @returns A promise that resolves to the SimpleDB instance after initialization.\n * @internal\n * @category Lifecycle\n */\n async start(): Promise<SimpleDB> {\n if (this.lifecycleState === \"closed\") {\n throw new Error(`start() cannot use a SimpleDB that is ${this.lifecycleState}.`);\n }\n if (this.#startPromise === null) {\n // The setup queries below must run before any queued operation, so\n // they must not trigger a flush.\n this.#startPromise = runExemptFromFlush(this, async () => {\n await this.#setup();\n this.#initialized = true;\n return this;\n });\n }\n return await this.#startPromise;\n }\n\n async #setup(): Promise<void> {\n if (this.readOnly && (this.file === \":memory:\" || this.overwrite)) {\n throw new Error(\n \"readOnly requires an existing database file and cannot be combined with overwrite.\",\n );\n }\n if (this.file !== \":memory:\") {\n if (getDbFileType(this.file) !== \"duckdb\") {\n throw new Error(\n \"Persistent databases must use .db or .duckdb. Use loadDB() to import SQLite files.\",\n );\n }\n if (this.readOnly && !existsSync(this.file)) {\n throw new Error(`The file ${this.file} does not exist.`);\n }\n if (existsSync(this.file) && this.overwrite) {\n rmSync(this.file);\n // A WAL belongs to the database being explicitly replaced.\n rmSync(`${this.file}.wal`, { force: true });\n }\n if (!this.readOnly) createDirectory(this.file);\n }\n\n this.db = await DuckDBInstance.create(\n this.file,\n this.readOnly ? { access_mode: \"READ_ONLY\" } : {},\n );\n this.connection = await this.db.connect();\n\n // Keep temporal parsing, extraction, and serialization deterministic\n // across machines. DuckDB otherwise inherits the process timezone.\n await this.customQuery(\"SET TimeZone = 'UTC';\");\n\n // By default, DuckDB does not compress in-memory databases, so we enable it here.\n if (this.file === \":memory:\") {\n await this.customQuery(\n `ATTACH OR REPLACE ':memory:' AS ${quoteIdentifier(\"memory\")} (COMPRESS);`,\n );\n }\n\n if (this.duckDbCache === true) {\n await this.customQuery(\"SET enable_external_file_cache=true;\");\n } else if (this.duckDbCache === false) {\n await this.customQuery(\"SET enable_external_file_cache=false;\");\n }\n\n if (this.progressBar) {\n await this.customQuery(`SET enable_progress_bar = TRUE; SET progress_bar_time = 0;`);\n }\n\n if (this.memoryLimit !== undefined) {\n await this.customQuery(`SET memory_limit = '${this.memoryLimit}';`);\n }\n if (this.tempDir !== undefined) {\n await this.customQuery(`SET temp_directory = '${this.tempDir}';`);\n }\n if (this.file !== \":memory:\") {\n const database = await getCurrentDatabase(this);\n const indexes = await readDbMetadata(this, database);\n await prepareDbExtensions(this, database, indexes);\n const existingNames = new Set((await this.getTableNames()).map((name) => name.toLowerCase()));\n const conflicts = this.getTables().filter((table) =>\n existingNames.has(table.name.toLowerCase()),\n );\n if (conflicts.length > 0) {\n throw new Error(\n `Tables already exist in ${this.file}: ${conflicts\n .map((table) => table.name)\n .join(\", \")}. Use getTable() to access them.`,\n );\n }\n await setDbProps(this, indexes);\n }\n }\n\n /**\n * Creates a new SimpleTable instance within the database.\n * The name must be unique among registered tables, ignoring ASCII letter case.\n *\n * @example\n * ```ts\n * // Create a table with a default name (e.g., \"table1\", \"table2\", etc.)\n * const dataTable = await sdb\n * .newTable()\n * .loadArray([{ value: 1 }])\n * .log();\n * ```\n *\n * @example\n * ```ts\n * // Create a table with a specific name\n * const employees = await sdb\n * .newTable(\"employees\")\n * .loadData(\"employees.csv\")\n * .log();\n * ```\n *\n * @param name - The name of the new table. If not provided, a default name is generated (e.g., \"table1\").\n * @returns A new table instance.\n * @category Table Management\n */\n newTable(name?: string): Table {\n if (this.lifecycleState !== \"open\") {\n throw new Error(`newTable() cannot use a SimpleDB that is ${this.lifecycleState}.`);\n }\n const TableClass = this.tableClass;\n\n // SHOULD MATCH clone\n let table;\n if (typeof name === \"string\") {\n table = new TableClass(name, this, {\n rowsToLog: this.rowsToLog,\n charsToLog: this.charsToLog,\n typesToLog: this.typesToLog,\n });\n table.defaultTableName = false;\n } else {\n while (\n this.getTables().some((table) => table.name.toLowerCase() === `table${this.tableIncrement}`)\n ) {\n this.tableIncrement++;\n }\n table = new TableClass(`table${this.tableIncrement}`, this, {\n rowsToLog: this.rowsToLog,\n charsToLog: this.charsToLog,\n typesToLog: this.typesToLog,\n });\n table.defaultTableName = true;\n this.tableIncrement += 1;\n }\n\n registerTable(this, table);\n\n return table;\n }\n\n /**\n * Retrieves an existing SimpleTable instance from the database.\n *\n * @example\n * ```ts\n * // Retrieve the \"employees\" table\n * const employees = await sdb.getTable(\"employees\");\n * await employees.log();\n * ```\n *\n * @param name - The name of the table to retrieve.\n * @returns A promise that resolves to the SimpleTable instance if found.\n * @category Table Management\n */\n async getTable(name: string): Promise<Table> {\n await this.start();\n const tables = this.getTables();\n const table = tables.find((t) => t.name === name);\n if (table) {\n return table;\n } else {\n throw new Error(\n formatMissingTables(\n \"getTable()\",\n [name],\n tables.map((availableTable) => availableTable.name),\n ),\n );\n }\n }\n\n /**\n * Removes one or more tables from the database.\n *\n * @example\n * ```ts\n * // Remove a single table by name\n * await sdb.removeTables(\"employees\");\n * ```\n *\n * @example\n * ```ts\n * // Remove multiple tables by name\n * await sdb.removeTables([\"customers\", \"products\"]);\n * ```\n *\n * @example\n * ```ts\n * // Remove a single table using a SimpleTable instance\n * const employeesTable = sdb.newTable(\"employees\");\n * // ... load data ...\n * await sdb.removeTables(employeesTable);\n * ```\n *\n * @example\n * ```ts\n * // Remove all tables\n * await sdb.removeTables(\"all\");\n * ```\n *\n * @param tables - A single table or an array of tables to remove, specified by name or as SimpleTable instances. Pass `\"all\"` to remove all tables.\n * @returns A promise that resolves to the database, so methods can be chained.\n * @category Table Management\n */\n async removeTables(tables: Table | string | (Table | string)[]): Promise<this> {\n await removeTables(this, tables);\n return this;\n }\n\n /**\n * Selects one or more tables to keep in the database, removing all others.\n *\n * @example\n * ```ts\n * // Select a single table by name, removing all other tables\n * await sdb.selectTables(\"employees\");\n * ```\n *\n * @example\n * ```ts\n * // Select multiple tables by name, removing all other tables\n * await sdb.selectTables([\"customers\", \"products\"]);\n * ```\n *\n * @example\n * ```ts\n * // Select a single table using a SimpleTable instance\n * const employeesTable = sdb.newTable(\"employees\");\n * // ... load data ...\n * await sdb.selectTables(employeesTable);\n * ```\n *\n * @param tables - A single table or an array of tables to select, specified by name or as SimpleTable instances.\n * @returns A promise that resolves to the database, so methods can be chained.\n * @category Table Management\n */\n async selectTables(tables: Table | string | (Table | string)[]): Promise<this> {\n await selectTables(this, tables);\n return this;\n }\n\n /**\n * Returns an array of all table names in the database, sorted alphabetically.\n *\n * @example\n * ```ts\n * // Get all table names\n * const tableNames = await sdb.getTableNames();\n * console.log(tableNames); // Output: [\"employees\", \"customers\"]\n * ```\n *\n * @returns A promise that resolves to an array of table names.\n * @category Table Management\n */\n async getTableNames(): Promise<string[]> {\n return await getTableNames(this);\n }\n\n /**\n * Logs the names of all tables in the database to the console, sorted alphabetically.\n *\n * @example\n * ```ts\n * // Log all table names to the console\n * await sdb.logTableNames();\n * // Example output: SimpleDB - Tables: [\"employees\",\"customers\"]\n * ```\n *\n * @returns A promise that resolves to the database, so methods can be chained.\n * @category Table Management\n */\n async logTableNames(): Promise<this> {\n const tables = await this.getTableNames();\n if (tables.length > 0) {\n console.log(`\\nSimpleDB - Tables: ${JSON.stringify(tables)}`);\n } else {\n console.log(`\\nSimpleDB - No tables found.`);\n }\n return this;\n }\n\n /**\n * Returns an array of all SimpleTable instances in the database.\n *\n * The returned array is a snapshot and cannot mutate the database's internal\n * table registry.\n *\n * @example\n * ```ts\n * // Get all SimpleTable instances\n * const tables = sdb.getTables();\n * ```\n *\n * @returns A read-only array of SimpleTable instances.\n * @category Table Management\n */\n getTables(): readonly Table[] {\n return listRegisteredTables(this);\n }\n\n /**\n * Checks if a table exists in the database.\n *\n * @example\n * ```ts\n * // Check if a table named \"employees\" exists\n * const exists = await sdb.hasTable(\"employees\");\n * console.log(exists); // Output: true or false\n * ```\n *\n * @example\n * ```ts\n * // Check if a SimpleTable instance exists in the database\n * const myTable = sdb.newTable(\"my_data\");\n * const existsInstance = await sdb.hasTable(myTable);\n * console.log(existsInstance); // Output: true or false\n * ```\n *\n * @param table - The name of the table or a SimpleTable instance.\n * @returns A promise that resolves to `true` if the table exists, `false` otherwise.\n * @category Table Management\n */\n async hasTable(table: Table | string): Promise<boolean> {\n const tableName = typeof table === \"string\" ? table : table.name;\n const result = (await this.getTableNames()).includes(tableName);\n return result;\n }\n\n /**\n * Returns a list of installed DuckDB extensions.\n *\n * @example\n * ```ts\n * // Get a list of all installed extensions\n * const extensions = await sdb.getExtensions();\n * console.log(extensions); // Output: [{ extension_name: \"spatial\", loaded: true, ... }]\n * ```\n *\n * @returns A promise that resolves to an array of objects, each representing an installed extension.\n * @category DuckDB\n */\n async getExtensions(): Promise<\n {\n [key: string]: unknown;\n }[]\n > {\n return (await queryDB(\n this,\n `FROM duckdb_extensions();`,\n mergeOptions(this, {\n returnData: true,\n table: null,\n method: \"getExtensions()\",\n parameters: {},\n }),\n )) as {\n [key: string]: unknown;\n }[];\n }\n\n /**\n * Executes a custom SQL query directly against the DuckDB instance.\n * With the default `SimpleDB.expressionSyntax: \"js\"`, queries support JavaScript-style operators (`&&`, `||`, `===`, `!==`). Set `expressionSyntax: \"sql\"` for unchanged SQL.\n * Queries run in UTC. When data is returned, temporal values use the same\n * JavaScript representations as `SimpleTable.getData()`.\n *\n * `customQuery()` bypasses the dependency and table-generation tracking used\n * by `SimpleTable.cache()`. Reading or changing a table with `customQuery()`\n * can therefore cause `cache()` to return stale data. Include a value that\n * identifies the custom query's dependencies in the cache's `options.inputs`\n * (such as a table content hash), or use tracked `SimpleTable` methods.\n *\n * @example\n * ```ts\n * // Execute a query without returning data\n * await sdb.customQuery(\"CREATE TABLE young_employees AS SELECT * FROM employees WHERE age > 30\");\n * ```\n *\n * @example\n * ```ts\n * // Execute a query and return the results\n * const youngEmployees = await sdb.customQuery(\n * \"SELECT * FROM employees WHERE age < 30\",\n * { returnData: true }\n * );\n * console.log(youngEmployees);\n * ```\n *\n * @param query - The SQL query string to execute.\n * @param options - Configuration options for the query.\n * @param options.returnData - If `true`, the query result is returned. Defaults to `false`.\n * @param options.table - The name of the table associated with the query, primarily used for debugging and logging.\n * @returns A promise that resolves to the query result as an array of objects if `returnData` is `true`, otherwise `null`.\n * @category DuckDB\n */\n async customQuery(\n query: string,\n options: {\n returnData?: boolean;\n table?: string;\n } = {},\n ): Promise<\n | {\n [key: string]: unknown;\n }[]\n | null\n > {\n return await queryDB(\n this,\n query,\n mergeOptions(this, {\n returnData: options.returnData ?? false,\n table: options.table ?? null,\n method: \"customQuery()\",\n parameters: { query, options },\n }),\n );\n }\n\n /**\n * Imports a copy of a `.db` or `.duckdb` (DuckDB) or `.sqlite` (SQLite)\n * file into the current database. The source is opened read-only and detached\n * after importing; subsequent transformations do not modify the source file.\n * Imports work with in-memory and writable persistent databases. Existing\n * table-name conflicts are rejected. A failed import may leave partial changes\n * in the destination database.\n *\n * DuckDB files restore embedded SDA index definitions when present. SQLite\n * imports copy data without SDA index metadata. The `__sda` schema is reserved\n * for SDA metadata.\n * To edit an existing DuckDB file in place, use `new SimpleDB({ file })`.\n *\n * @example\n * ```ts\n * // Load a DuckDB database file\n * await sdb.loadDB(\"./my_database.db\");\n * ```\n *\n * @example\n * ```ts\n * // Import SQLite tables without modifying the original file\n * await sdb.loadDB(\"./my_database.sqlite\");\n * ```\n *\n * @example\n * ```ts\n * // Import a copy into a persistent DuckDB database\n * const sdb = new SimpleDB({ file: \"./analysis.duckdb\" });\n * await sdb.loadDB(\"./archive.db\");\n * await sdb.close();\n * ```\n *\n * @param file - The relative or absolute path to the database file.\n * @returns A promise that resolves to the database, so methods can be chained.\n * @category File Operations\n */\n async loadDB(file: string): Promise<this> {\n await loadDB(this, file);\n return this;\n }\n\n /**\n * Exports a snapshot of the current database after executing pending work.\n * Does not change the working database or where subsequent changes persist.\n * DuckDB outputs (`.db` and `.duckdb`) preserve database objects and embed SDA\n * index definitions in the reserved `__sda` schema.\n *\n * SQLite output (`.sqlite`) materializes main-schema tables and views as\n * tables. It does not preserve DuckDB schemas, indexes, constraints, or SDA\n * metadata, and SQLite type conversion may lose type information. Unsupported\n * conversions fail without replacing an existing destination.\n *\n * Existing files require explicit overwrite permission. The completed export\n * is published only after its connection is detached. Database files attached\n * to this instance, directories, and symbolic links cannot be replaced.\n *\n * @example\n * ```ts\n * // Write the current database to a DuckDB file\n * await sdb.writeDB(\"./my_exported_database.db\");\n * ```\n *\n * @example\n * ```ts\n * // Explicitly replace an earlier snapshot\n * await sdb.writeDB(\"./my_exported_database.duckdb\", { overwrite: true });\n * ```\n *\n * @example\n * ```ts\n * // Export table data for use with SQLite\n * await sdb.writeDB(\"./my_exported_database.sqlite\");\n * ```\n *\n * @param file - The relative or absolute path to the output file.\n * @param options - Configuration options for writing the database.\n * @param options.overwrite - If true, permits atomic replacement of an existing output file. Defaults to false.\n * @param options.metadata - If false, omits logical SDA index definitions from DuckDB exports. Defaults to true. Does not control physical indexes; SQLite exports never include SDA metadata.\n * @returns A promise that resolves to the database, so methods can be chained.\n * @category File Operations\n */\n async writeDB(\n file: string,\n options: { overwrite?: boolean; metadata?: boolean } = {},\n ): Promise<this> {\n await writeDB(this, file, options);\n return this;\n }\n\n /**\n * Executes all queued methods across every table in the database. Sync\n * builder methods (like `filter()` or `convert()`) only queue their\n * operation; execution happens when an async observer method (like\n * `getData()`, `log()`, or `writeData()`) is awaited. Use `run()` when\n * your script ends in pure mutations with nothing to observe and you want\n * the work done now.\n *\n * The whole database is flushed in program order, so operations on\n * different tables execute exactly in the order they were queued. This is\n * the database-level counterpart to `SimpleTable.run()`.\n *\n * @example\n * ```ts\n * // Nothing is observed after the mutations, so run() executes them.\n * table1.loadData(\"data1.csv\").convert({ price: \"number\" });\n * table2.loadData(\"data2.csv\").filter(`price > 0`);\n * await sdb.run();\n * ```\n *\n * @returns A promise that resolves to the SimpleDB instance once the queued methods have been executed.\n * @category Lifecycle\n */\n async run(): Promise<SimpleDB> {\n if (this.lifecycleState !== \"open\") {\n throw new Error(`run() cannot use a SimpleDB that is ${this.lifecycleState}.`);\n }\n await flushAllTables(this);\n return this;\n }\n\n /**\n * Executes pending transformations, saves SDA metadata for writable persistent\n * databases, and closes the connection and instance. Also cleans up temporary\n * files and the cache. Does not copy, compact, or replace the database file.\n *\n * @example\n * ```ts\n * // close() executes queued transformations before cleaning up resources.\n * table.loadData(\"data.csv\").convert({ price: \"number\" });\n * await sdb.close();\n * ```\n *\n * @returns A promise that resolves to the SimpleDB instance after cleanup.\n * @throws An error after cleanup when pending execution or cleanup fails.\n * @category Lifecycle\n */\n async close(): Promise<SimpleDB> {\n if (this.#closePromise !== null) {\n return await this.#closePromise;\n }\n this.lifecycleState = \"closing\";\n const closePromise = this.#close();\n this.#closePromise = closePromise;\n return await closePromise;\n }\n\n async #close(): Promise<SimpleDB> {\n let operationError: unknown;\n try {\n await flushAllTables(this);\n if (this.file !== \":memory:\" && !this.readOnly && this.#initialized) {\n const database = await getCurrentDatabase(this);\n await readDbMetadata(this, database);\n await writeDbMetadata(this, database, getDbIndexes(this));\n await queryDbFile(this, `CHECKPOINT ${quoteIdentifier(database)};`);\n }\n } catch (error) {\n operationError = error;\n // A failed flush can requeue work belonging to other tables. The\n // connection is about to close, so release those captured values.\n discardAllPending(this);\n }\n\n const cleanupErrors: unknown[] = [];\n const cacheCleanupMessages: string[] = [];\n if (this.db instanceof DuckDBInstance) {\n try {\n this.connection.closeSync();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n this.db.closeSync();\n } catch (error) {\n cleanupErrors.push(error);\n }\n }\n try {\n const tmpDir = this.tempDir ?? (this.file === \":memory:\" ? \".tmp\" : `${this.file}.tmp`);\n if (existsSync(tmpDir)) {\n rmSync(tmpDir, { recursive: true });\n }\n // Defer cache logs until after the summary, while timing cleanup too.\n cleanCache(this, (message) => cacheCleanupMessages.push(message));\n } catch (error) {\n cleanupErrors.push(error);\n }\n this.lifecycleState = \"closed\";\n\n if (\n operationError === undefined &&\n cleanupErrors.length === 0 &&\n typeof this.durationStart === \"number\"\n ) {\n let string = prettyDuration(this.durationStart, {\n prefix: \"\\n\\nSimpleDB ran for \",\n });\n\n if (this.cacheTimeSaved > 0) {\n string += ` / ${prettyDuration(0, {\n end: this.cacheTimeSaved,\n })} saved by using the cache`;\n }\n if (this.cacheTimeWriting > 0) {\n string += ` / ${prettyDuration(0, {\n end: this.cacheTimeWriting,\n })} spent writing the cache`;\n }\n\n console.log(`${string}\\n`);\n }\n\n for (const message of cacheCleanupMessages) {\n console.log(message);\n }\n if (cacheCleanupMessages.length > 0) {\n console.log();\n }\n\n if (operationError !== undefined && cleanupErrors.length > 0) {\n throw new AggregateError(\n [operationError, ...cleanupErrors],\n \"Pending execution and database cleanup both failed.\",\n { cause: operationError },\n );\n }\n if (operationError !== undefined) {\n throw operationError;\n }\n if (cleanupErrors.length === 1) {\n throw cleanupErrors[0];\n }\n if (cleanupErrors.length > 1) {\n throw new AggregateError(\n cleanupErrors,\n \"Multiple errors occurred while cleaning up the database.\",\n { cause: cleanupErrors[0] },\n );\n }\n\n return this;\n }\n}\n"],"mappings":"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"}