@nshiab/simple-data-analysis-core 2.0.8 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (513) hide show
  1. package/esm/class/SDAError.d.ts +6 -6
  2. package/esm/class/SDAError.js +6 -6
  3. package/esm/class/Simple.d.ts +9 -9
  4. package/esm/class/Simple.js +9 -9
  5. package/esm/class/SimpleDB.d.ts +80 -76
  6. package/esm/class/SimpleDB.d.ts.map +1 -1
  7. package/esm/class/SimpleDB.js +80 -76
  8. package/esm/class/SimpleTable.d.ts +2805 -1077
  9. package/esm/class/SimpleTable.d.ts.map +1 -1
  10. package/esm/class/SimpleTable.js +2777 -1077
  11. package/esm/helpers/appendColumnBatches.d.ts +3 -0
  12. package/esm/helpers/appendColumnBatches.d.ts.map +1 -0
  13. package/esm/helpers/appendColumnBatches.js +21 -0
  14. package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts +45 -0
  15. package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts.map +1 -0
  16. package/esm/helpers/buildApproximateMutualReachabilityMst.js +212 -0
  17. package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts +14 -0
  18. package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts.map +1 -0
  19. package/esm/helpers/buildChronologicalGraphComponentsSql.js +167 -0
  20. package/esm/helpers/buildExactMutualReachabilityMst.d.ts +28 -0
  21. package/esm/helpers/buildExactMutualReachabilityMst.d.ts.map +1 -0
  22. package/esm/helpers/buildExactMutualReachabilityMst.js +97 -0
  23. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts +12 -0
  24. package/esm/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -0
  25. package/esm/helpers/buildGraphTemporalCostStateSql.js +86 -0
  26. package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts +13 -0
  27. package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts.map +1 -0
  28. package/esm/helpers/buildGraphTemporalReachabilitySql.js +70 -0
  29. package/esm/helpers/buildSparseMutualReachabilityMst.d.ts +10 -0
  30. package/esm/helpers/buildSparseMutualReachabilityMst.d.ts.map +1 -0
  31. package/esm/helpers/buildSparseMutualReachabilityMst.js +47 -0
  32. package/esm/helpers/buildUmapGraph.d.ts +21 -0
  33. package/esm/helpers/buildUmapGraph.d.ts.map +1 -0
  34. package/esm/helpers/buildUmapGraph.js +61 -0
  35. package/esm/helpers/buildVectorNeighbors.d.ts +45 -0
  36. package/esm/helpers/buildVectorNeighbors.d.ts.map +1 -0
  37. package/esm/helpers/buildVectorNeighbors.js +170 -0
  38. package/esm/helpers/buildWeakGraphComponentsSql.d.ts +3 -0
  39. package/esm/helpers/buildWeakGraphComponentsSql.d.ts.map +1 -0
  40. package/esm/helpers/buildWeakGraphComponentsSql.js +32 -0
  41. package/esm/helpers/cacheDatabase.d.ts.map +1 -1
  42. package/esm/helpers/cacheDatabase.js +2 -1
  43. package/esm/helpers/camelCase.d.ts +7 -5
  44. package/esm/helpers/camelCase.d.ts.map +1 -1
  45. package/esm/helpers/camelCase.js +7 -5
  46. package/esm/helpers/capitalize.d.ts +6 -4
  47. package/esm/helpers/capitalize.d.ts.map +1 -1
  48. package/esm/helpers/capitalize.js +6 -4
  49. package/esm/helpers/clusterHdbscan.d.ts +18 -0
  50. package/esm/helpers/clusterHdbscan.d.ts.map +1 -0
  51. package/esm/helpers/clusterHdbscan.js +342 -0
  52. package/esm/helpers/computeCovariance.d.ts +16 -0
  53. package/esm/helpers/computeCovariance.d.ts.map +1 -0
  54. package/esm/helpers/computeCovariance.js +99 -0
  55. package/esm/helpers/computeMahalanobisDistances.d.ts +14 -0
  56. package/esm/helpers/computeMahalanobisDistances.d.ts.map +1 -0
  57. package/esm/helpers/computeMahalanobisDistances.js +87 -0
  58. package/esm/helpers/createDirectory.d.ts +4 -3
  59. package/esm/helpers/createDirectory.d.ts.map +1 -1
  60. package/esm/helpers/createDirectory.js +4 -3
  61. package/esm/helpers/dataToArrays.d.ts +6 -4
  62. package/esm/helpers/dataToArrays.d.ts.map +1 -1
  63. package/esm/helpers/dataToArrays.js +6 -4
  64. package/esm/helpers/extractTypes.d.ts +1 -1
  65. package/esm/helpers/extractTypes.js +4 -9
  66. package/esm/helpers/factorCovariance.d.ts +17 -0
  67. package/esm/helpers/factorCovariance.d.ts.map +1 -0
  68. package/esm/helpers/factorCovariance.js +189 -0
  69. package/esm/helpers/findGeoColumn.d.ts +6 -4
  70. package/esm/helpers/findGeoColumn.d.ts.map +1 -1
  71. package/esm/helpers/findGeoColumn.js +6 -4
  72. package/esm/helpers/findGeoColumnFromSchema.d.ts +8 -5
  73. package/esm/helpers/findGeoColumnFromSchema.d.ts.map +1 -1
  74. package/esm/helpers/findGeoColumnFromSchema.js +8 -5
  75. package/esm/helpers/fitUmapCurve.d.ts +2 -0
  76. package/esm/helpers/fitUmapCurve.d.ts.map +1 -0
  77. package/esm/helpers/fitUmapCurve.js +66 -0
  78. package/esm/helpers/formatDate.d.ts +12 -6
  79. package/esm/helpers/formatDate.d.ts.map +1 -1
  80. package/esm/helpers/formatDate.js +12 -6
  81. package/esm/helpers/formatMissingTables.d.ts +8 -5
  82. package/esm/helpers/formatMissingTables.d.ts.map +1 -1
  83. package/esm/helpers/formatMissingTables.js +8 -5
  84. package/esm/helpers/formatNumber.d.ts +19 -10
  85. package/esm/helpers/formatNumber.d.ts.map +1 -1
  86. package/esm/helpers/formatNumber.js +32 -17
  87. package/esm/helpers/getGraphEdgeIdColumn.d.ts +9 -0
  88. package/esm/helpers/getGraphEdgeIdColumn.d.ts.map +1 -0
  89. package/esm/helpers/getGraphEdgeIdColumn.js +25 -0
  90. package/esm/helpers/getGraphEndpointColumns.d.ts +11 -0
  91. package/esm/helpers/getGraphEndpointColumns.d.ts.map +1 -0
  92. package/esm/helpers/getGraphEndpointColumns.js +160 -0
  93. package/esm/helpers/getGraphWeightColumn.d.ts +10 -0
  94. package/esm/helpers/getGraphWeightColumn.d.ts.map +1 -0
  95. package/esm/helpers/getGraphWeightColumn.js +40 -0
  96. package/esm/helpers/graphRouteResultSchema.d.ts +4 -0
  97. package/esm/helpers/graphRouteResultSchema.d.ts.map +1 -0
  98. package/esm/helpers/graphRouteResultSchema.js +12 -0
  99. package/esm/helpers/graphRouteResultSelect.d.ts +4 -0
  100. package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -0
  101. package/esm/helpers/graphRouteResultSelect.js +22 -0
  102. package/esm/helpers/hasGeometryColumn.d.ts +4 -3
  103. package/esm/helpers/hasGeometryColumn.d.ts.map +1 -1
  104. package/esm/helpers/hasGeometryColumn.js +4 -3
  105. package/esm/helpers/initialUmapCoordinates.d.ts +2 -0
  106. package/esm/helpers/initialUmapCoordinates.d.ts.map +1 -0
  107. package/esm/helpers/initialUmapCoordinates.js +5 -0
  108. package/esm/helpers/inspectGraphConnectivity.d.ts +10 -0
  109. package/esm/helpers/inspectGraphConnectivity.d.ts.map +1 -0
  110. package/esm/helpers/inspectGraphConnectivity.js +55 -0
  111. package/esm/helpers/mergeOptions.d.ts +24 -13
  112. package/esm/helpers/mergeOptions.d.ts.map +1 -1
  113. package/esm/helpers/mergeOptions.js +24 -13
  114. package/esm/helpers/optimizeUmapLayout.d.ts +7 -0
  115. package/esm/helpers/optimizeUmapLayout.d.ts.map +1 -0
  116. package/esm/helpers/optimizeUmapLayout.js +93 -0
  117. package/esm/helpers/parseValue.d.ts +6 -4
  118. package/esm/helpers/parseValue.d.ts.map +1 -1
  119. package/esm/helpers/parseValue.js +6 -4
  120. package/esm/helpers/prepareGraphRouteSql.d.ts +31 -0
  121. package/esm/helpers/prepareGraphRouteSql.d.ts.map +1 -0
  122. package/esm/helpers/prepareGraphRouteSql.js +86 -0
  123. package/esm/helpers/prepareGraphStarts.d.ts +9 -0
  124. package/esm/helpers/prepareGraphStarts.d.ts.map +1 -0
  125. package/esm/helpers/prepareGraphStarts.js +68 -0
  126. package/esm/helpers/prepareGraphTemporalSql.d.ts +28 -0
  127. package/esm/helpers/prepareGraphTemporalSql.d.ts.map +1 -0
  128. package/esm/helpers/prepareGraphTemporalSql.js +154 -0
  129. package/esm/helpers/prepareGraphTraversal.d.ts +19 -0
  130. package/esm/helpers/prepareGraphTraversal.d.ts.map +1 -0
  131. package/esm/helpers/prepareGraphTraversal.js +79 -0
  132. package/esm/helpers/prepareNumericFeatures.d.ts +41 -0
  133. package/esm/helpers/prepareNumericFeatures.d.ts.map +1 -0
  134. package/esm/helpers/prepareNumericFeatures.js +210 -0
  135. package/esm/helpers/prepareUmapLayoutOptions.d.ts +14 -0
  136. package/esm/helpers/prepareUmapLayoutOptions.d.ts.map +1 -0
  137. package/esm/helpers/prepareUmapLayoutOptions.js +23 -0
  138. package/esm/helpers/prettyDuration.d.ts +14 -8
  139. package/esm/helpers/prettyDuration.d.ts.map +1 -1
  140. package/esm/helpers/prettyDuration.js +14 -8
  141. package/esm/helpers/printTable.d.ts +18 -13
  142. package/esm/helpers/printTable.d.ts.map +1 -1
  143. package/esm/helpers/printTable.js +18 -13
  144. package/esm/helpers/publishPreparedColumns.d.ts +37 -0
  145. package/esm/helpers/publishPreparedColumns.d.ts.map +1 -0
  146. package/esm/helpers/publishPreparedColumns.js +113 -0
  147. package/esm/helpers/queryDB.d.ts +24 -13
  148. package/esm/helpers/queryDB.d.ts.map +1 -1
  149. package/esm/helpers/queryDB.js +24 -13
  150. package/esm/helpers/queueAsyncBarrier.d.ts +12 -7
  151. package/esm/helpers/queueAsyncBarrier.d.ts.map +1 -1
  152. package/esm/helpers/queueAsyncBarrier.js +12 -7
  153. package/esm/helpers/queueGraphResult.d.ts +18 -0
  154. package/esm/helpers/queueGraphResult.d.ts.map +1 -0
  155. package/esm/helpers/queueGraphResult.js +39 -0
  156. package/esm/helpers/quoteIdentifier.d.ts +4 -3
  157. package/esm/helpers/quoteIdentifier.d.ts.map +1 -1
  158. package/esm/helpers/quoteIdentifier.js +4 -3
  159. package/esm/helpers/quoteQualifiedIdentifier.d.ts +6 -4
  160. package/esm/helpers/quoteQualifiedIdentifier.d.ts.map +1 -1
  161. package/esm/helpers/quoteQualifiedIdentifier.js +6 -4
  162. package/esm/helpers/readScalarNumber.d.ts +3 -0
  163. package/esm/helpers/readScalarNumber.d.ts.map +1 -0
  164. package/esm/helpers/readScalarNumber.js +4 -0
  165. package/esm/helpers/runQuery.d.ts.map +1 -1
  166. package/esm/helpers/runQuery.js +17 -3
  167. package/esm/helpers/selectFuzzyReplacements.d.ts +11 -0
  168. package/esm/helpers/selectFuzzyReplacements.d.ts.map +1 -0
  169. package/esm/helpers/selectFuzzyReplacements.js +124 -0
  170. package/esm/helpers/stabilizeCosineVectors.d.ts +14 -0
  171. package/esm/helpers/stabilizeCosineVectors.d.ts.map +1 -0
  172. package/esm/helpers/stabilizeCosineVectors.js +34 -0
  173. package/esm/helpers/stringToArray.d.ts +4 -3
  174. package/esm/helpers/stringToArray.d.ts.map +1 -1
  175. package/esm/helpers/stringToArray.js +4 -3
  176. package/esm/helpers/umapRandom.d.ts +2 -0
  177. package/esm/helpers/umapRandom.d.ts.map +1 -0
  178. package/esm/helpers/umapRandom.js +10 -0
  179. package/esm/helpers/updateColumnsWithJS.d.ts +12 -6
  180. package/esm/helpers/updateColumnsWithJS.d.ts.map +1 -1
  181. package/esm/helpers/updateColumnsWithJS.js +12 -6
  182. package/esm/helpers/validateGraphRouteResultSchema.d.ts +4 -0
  183. package/esm/helpers/validateGraphRouteResultSchema.d.ts.map +1 -0
  184. package/esm/helpers/validateGraphRouteResultSchema.js +13 -0
  185. package/esm/helpers/validateGraphTemporalEvents.d.ts +7 -0
  186. package/esm/helpers/validateGraphTemporalEvents.d.ts.map +1 -0
  187. package/esm/helpers/validateGraphTemporalEvents.js +47 -0
  188. package/esm/helpers/validateNumericalAnalysis.d.ts +10 -6
  189. package/esm/helpers/validateNumericalAnalysis.d.ts.map +1 -1
  190. package/esm/helpers/validateNumericalAnalysis.js +10 -6
  191. package/esm/helpers/validateVectorRowIds.d.ts +4 -0
  192. package/esm/helpers/validateVectorRowIds.d.ts.map +1 -0
  193. package/esm/helpers/validateVectorRowIds.js +16 -0
  194. package/esm/helpers/vectorDistanceExpression.d.ts +6 -0
  195. package/esm/helpers/vectorDistanceExpression.d.ts.map +1 -0
  196. package/esm/helpers/vectorDistanceExpression.js +11 -0
  197. package/esm/helpers/wrapString.d.ts +10 -7
  198. package/esm/helpers/wrapString.d.ts.map +1 -1
  199. package/esm/helpers/wrapString.js +10 -7
  200. package/esm/methods/addId.d.ts +5 -0
  201. package/esm/methods/addId.d.ts.map +1 -0
  202. package/esm/methods/addId.js +38 -0
  203. package/esm/methods/cache.js +1 -1
  204. package/esm/methods/commonNeighbors.d.ts +10 -0
  205. package/esm/methods/commonNeighbors.d.ts.map +1 -0
  206. package/esm/methods/commonNeighbors.js +101 -0
  207. package/esm/methods/connectedComponents.d.ts +9 -0
  208. package/esm/methods/connectedComponents.d.ts.map +1 -0
  209. package/esm/methods/connectedComponents.js +147 -0
  210. package/esm/methods/degree.d.ts +9 -0
  211. package/esm/methods/degree.d.ts.map +1 -0
  212. package/esm/methods/degree.js +135 -0
  213. package/esm/methods/distances.d.ts +12 -0
  214. package/esm/methods/distances.d.ts.map +1 -0
  215. package/esm/methods/distances.js +164 -0
  216. package/esm/methods/findCycles.d.ts +12 -0
  217. package/esm/methods/findCycles.d.ts.map +1 -0
  218. package/esm/methods/findCycles.js +330 -0
  219. package/esm/methods/fuzzyClean.d.ts.map +1 -1
  220. package/esm/methods/fuzzyClean.js +17 -136
  221. package/esm/methods/fuzzyJoin.js +70 -16
  222. package/esm/methods/getTypes.d.ts +1 -1
  223. package/esm/methods/hdbscan.d.ts +5 -0
  224. package/esm/methods/hdbscan.d.ts.map +1 -0
  225. package/esm/methods/hdbscan.js +208 -0
  226. package/esm/methods/loadArray.d.ts.map +1 -1
  227. package/esm/methods/loadArray.js +3 -20
  228. package/esm/methods/mahalanobis.d.ts +5 -0
  229. package/esm/methods/mahalanobis.d.ts.map +1 -0
  230. package/esm/methods/mahalanobis.js +92 -0
  231. package/esm/methods/neighbors.d.ts +9 -0
  232. package/esm/methods/neighbors.d.ts.map +1 -0
  233. package/esm/methods/neighbors.js +81 -0
  234. package/esm/methods/normalizeVector.d.ts +5 -0
  235. package/esm/methods/normalizeVector.d.ts.map +1 -0
  236. package/esm/methods/normalizeVector.js +132 -0
  237. package/esm/methods/paths.d.ts +12 -0
  238. package/esm/methods/paths.d.ts.map +1 -0
  239. package/esm/methods/paths.js +287 -0
  240. package/esm/methods/reachable.d.ts +11 -0
  241. package/esm/methods/reachable.d.ts.map +1 -0
  242. package/esm/methods/reachable.js +131 -0
  243. package/esm/methods/rowToVector.d.ts +5 -0
  244. package/esm/methods/rowToVector.d.ts.map +1 -0
  245. package/esm/methods/rowToVector.js +77 -0
  246. package/esm/methods/shortestPath.d.ts +12 -0
  247. package/esm/methods/shortestPath.d.ts.map +1 -0
  248. package/esm/methods/shortestPath.js +337 -0
  249. package/esm/methods/topologicalSort.d.ts +7 -0
  250. package/esm/methods/topologicalSort.d.ts.map +1 -0
  251. package/esm/methods/topologicalSort.js +164 -0
  252. package/esm/methods/umap.d.ts +5 -0
  253. package/esm/methods/umap.d.ts.map +1 -0
  254. package/esm/methods/umap.js +156 -0
  255. package/esm/methods/updateWithJS.js +9 -21
  256. package/llm.md +2170 -128
  257. package/llms.txt +1 -1
  258. package/package.json +1 -1
  259. package/script/class/SDAError.d.ts +6 -6
  260. package/script/class/SDAError.js +6 -6
  261. package/script/class/Simple.d.ts +9 -9
  262. package/script/class/Simple.js +9 -9
  263. package/script/class/SimpleDB.d.ts +80 -76
  264. package/script/class/SimpleDB.d.ts.map +1 -1
  265. package/script/class/SimpleDB.js +80 -76
  266. package/script/class/SimpleTable.d.ts +2805 -1077
  267. package/script/class/SimpleTable.d.ts.map +1 -1
  268. package/script/class/SimpleTable.js +2777 -1077
  269. package/script/helpers/appendColumnBatches.d.ts +3 -0
  270. package/script/helpers/appendColumnBatches.d.ts.map +1 -0
  271. package/script/helpers/appendColumnBatches.js +24 -0
  272. package/script/helpers/buildApproximateMutualReachabilityMst.d.ts +45 -0
  273. package/script/helpers/buildApproximateMutualReachabilityMst.d.ts.map +1 -0
  274. package/script/helpers/buildApproximateMutualReachabilityMst.js +219 -0
  275. package/script/helpers/buildChronologicalGraphComponentsSql.d.ts +14 -0
  276. package/script/helpers/buildChronologicalGraphComponentsSql.d.ts.map +1 -0
  277. package/script/helpers/buildChronologicalGraphComponentsSql.js +174 -0
  278. package/script/helpers/buildExactMutualReachabilityMst.d.ts +28 -0
  279. package/script/helpers/buildExactMutualReachabilityMst.d.ts.map +1 -0
  280. package/script/helpers/buildExactMutualReachabilityMst.js +103 -0
  281. package/script/helpers/buildGraphTemporalCostStateSql.d.ts +12 -0
  282. package/script/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -0
  283. package/script/helpers/buildGraphTemporalCostStateSql.js +92 -0
  284. package/script/helpers/buildGraphTemporalReachabilitySql.d.ts +13 -0
  285. package/script/helpers/buildGraphTemporalReachabilitySql.d.ts.map +1 -0
  286. package/script/helpers/buildGraphTemporalReachabilitySql.js +76 -0
  287. package/script/helpers/buildSparseMutualReachabilityMst.d.ts +10 -0
  288. package/script/helpers/buildSparseMutualReachabilityMst.d.ts.map +1 -0
  289. package/script/helpers/buildSparseMutualReachabilityMst.js +50 -0
  290. package/script/helpers/buildUmapGraph.d.ts +21 -0
  291. package/script/helpers/buildUmapGraph.d.ts.map +1 -0
  292. package/script/helpers/buildUmapGraph.js +67 -0
  293. package/script/helpers/buildVectorNeighbors.d.ts +45 -0
  294. package/script/helpers/buildVectorNeighbors.d.ts.map +1 -0
  295. package/script/helpers/buildVectorNeighbors.js +176 -0
  296. package/script/helpers/buildWeakGraphComponentsSql.d.ts +3 -0
  297. package/script/helpers/buildWeakGraphComponentsSql.d.ts.map +1 -0
  298. package/script/helpers/buildWeakGraphComponentsSql.js +38 -0
  299. package/script/helpers/cacheDatabase.d.ts.map +1 -1
  300. package/script/helpers/cacheDatabase.js +2 -1
  301. package/script/helpers/camelCase.d.ts +7 -5
  302. package/script/helpers/camelCase.d.ts.map +1 -1
  303. package/script/helpers/camelCase.js +7 -5
  304. package/script/helpers/capitalize.d.ts +6 -4
  305. package/script/helpers/capitalize.d.ts.map +1 -1
  306. package/script/helpers/capitalize.js +6 -4
  307. package/script/helpers/clusterHdbscan.d.ts +18 -0
  308. package/script/helpers/clusterHdbscan.d.ts.map +1 -0
  309. package/script/helpers/clusterHdbscan.js +346 -0
  310. package/script/helpers/computeCovariance.d.ts +16 -0
  311. package/script/helpers/computeCovariance.d.ts.map +1 -0
  312. package/script/helpers/computeCovariance.js +105 -0
  313. package/script/helpers/computeMahalanobisDistances.d.ts +14 -0
  314. package/script/helpers/computeMahalanobisDistances.d.ts.map +1 -0
  315. package/script/helpers/computeMahalanobisDistances.js +93 -0
  316. package/script/helpers/createDirectory.d.ts +4 -3
  317. package/script/helpers/createDirectory.d.ts.map +1 -1
  318. package/script/helpers/createDirectory.js +4 -3
  319. package/script/helpers/dataToArrays.d.ts +6 -4
  320. package/script/helpers/dataToArrays.d.ts.map +1 -1
  321. package/script/helpers/dataToArrays.js +6 -4
  322. package/script/helpers/extractTypes.d.ts +1 -1
  323. package/script/helpers/extractTypes.js +4 -9
  324. package/script/helpers/factorCovariance.d.ts +17 -0
  325. package/script/helpers/factorCovariance.d.ts.map +1 -0
  326. package/script/helpers/factorCovariance.js +194 -0
  327. package/script/helpers/findGeoColumn.d.ts +6 -4
  328. package/script/helpers/findGeoColumn.d.ts.map +1 -1
  329. package/script/helpers/findGeoColumn.js +6 -4
  330. package/script/helpers/findGeoColumnFromSchema.d.ts +8 -5
  331. package/script/helpers/findGeoColumnFromSchema.d.ts.map +1 -1
  332. package/script/helpers/findGeoColumnFromSchema.js +8 -5
  333. package/script/helpers/fitUmapCurve.d.ts +2 -0
  334. package/script/helpers/fitUmapCurve.d.ts.map +1 -0
  335. package/script/helpers/fitUmapCurve.js +69 -0
  336. package/script/helpers/formatDate.d.ts +12 -6
  337. package/script/helpers/formatDate.d.ts.map +1 -1
  338. package/script/helpers/formatDate.js +12 -6
  339. package/script/helpers/formatMissingTables.d.ts +8 -5
  340. package/script/helpers/formatMissingTables.d.ts.map +1 -1
  341. package/script/helpers/formatMissingTables.js +8 -5
  342. package/script/helpers/formatNumber.d.ts +19 -10
  343. package/script/helpers/formatNumber.d.ts.map +1 -1
  344. package/script/helpers/formatNumber.js +32 -17
  345. package/script/helpers/getGraphEdgeIdColumn.d.ts +9 -0
  346. package/script/helpers/getGraphEdgeIdColumn.d.ts.map +1 -0
  347. package/script/helpers/getGraphEdgeIdColumn.js +31 -0
  348. package/script/helpers/getGraphEndpointColumns.d.ts +11 -0
  349. package/script/helpers/getGraphEndpointColumns.d.ts.map +1 -0
  350. package/script/helpers/getGraphEndpointColumns.js +166 -0
  351. package/script/helpers/getGraphWeightColumn.d.ts +10 -0
  352. package/script/helpers/getGraphWeightColumn.d.ts.map +1 -0
  353. package/script/helpers/getGraphWeightColumn.js +46 -0
  354. package/script/helpers/graphRouteResultSchema.d.ts +4 -0
  355. package/script/helpers/graphRouteResultSchema.d.ts.map +1 -0
  356. package/script/helpers/graphRouteResultSchema.js +18 -0
  357. package/script/helpers/graphRouteResultSelect.d.ts +4 -0
  358. package/script/helpers/graphRouteResultSelect.d.ts.map +1 -0
  359. package/script/helpers/graphRouteResultSelect.js +28 -0
  360. package/script/helpers/hasGeometryColumn.d.ts +4 -3
  361. package/script/helpers/hasGeometryColumn.d.ts.map +1 -1
  362. package/script/helpers/hasGeometryColumn.js +4 -3
  363. package/script/helpers/initialUmapCoordinates.d.ts +2 -0
  364. package/script/helpers/initialUmapCoordinates.d.ts.map +1 -0
  365. package/script/helpers/initialUmapCoordinates.js +11 -0
  366. package/script/helpers/inspectGraphConnectivity.d.ts +10 -0
  367. package/script/helpers/inspectGraphConnectivity.d.ts.map +1 -0
  368. package/script/helpers/inspectGraphConnectivity.js +58 -0
  369. package/script/helpers/mergeOptions.d.ts +24 -13
  370. package/script/helpers/mergeOptions.d.ts.map +1 -1
  371. package/script/helpers/mergeOptions.js +24 -13
  372. package/script/helpers/optimizeUmapLayout.d.ts +7 -0
  373. package/script/helpers/optimizeUmapLayout.d.ts.map +1 -0
  374. package/script/helpers/optimizeUmapLayout.js +99 -0
  375. package/script/helpers/parseValue.d.ts +6 -4
  376. package/script/helpers/parseValue.d.ts.map +1 -1
  377. package/script/helpers/parseValue.js +6 -4
  378. package/script/helpers/prepareGraphRouteSql.d.ts +31 -0
  379. package/script/helpers/prepareGraphRouteSql.d.ts.map +1 -0
  380. package/script/helpers/prepareGraphRouteSql.js +127 -0
  381. package/script/helpers/prepareGraphStarts.d.ts +9 -0
  382. package/script/helpers/prepareGraphStarts.d.ts.map +1 -0
  383. package/script/helpers/prepareGraphStarts.js +71 -0
  384. package/script/helpers/prepareGraphTemporalSql.d.ts +28 -0
  385. package/script/helpers/prepareGraphTemporalSql.d.ts.map +1 -0
  386. package/script/helpers/prepareGraphTemporalSql.js +161 -0
  387. package/script/helpers/prepareGraphTraversal.d.ts +19 -0
  388. package/script/helpers/prepareGraphTraversal.d.ts.map +1 -0
  389. package/script/helpers/prepareGraphTraversal.js +87 -0
  390. package/script/helpers/prepareNumericFeatures.d.ts +41 -0
  391. package/script/helpers/prepareNumericFeatures.d.ts.map +1 -0
  392. package/script/helpers/prepareNumericFeatures.js +217 -0
  393. package/script/helpers/prepareUmapLayoutOptions.d.ts +14 -0
  394. package/script/helpers/prepareUmapLayoutOptions.d.ts.map +1 -0
  395. package/script/helpers/prepareUmapLayoutOptions.js +29 -0
  396. package/script/helpers/prettyDuration.d.ts +14 -8
  397. package/script/helpers/prettyDuration.d.ts.map +1 -1
  398. package/script/helpers/prettyDuration.js +14 -8
  399. package/script/helpers/printTable.d.ts +18 -13
  400. package/script/helpers/printTable.d.ts.map +1 -1
  401. package/script/helpers/printTable.js +18 -13
  402. package/script/helpers/publishPreparedColumns.d.ts +37 -0
  403. package/script/helpers/publishPreparedColumns.d.ts.map +1 -0
  404. package/script/helpers/publishPreparedColumns.js +119 -0
  405. package/script/helpers/queryDB.d.ts +24 -13
  406. package/script/helpers/queryDB.d.ts.map +1 -1
  407. package/script/helpers/queryDB.js +24 -13
  408. package/script/helpers/queueAsyncBarrier.d.ts +12 -7
  409. package/script/helpers/queueAsyncBarrier.d.ts.map +1 -1
  410. package/script/helpers/queueAsyncBarrier.js +12 -7
  411. package/script/helpers/queueGraphResult.d.ts +18 -0
  412. package/script/helpers/queueGraphResult.d.ts.map +1 -0
  413. package/script/helpers/queueGraphResult.js +45 -0
  414. package/script/helpers/quoteIdentifier.d.ts +4 -3
  415. package/script/helpers/quoteIdentifier.d.ts.map +1 -1
  416. package/script/helpers/quoteIdentifier.js +4 -3
  417. package/script/helpers/quoteQualifiedIdentifier.d.ts +6 -4
  418. package/script/helpers/quoteQualifiedIdentifier.d.ts.map +1 -1
  419. package/script/helpers/quoteQualifiedIdentifier.js +6 -4
  420. package/script/helpers/readScalarNumber.d.ts +3 -0
  421. package/script/helpers/readScalarNumber.d.ts.map +1 -0
  422. package/script/helpers/readScalarNumber.js +7 -0
  423. package/script/helpers/runQuery.d.ts.map +1 -1
  424. package/script/helpers/runQuery.js +17 -3
  425. package/script/helpers/selectFuzzyReplacements.d.ts +11 -0
  426. package/script/helpers/selectFuzzyReplacements.d.ts.map +1 -0
  427. package/script/helpers/selectFuzzyReplacements.js +127 -0
  428. package/script/helpers/stabilizeCosineVectors.d.ts +14 -0
  429. package/script/helpers/stabilizeCosineVectors.d.ts.map +1 -0
  430. package/script/helpers/stabilizeCosineVectors.js +40 -0
  431. package/script/helpers/stringToArray.d.ts +4 -3
  432. package/script/helpers/stringToArray.d.ts.map +1 -1
  433. package/script/helpers/stringToArray.js +4 -3
  434. package/script/helpers/umapRandom.d.ts +2 -0
  435. package/script/helpers/umapRandom.d.ts.map +1 -0
  436. package/script/helpers/umapRandom.js +13 -0
  437. package/script/helpers/updateColumnsWithJS.d.ts +12 -6
  438. package/script/helpers/updateColumnsWithJS.d.ts.map +1 -1
  439. package/script/helpers/updateColumnsWithJS.js +12 -6
  440. package/script/helpers/validateGraphRouteResultSchema.d.ts +4 -0
  441. package/script/helpers/validateGraphRouteResultSchema.d.ts.map +1 -0
  442. package/script/helpers/validateGraphRouteResultSchema.js +19 -0
  443. package/script/helpers/validateGraphTemporalEvents.d.ts +7 -0
  444. package/script/helpers/validateGraphTemporalEvents.d.ts.map +1 -0
  445. package/script/helpers/validateGraphTemporalEvents.js +53 -0
  446. package/script/helpers/validateNumericalAnalysis.d.ts +10 -6
  447. package/script/helpers/validateNumericalAnalysis.d.ts.map +1 -1
  448. package/script/helpers/validateNumericalAnalysis.js +10 -6
  449. package/script/helpers/validateVectorRowIds.d.ts +4 -0
  450. package/script/helpers/validateVectorRowIds.d.ts.map +1 -0
  451. package/script/helpers/validateVectorRowIds.js +19 -0
  452. package/script/helpers/vectorDistanceExpression.d.ts +6 -0
  453. package/script/helpers/vectorDistanceExpression.d.ts.map +1 -0
  454. package/script/helpers/vectorDistanceExpression.js +14 -0
  455. package/script/helpers/wrapString.d.ts +10 -7
  456. package/script/helpers/wrapString.d.ts.map +1 -1
  457. package/script/helpers/wrapString.js +10 -7
  458. package/script/methods/addId.d.ts +5 -0
  459. package/script/methods/addId.d.ts.map +1 -0
  460. package/script/methods/addId.js +44 -0
  461. package/script/methods/cache.js +1 -1
  462. package/script/methods/commonNeighbors.d.ts +10 -0
  463. package/script/methods/commonNeighbors.d.ts.map +1 -0
  464. package/script/methods/commonNeighbors.js +140 -0
  465. package/script/methods/connectedComponents.d.ts +9 -0
  466. package/script/methods/connectedComponents.d.ts.map +1 -0
  467. package/script/methods/connectedComponents.js +186 -0
  468. package/script/methods/degree.d.ts +9 -0
  469. package/script/methods/degree.d.ts.map +1 -0
  470. package/script/methods/degree.js +141 -0
  471. package/script/methods/distances.d.ts +12 -0
  472. package/script/methods/distances.d.ts.map +1 -0
  473. package/script/methods/distances.js +203 -0
  474. package/script/methods/findCycles.d.ts +12 -0
  475. package/script/methods/findCycles.d.ts.map +1 -0
  476. package/script/methods/findCycles.js +369 -0
  477. package/script/methods/fuzzyClean.d.ts.map +1 -1
  478. package/script/methods/fuzzyClean.js +17 -136
  479. package/script/methods/fuzzyJoin.js +70 -16
  480. package/script/methods/getTypes.d.ts +1 -1
  481. package/script/methods/hdbscan.d.ts +5 -0
  482. package/script/methods/hdbscan.d.ts.map +1 -0
  483. package/script/methods/hdbscan.js +214 -0
  484. package/script/methods/loadArray.d.ts.map +1 -1
  485. package/script/methods/loadArray.js +2 -19
  486. package/script/methods/mahalanobis.d.ts +5 -0
  487. package/script/methods/mahalanobis.d.ts.map +1 -0
  488. package/script/methods/mahalanobis.js +98 -0
  489. package/script/methods/neighbors.d.ts +9 -0
  490. package/script/methods/neighbors.d.ts.map +1 -0
  491. package/script/methods/neighbors.js +120 -0
  492. package/script/methods/normalizeVector.d.ts +5 -0
  493. package/script/methods/normalizeVector.d.ts.map +1 -0
  494. package/script/methods/normalizeVector.js +138 -0
  495. package/script/methods/paths.d.ts +12 -0
  496. package/script/methods/paths.d.ts.map +1 -0
  497. package/script/methods/paths.js +326 -0
  498. package/script/methods/reachable.d.ts +11 -0
  499. package/script/methods/reachable.d.ts.map +1 -0
  500. package/script/methods/reachable.js +170 -0
  501. package/script/methods/rowToVector.d.ts +5 -0
  502. package/script/methods/rowToVector.d.ts.map +1 -0
  503. package/script/methods/rowToVector.js +83 -0
  504. package/script/methods/shortestPath.d.ts +12 -0
  505. package/script/methods/shortestPath.d.ts.map +1 -0
  506. package/script/methods/shortestPath.js +376 -0
  507. package/script/methods/topologicalSort.d.ts +7 -0
  508. package/script/methods/topologicalSort.d.ts.map +1 -0
  509. package/script/methods/topologicalSort.js +170 -0
  510. package/script/methods/umap.d.ts +5 -0
  511. package/script/methods/umap.d.ts.map +1 -0
  512. package/script/methods/umap.js +162 -0
  513. package/script/methods/updateWithJS.js +9 -21
@@ -1,12 +1,13 @@
1
1
  import quoteIdentifier from "../helpers/quoteIdentifier.js";
2
+ import { DuckDBListValue } from "@duckdb/node-api";
2
3
  import mergeOptions from "../helpers/mergeOptions.js";
3
4
  import queryDB from "../helpers/queryDB.js";
4
5
  import queueOp from "../helpers/queueOp.js";
5
6
  import buildFuzzyMatchSql from "../helpers/buildFuzzyMatchSql.js";
7
+ import selectFuzzyReplacements from "../helpers/selectFuzzyReplacements.js";
6
8
  export default function fuzzyClean(table, column, newColumn, threshold, options = {}) {
7
- // The clustering runs in JS over the fuzzy pairs read from the table, so
8
- // fuzzyClean can't be expressed as a single SELECT over its input: it
9
- // executes as a barrier.
9
+ // This implementation clusters fuzzy pairs in JS and writes the mapping
10
+ // back to DuckDB, so it executes as a barrier.
10
11
  options = structuredClone(options);
11
12
  queueOp(table, {
12
13
  kind: "barrier",
@@ -57,149 +58,29 @@ async function executeFuzzyClean(table, column, newColumn, threshold, options =
57
58
  }
58
59
  return;
59
60
  }
60
- // Build count map from the pairs — no separate query needed.
61
- const countMap = new Map();
62
- for (const { left_value, left_cnt, right_value, right_cnt } of pairs) {
63
- countMap.set(left_value, Number(left_cnt));
64
- countMap.set(right_value, Number(right_cnt));
65
- }
66
- // Union-Find — only over values that actually participate in a pair.
67
- const parent = new Map();
68
- const find = (x) => {
69
- if (!parent.has(x))
70
- parent.set(x, x);
71
- if (parent.get(x) !== x)
72
- parent.set(x, find(parent.get(x)));
73
- return parent.get(x);
74
- };
75
- const union = (a, b) => {
76
- const ra = find(a);
77
- const rb = find(b);
78
- if (ra !== rb)
79
- parent.set(ra, rb);
80
- };
81
- for (const v of countMap.keys())
82
- find(v);
83
- for (const { left_value, right_value } of pairs) {
84
- union(left_value, right_value);
85
- }
86
- // Group values by their cluster root.
87
- const clusters = new Map();
88
- for (const v of countMap.keys()) {
89
- const root = find(v);
90
- if (!clusters.has(root))
91
- clusters.set(root, []);
92
- clusters.get(root).push(v);
93
- }
94
- // Pick the canonical value for each cluster.
95
- const replacement = new Map();
96
- for (const members of clusters.values()) {
97
- if (members.length === 1)
98
- continue; // All pairs are already canonical — skip.
99
- // Score sums and per-member max scores are computed lazily — only when
100
- // actually needed as a primary criterion or tie-breaker.
101
- //
102
- // scoreSum: total similarity to all other cluster members (used by
103
- // "mostCentral" as primary, and as tie-breaker for all strategies).
104
- // scoreMax: highest single pairwise score (used by "maxScore" as primary).
105
- let scoreSum = null;
106
- const getScoreSum = () => {
107
- if (scoreSum === null) {
108
- scoreSum = new Map(members.map((m) => [m, 0]));
109
- for (const { left_value, right_value, score } of pairs) {
110
- if (scoreSum.has(left_value) && scoreSum.has(right_value)) {
111
- scoreSum.set(left_value, (scoreSum.get(left_value) ?? 0) + score);
112
- scoreSum.set(right_value, (scoreSum.get(right_value) ?? 0) + score);
113
- }
114
- }
115
- }
116
- return scoreSum;
117
- };
118
- let scoreMax = null;
119
- const getScoreMax = () => {
120
- if (scoreMax === null) {
121
- scoreMax = new Map(members.map((m) => [m, 0]));
122
- for (const { left_value, right_value, score } of pairs) {
123
- if (scoreMax.has(left_value) && scoreMax.has(right_value)) {
124
- scoreMax.set(left_value, Math.max(scoreMax.get(left_value) ?? 0, score));
125
- scoreMax.set(right_value, Math.max(scoreMax.get(right_value) ?? 0, score));
126
- }
127
- }
128
- }
129
- return scoreMax;
130
- };
131
- // Sum-based comparator: highest total similarity, then alphabetical.
132
- const byScore = (a, b) => {
133
- const sum = getScoreSum();
134
- const sa = sum.get(a) ?? 0;
135
- const sb = sum.get(b) ?? 0;
136
- if (sa !== sb)
137
- return sa > sb ? a : b;
138
- return a <= b ? a : b; // alphabetical tie-break
139
- };
140
- // Max-based comparator: highest single-pair score, then sum, then alphabetical.
141
- const byMaxScore = (a, b) => {
142
- const mx = getScoreMax();
143
- const ma = mx.get(a) ?? 0;
144
- const mb = mx.get(b) ?? 0;
145
- if (ma !== mb)
146
- return ma > mb ? a : b;
147
- return byScore(a, b); // sum then alphabetical tie-break
148
- };
149
- let canonical;
150
- if (strategy === "longestString") {
151
- canonical = members.reduce((a, b) => {
152
- if (a.length !== b.length)
153
- return a.length > b.length ? a : b;
154
- return byScore(a, b);
155
- });
156
- }
157
- else if (strategy === "shortestString") {
158
- canonical = members.reduce((a, b) => {
159
- if (a.length !== b.length)
160
- return a.length < b.length ? a : b;
161
- return byScore(a, b);
162
- });
163
- }
164
- else if (strategy === "mostCommon") {
165
- canonical = members.reduce((a, b) => {
166
- const ca = countMap.get(a) ?? 0;
167
- const cb = countMap.get(b) ?? 0;
168
- if (ca !== cb)
169
- return ca > cb ? a : b;
170
- return byScore(a, b);
171
- });
172
- }
173
- else if (strategy === "mostCentral") {
174
- // Most central string — highest total similarity to all other cluster members.
175
- canonical = members.reduce((a, b) => byScore(a, b));
176
- }
177
- else {
178
- // "maxScore": the string participating in the single highest-scoring pair.
179
- canonical = members.reduce((a, b) => byMaxScore(a, b));
180
- }
181
- for (const m of members) {
182
- if (m !== canonical)
183
- replacement.set(m, canonical);
184
- }
185
- }
61
+ const replacement = selectFuzzyReplacements(pairs, strategy);
186
62
  if (replacement.size === 0)
187
63
  return;
188
- // Use a VALUES-based CTE for the UPDATE so DuckDB can use a hash join
189
- // instead of evaluating a potentially huge CASE WHEN expression.
190
- const replacementEntries = [...replacement.entries()];
191
- const valuesList = replacementEntries.map(() => "(?, ?)").join(",\n ");
192
- const values = replacementEntries.flatMap(([from, to]) => [from, to]);
64
+ // Two bound lists keep the SQL and parameter count fixed as the mapping
65
+ // grows. Side-by-side UNNEST zips the equally sized lists into mapping rows,
66
+ // which DuckDB can hash-join to the original table.
67
+ const values = [
68
+ new DuckDBListValue([...replacement.keys()]),
69
+ new DuckDBListValue([...replacement.values()]),
70
+ ];
71
+ const mapping = `WITH mapping(original, canonical) AS (
72
+ SELECT UNNEST(?::VARCHAR[]), UNNEST(?::VARCHAR[])
73
+ )`;
193
74
  const query = newColumn !== column
194
75
  ? `ALTER TABLE ${quoteIdentifier(table.name)} ADD ${quoteIdentifier(newColumn)} VARCHAR;
195
76
  UPDATE ${quoteIdentifier(table.name)}
196
77
  SET ${quoteIdentifier(newColumn)} = ${quoteIdentifier(column)};
197
- WITH mapping(original, canonical) AS (VALUES ${valuesList})
78
+ ${mapping}
198
79
  UPDATE ${quoteIdentifier(table.name)}
199
80
  SET ${quoteIdentifier(newColumn)} = m.canonical
200
81
  FROM mapping m
201
82
  WHERE ${quoteIdentifier(table.name)}.${quoteIdentifier(newColumn)} = m.original`
202
- : `WITH mapping(original, canonical) AS (VALUES ${valuesList})
83
+ : `${mapping}
203
84
  UPDATE ${quoteIdentifier(table.name)}
204
85
  SET ${quoteIdentifier(column)} = m.canonical
205
86
  FROM mapping m
@@ -48,17 +48,7 @@ async function executeFuzzyJoin(leftTable, rightTable, outputTable, leftColumn,
48
48
  }
49
49
  const method = options.method ?? "ratio";
50
50
  const similarityColumn = options.similarityColumn;
51
- // The right table's copy of a column shared with the left table (only
52
- // rightColumn can be shared, checked above) is excluded from the SELECT
53
- // directly, instead of dropping its _1 duplicate with a rewrite after the
54
- // join.
55
- const rightSelect = rightCols
56
- .filter((d) => !leftCols.includes(d))
57
- .map((d) => `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)}`)
58
- .join(", ");
59
- const sql = `INSTALL rapidfuzz FROM community; LOAD rapidfuzz;\n` +
60
- fuzzyJoinQuery(leftTable.name, leftColumn, rightTable.name, rightColumn, method, threshold, outputTable.name, similarityColumn, rightSelect, options.prefilterPrefixLength);
61
- await queryDB(leftTable, sql, mergeOptions(leftTable, {
51
+ const queryOptions = mergeOptions(leftTable, {
62
52
  table: outputTable.name,
63
53
  method: "fuzzyJoin()",
64
54
  parameters: {
@@ -68,26 +58,90 @@ async function executeFuzzyJoin(leftTable, rightTable, outputTable, leftColumn,
68
58
  threshold,
69
59
  options,
70
60
  },
71
- }));
61
+ });
62
+ const deduplicate = await shouldDeduplicateFuzzyJoin(leftTable, rightTable, leftColumn, rightColumn, queryOptions);
63
+ // The right table's copy of a column shared with the left table (only
64
+ // rightColumn can be shared, checked above) is excluded from the SELECT
65
+ // directly, instead of dropping its _1 duplicate with a rewrite after the
66
+ // join.
67
+ const rightSelect = rightCols
68
+ .filter((d) => !leftCols.includes(d))
69
+ .map((d) => `${quoteIdentifier(rightTable.name)}.${quoteIdentifier(d)}`)
70
+ .join(", ");
71
+ const sql = `INSTALL rapidfuzz FROM community; LOAD rapidfuzz;\n` +
72
+ fuzzyJoinQuery(leftTable.name, leftColumn, rightTable.name, rightColumn, method, threshold, outputTable.name, similarityColumn, rightSelect, options.prefilterPrefixLength, deduplicate);
73
+ await queryDB(leftTable, sql, queryOptions);
72
74
  }
73
- function fuzzyJoinQuery(leftTable, leftColumn, rightTable, rightColumn, method, threshold, outputTable, similarityColumn, rightSelect, prefilterPrefixLength) {
75
+ async function shouldDeduplicateFuzzyJoin(leftTable, rightTable, leftColumn, rightColumn, queryOptions) {
76
+ const left = quoteIdentifier(leftTable.name);
77
+ const right = quoteIdentifier(rightTable.name);
78
+ const counts = (await queryDB(leftTable, `SELECT (SELECT COUNT(*) FROM ${left}) AS left_count,
79
+ (SELECT COUNT(*) FROM ${right}) AS right_count`, { ...queryOptions, returnData: true }))[0];
80
+ const leftCount = Number(counts.left_count);
81
+ const rightCount = Number(counts.right_count);
82
+ const comparisons = leftCount * rightCount;
83
+ // Avoid distinct scans for small joins and short lookup tables. For larger
84
+ // joins, require at least a twofold reduction to pay for grouping and rejoining.
85
+ if (comparisons < 100_000 || Math.min(leftCount, rightCount) < 32) {
86
+ return false;
87
+ }
88
+ const distinct = (await queryDB(leftTable, `SELECT
89
+ (SELECT COUNT(DISTINCT ENCODE(${quoteIdentifier(leftColumn)})) FROM ${left}) AS left_count,
90
+ (SELECT COUNT(DISTINCT ENCODE(${quoteIdentifier(rightColumn)})) FROM ${right}) AS right_count`, { ...queryOptions, returnData: true }))[0];
91
+ return Number(distinct.left_count) * Number(distinct.right_count) <=
92
+ comparisons / 2;
93
+ }
94
+ function fuzzyJoinQuery(leftTable, leftColumn, rightTable, rightColumn, method, threshold, outputTable, similarityColumn, rightSelect, prefilterPrefixLength, deduplicate = false) {
74
95
  const leftExpression = `${quoteIdentifier(leftTable)}.${quoteIdentifier(leftColumn)}`;
75
96
  const rightExpression = `${quoteIdentifier(rightTable)}.${quoteIdentifier(rightColumn)}`;
76
97
  const { scoreExpression, condition } = buildFuzzyMatchSql(leftExpression, rightExpression, method, threshold, { decimals: 2, prefilterPrefixLength });
98
+ let cte = "";
99
+ let from = `FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(rightTable)} ON ${condition}`;
100
+ let score = scoreExpression;
101
+ if (deduplicate) {
102
+ const matches = quoteIdentifier(`__sda_fuzzy_matches_${crypto.randomUUID().replaceAll("-", "")}`);
103
+ const match = buildFuzzyMatchSql("l.value", "r.value", method, threshold, { decimals: 2, prefilterPrefixLength });
104
+ // Keep the original value's collation for prefix matching, but use byte
105
+ // keys for deduplication and expansion: fuzzy scores distinguish case even
106
+ // when an input column has a case-insensitive collation.
107
+ cte = `WITH ${matches} AS MATERIALIZED (
108
+ SELECT l.key AS left_key, r.key AS right_key,
109
+ ${match.scoreExpression} AS score
110
+ FROM (
111
+ SELECT DISTINCT ${quoteIdentifier(leftColumn)} AS value,
112
+ ENCODE(${quoteIdentifier(leftColumn)}) AS key
113
+ FROM ${quoteIdentifier(leftTable)}
114
+ WHERE ${quoteIdentifier(leftColumn)} IS NOT NULL
115
+ ) l
116
+ INNER JOIN (
117
+ SELECT DISTINCT ${quoteIdentifier(rightColumn)} AS value,
118
+ ENCODE(${quoteIdentifier(rightColumn)}) AS key
119
+ FROM ${quoteIdentifier(rightTable)}
120
+ WHERE ${quoteIdentifier(rightColumn)} IS NOT NULL
121
+ ) r ON ${match.condition}
122
+ )`;
123
+ from = `FROM ${quoteIdentifier(leftTable)}
124
+ LEFT JOIN ${matches} ON ENCODE(${leftExpression}) = ${matches}.left_key
125
+ LEFT JOIN ${quoteIdentifier(rightTable)}
126
+ ON ENCODE(${rightExpression}) = ${matches}.right_key`;
127
+ score = `${matches}.score`;
128
+ }
77
129
  if (similarityColumn) {
78
130
  return `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable)} AS
131
+ ${cte}
79
132
  SELECT * EXCLUDE ("_sda_score"), "_sda_score" AS ${quoteIdentifier(similarityColumn)}
80
133
  FROM (
81
- SELECT ${quoteIdentifier(leftTable)}.*, ${rightSelect}, ${scoreExpression} AS "_sda_score"
82
- FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(rightTable)} ON ${condition}
134
+ SELECT ${quoteIdentifier(leftTable)}.*, ${rightSelect}, ${score} AS "_sda_score"
135
+ ${from}
83
136
  ) _sda
84
137
  ORDER BY ${quoteIdentifier(leftColumn)}, "_sda_score" DESC;\n`;
85
138
  }
86
139
  return `CREATE OR REPLACE TABLE ${quoteIdentifier(outputTable)} AS
140
+ ${cte}
87
141
  SELECT *
88
142
  FROM (
89
143
  SELECT ${quoteIdentifier(leftTable)}.*, ${rightSelect}
90
- FROM ${quoteIdentifier(leftTable)} LEFT JOIN ${quoteIdentifier(rightTable)} ON ${condition}
144
+ ${from}
91
145
  ) _sda
92
146
  ORDER BY ${quoteIdentifier(leftColumn)}, ${quoteIdentifier(rightColumn)};\n`;
93
147
  }
@@ -1,5 +1,5 @@
1
1
  import type SimpleTable from "../class/SimpleTable.js";
2
2
  export default function getTypes(simpleTable: SimpleTable): Promise<{
3
- [key: string]: string;
3
+ [k: string]: string;
4
4
  }>;
5
5
  //# sourceMappingURL=getTypes.d.ts.map
@@ -0,0 +1,5 @@
1
+ import type SimpleTable from "../class/SimpleTable.js";
2
+ type Options = NonNullable<Parameters<SimpleTable["hdbscan"]>[2]>;
3
+ export default function hdbscan(table: SimpleTable, columns: string | string[], newColumn: string, options?: Options): void;
4
+ export {};
5
+ //# sourceMappingURL=hdbscan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hdbscan.d.ts","sourceRoot":"","sources":["../../src/methods/hdbscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAWvD,KAAK,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAElE,MAAM,CAAC,OAAO,UAAU,OAAO,CAC7B,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,OAAY,GACpB,IAAI,CASN"}
@@ -0,0 +1,208 @@
1
+ import { DOUBLE, INTEGER, VARCHAR } from "@duckdb/node-api";
2
+ import appendColumnBatches from "../helpers/appendColumnBatches.js";
3
+ import buildApproximateMutualReachabilityMst from "../helpers/buildApproximateMutualReachabilityMst.js";
4
+ import buildExactMutualReachabilityMst from "../helpers/buildExactMutualReachabilityMst.js";
5
+ import clusterHdbscan from "../helpers/clusterHdbscan.js";
6
+ import foldIdentifier from "../helpers/foldIdentifier.js";
7
+ import prepareNumericFeatures from "../helpers/prepareNumericFeatures.js";
8
+ import publishPreparedColumns from "../helpers/publishPreparedColumns.js";
9
+ import queueOp from "../helpers/queueOp.js";
10
+ import quoteIdentifier from "../helpers/quoteIdentifier.js";
11
+ export default function hdbscan(table, columns, newColumn, options = {}) {
12
+ const selected = typeof columns === "string" ? columns : [...columns];
13
+ const settings = structuredClone(options);
14
+ queueOp(table, {
15
+ kind: "barrier",
16
+ method: "hdbscan()",
17
+ parameters: { columns: selected, newColumn, options: settings },
18
+ execute: () => execute(table, selected, newColumn, settings),
19
+ });
20
+ }
21
+ async function execute(table, columns, newColumn, options) {
22
+ const { minClusterSize = 5, metric = "euclidean", allowSingleCluster = false, approximate = false, membershipScoreColumn, outlierScoreColumn, } = options;
23
+ const minSamples = options.minSamples ?? minClusterSize;
24
+ if (typeof newColumn !== "string") {
25
+ throw new Error("hdbscan() newColumn must be a string.");
26
+ }
27
+ if (!Number.isSafeInteger(minClusterSize) || minClusterSize < 2) {
28
+ throw new Error("hdbscan() minClusterSize must be a safe integer of at least 2.");
29
+ }
30
+ if (!Number.isSafeInteger(minSamples) || minSamples < 1) {
31
+ throw new Error("hdbscan() minSamples must be a safe integer of at least 1.");
32
+ }
33
+ if (!["euclidean", "cosine"].includes(metric)) {
34
+ throw new Error('hdbscan() metric must be "euclidean" or "cosine".');
35
+ }
36
+ if (typeof allowSingleCluster !== "boolean") {
37
+ throw new Error("hdbscan() allowSingleCluster must be a boolean.");
38
+ }
39
+ if (typeof approximate !== "boolean") {
40
+ throw new Error("hdbscan() approximate must be a boolean.");
41
+ }
42
+ if (membershipScoreColumn !== undefined &&
43
+ typeof membershipScoreColumn !== "string") {
44
+ throw new Error("hdbscan() membershipScoreColumn must be a string.");
45
+ }
46
+ if (outlierScoreColumn !== undefined &&
47
+ typeof outlierScoreColumn !== "string") {
48
+ throw new Error("hdbscan() outlierScoreColumn must be a string.");
49
+ }
50
+ const sourceColumns = Object.keys(await table.getTypes());
51
+ const outputNames = [newColumn, membershipScoreColumn, outlierScoreColumn]
52
+ .filter((name) => name !== undefined);
53
+ validateOutputNames(sourceColumns, outputNames);
54
+ const prepared = await prepareNumericFeatures(table, typeof columns === "string"
55
+ ? { kind: "vector", column: columns }
56
+ : { kind: "scalars", columns }, { method: "hdbscan()" });
57
+ const connection = table.connection;
58
+ const suffix = crypto.randomUUID().replaceAll("-", "");
59
+ const name = (part) => `__sda_hdbscan_${suffix}_${part}`;
60
+ const names = {
61
+ rows: name("rows"),
62
+ neighbors: name("neighbors"),
63
+ search: name("search"),
64
+ hnsw: name("hnsw"),
65
+ candidates: name("candidates"),
66
+ coreDistances: name("core_distances"),
67
+ frontier: name("frontier"),
68
+ edges: name("edges"),
69
+ components: name("components"),
70
+ representatives: name("representatives"),
71
+ componentPairs: name("component_pairs"),
72
+ bridgeCandidates: name("bridge_candidates"),
73
+ mst: name("mst"),
74
+ result: name("result"),
75
+ };
76
+ try {
77
+ if (prepared.rowCount < 2) {
78
+ throw new Error(`hdbscan() requires at least 2 rows, but the input has ${prepared.rowCount}.`);
79
+ }
80
+ if (prepared.rowCount > 0x40000000) {
81
+ throw new Error("hdbscan() supports at most 1073741824 rows because its 2*n-1 hierarchy nodes use signed INTEGER identifiers.");
82
+ }
83
+ if (minSamples >= prepared.rowCount) {
84
+ const defaulted = options.minSamples === undefined
85
+ ? " (defaulted from minClusterSize)"
86
+ : "";
87
+ throw new Error(`hdbscan() minSamples is ${minSamples}${defaulted}, but ${prepared.rowCount} rows provide at most ${prepared.rowCount - 1} other point${prepared.rowCount === 2 ? "" : "s"}. Set minSamples between 1 and ${prepared.rowCount - 1}, or provide at least ${minSamples + 1} rows.`);
88
+ }
89
+ if (minClusterSize > prepared.rowCount) {
90
+ throw new Error(`hdbscan() minClusterSize is ${minClusterSize}, but the input has ${prepared.rowCount} rows. Set minClusterSize between 2 and ${prepared.rowCount}, or provide more rows.`);
91
+ }
92
+ const q = quoteIdentifier;
93
+ await connection.run(`CREATE TEMP TABLE ${q(names.rows)} AS
94
+ SELECT ${q(prepared.rowIdColumn)}::INTEGER AS vertex,
95
+ ${q(prepared.vectorColumn)} AS vec
96
+ FROM ${q(prepared.relation)}
97
+ ORDER BY ${q(prepared.rowIdColumn)}`);
98
+ if (approximate) {
99
+ await buildApproximateMutualReachabilityMst(connection, {
100
+ count: prepared.rowCount,
101
+ dimensions: prepared.dimensions,
102
+ minSamples,
103
+ }, { metric }, {
104
+ rows: names.rows,
105
+ neighbors: names.neighbors,
106
+ search: names.search,
107
+ hnsw: names.hnsw,
108
+ candidates: names.candidates,
109
+ coreDistances: names.coreDistances,
110
+ edges: names.edges,
111
+ components: names.components,
112
+ representatives: names.representatives,
113
+ componentPairs: names.componentPairs,
114
+ bridgeCandidates: names.bridgeCandidates,
115
+ mst: names.mst,
116
+ });
117
+ }
118
+ else {
119
+ await buildExactMutualReachabilityMst(connection, { count: prepared.rowCount, minSamples }, { metric }, {
120
+ rows: q(names.rows),
121
+ coreDistances: q(names.coreDistances),
122
+ frontier: q(names.frontier),
123
+ mst: q(names.mst),
124
+ });
125
+ }
126
+ const result = await clusterHdbscan(connection, q(names.mst), {
127
+ count: prepared.rowCount,
128
+ minClusterSize,
129
+ allowSingleCluster,
130
+ });
131
+ const labelColumn = "label";
132
+ const membershipColumn = "membership";
133
+ const gloshColumn = "glosh";
134
+ const resultColumns = [
135
+ "row_id INTEGER",
136
+ `${labelColumn} VARCHAR`,
137
+ membershipScoreColumn === undefined
138
+ ? undefined
139
+ : `${membershipColumn} DOUBLE`,
140
+ outlierScoreColumn === undefined ? undefined : `${gloshColumn} DOUBLE`,
141
+ ].filter((definition) => definition !== undefined);
142
+ await connection.run(`CREATE TEMP TABLE ${q(names.result)} (${resultColumns.join(",")})`);
143
+ const outputTypes = [
144
+ INTEGER,
145
+ VARCHAR,
146
+ ...(membershipScoreColumn === undefined ? [] : [DOUBLE]),
147
+ ...(outlierScoreColumn === undefined ? [] : [DOUBLE]),
148
+ ];
149
+ await appendColumnBatches(connection, names.result, outputTypes, prepared.rowCount, (column, start, end) => {
150
+ if (column === 0) {
151
+ return Array.from({ length: end - start }, (_, offset) => start + offset);
152
+ }
153
+ if (column === 1) {
154
+ return Array.from(result.labels.subarray(start, end), (label) => label < 0 ? "noise" : `cluster-${label}`);
155
+ }
156
+ const membershipIndex = membershipScoreColumn === undefined ? -1 : 2;
157
+ return Array.from(column === membershipIndex
158
+ ? result.probabilities.subarray(start, end)
159
+ : result.outlierScores.subarray(start, end));
160
+ });
161
+ const publicationOutputs = [{
162
+ name: newColumn,
163
+ expression: `r.${q(labelColumn)}`,
164
+ }];
165
+ if (membershipScoreColumn !== undefined) {
166
+ publicationOutputs.push({
167
+ name: membershipScoreColumn,
168
+ expression: `r.${q(membershipColumn)}`,
169
+ });
170
+ }
171
+ if (outlierScoreColumn !== undefined) {
172
+ publicationOutputs.push({
173
+ name: outlierScoreColumn,
174
+ expression: `r.${q(gloshColumn)}`,
175
+ });
176
+ }
177
+ await publishPreparedColumns(table, prepared, {
178
+ method: "hdbscan()",
179
+ parameters: { columns, newColumn, options },
180
+ result: { relation: names.result, rowIdColumn: "row_id" },
181
+ outputs: publicationOutputs,
182
+ });
183
+ }
184
+ finally {
185
+ for (const relation of Object.entries(names).reverse().flatMap(([key, value]) => key === "hnsw" ? [] : [value])) {
186
+ await connection.run(`DROP TABLE IF EXISTS ${quoteIdentifier(relation)}`);
187
+ }
188
+ await prepared.cleanup();
189
+ }
190
+ }
191
+ function validateOutputNames(sourceColumns, outputNames) {
192
+ const seen = new Map();
193
+ for (const name of outputNames) {
194
+ if (name.length === 0 || name.includes("\0")) {
195
+ throw new Error("hdbscan() output column names must be non-empty strings without null characters.");
196
+ }
197
+ const folded = foldIdentifier(name);
198
+ const source = sourceColumns.find((column) => foldIdentifier(column) === folded);
199
+ if (source !== undefined) {
200
+ throw new Error(`hdbscan() cannot create ${quoteIdentifier(name)} because that source column already exists. Remove it first or choose different output names.`);
201
+ }
202
+ const duplicate = seen.get(folded);
203
+ if (duplicate !== undefined) {
204
+ throw new Error(`hdbscan() output columns ${quoteIdentifier(duplicate)} and ${quoteIdentifier(name)} refer to the same column. Choose distinct output names.`);
205
+ }
206
+ seen.set(folded, name);
207
+ }
208
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"loadArray.d.ts","sourceRoot":"","sources":["../../src/methods/loadArray.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAKvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,OAAO,GAAE,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAM,QAiBnE;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,WAAW,EAAE,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,WAAW,GAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAO,EAC3C,0BAA0B,UAAQ,GACjC,aAAa,CAsHf;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,aAAa,iBA4ExB"}
1
+ {"version":3,"file":"loadArray.d.ts","sourceRoot":"","sources":["../../src/methods/loadArray.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAM1B,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAKvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,OAAO,GAAE,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAM,QAiBnE;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,WAAW,EAAE,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,WAAW,GAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAO,EAC3C,0BAA0B,UAAQ,GACjC,aAAa,CAsHf;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,aAAa,iBA+DxB"}
@@ -1,4 +1,5 @@
1
- import { arrayValue, DuckDBDataChunk, DuckDBDateValue, DuckDBTimestampTZValue, DuckDBTimestampValue, DuckDBTimeValue, } from "@duckdb/node-api";
1
+ import { arrayValue, DuckDBDateValue, DuckDBTimestampTZValue, DuckDBTimestampValue, DuckDBTimeValue, } from "@duckdb/node-api";
2
+ import appendColumnBatches from "../helpers/appendColumnBatches.js";
2
3
  import prepareGeometry from "../helpers/prepareGeometry.js";
3
4
  import prepareJSON from "../helpers/prepareJSON.js";
4
5
  import geometryFromJSON from "../helpers/geometryFromJSON.js";
@@ -136,25 +137,7 @@ export async function executePreparedArray(simpleTable, prepared) {
136
137
  }
137
138
  try {
138
139
  await simpleTable.sdb.customQuery(`CREATE ${needsConversion ? "TEMP" : "OR REPLACE"} TABLE ${quoteIdentifier(staged)}(${keys.map((key, i) => `${quoteIdentifier(key)} ${storageTypes[i]}`).join(", ")})`);
139
- const appender = await simpleTable.connection
140
- .createAppender(staged);
141
- try {
142
- const duckDBTypes = storageTypes.map((d) => parseDuckDBType(d));
143
- // The maximum capacity of a DuckDB data chunk is 2048 rows.
144
- const chunkSize = 2000;
145
- for (let start = 0; start < rowCount; start += chunkSize) {
146
- const end = Math.min(start + chunkSize, rowCount);
147
- const dataChunk = DuckDBDataChunk.create(duckDBTypes, end - start);
148
- for (let i = 0; i < keys.length; i++) {
149
- dataChunk.setColumnValues(i, columnsData[i].slice(start, end));
150
- }
151
- appender.appendDataChunk(dataChunk);
152
- }
153
- appender.flushSync();
154
- }
155
- finally {
156
- appender.closeSync();
157
- }
140
+ await appendColumnBatches(simpleTable.connection, staged, storageTypes.map((type) => parseDuckDBType(type)), rowCount, (column, start, end) => columnsData[column].slice(start, end));
158
141
  if (!needsConversion)
159
142
  return;
160
143
  // CTAS is atomic: conversion must finish before the destination is replaced.
@@ -0,0 +1,5 @@
1
+ import type SimpleTable from "../class/SimpleTable.js";
2
+ type Options = NonNullable<Parameters<SimpleTable["mahalanobis"]>[3]>;
3
+ export default function mahalanobis(table: SimpleTable, columns: string | string[], referencePoint: number[], newColumn: string, options?: Options): void;
4
+ export {};
5
+ //# sourceMappingURL=mahalanobis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mahalanobis.d.ts","sourceRoot":"","sources":["../../src/methods/mahalanobis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AASvD,KAAK,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtE,MAAM,CAAC,OAAO,UAAU,WAAW,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAC1B,cAAc,EAAE,MAAM,EAAE,EACxB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,OAAY,GACpB,IAAI,CAyBN"}