semanticdb-v2 2.0.0-alpha.1

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 (306) hide show
  1. package/README.md +448 -0
  2. package/dist/cache/expiry.d.ts +5 -0
  3. package/dist/cache/expiry.js +1 -0
  4. package/dist/cache/identity.d.ts +3 -0
  5. package/dist/cache/identity.js +1 -0
  6. package/dist/cache/index.d.ts +3 -0
  7. package/dist/cache/redis-query-cache.d.ts +37 -0
  8. package/dist/cache/redis-query-cache.js +1 -0
  9. package/dist/cache/serialization.d.ts +3 -0
  10. package/dist/cache/serialization.js +1 -0
  11. package/dist/cache/types.d.ts +27 -0
  12. package/dist/calendar/constants.d.ts +7 -0
  13. package/dist/calendar/constants.js +1 -0
  14. package/dist/calendar/index.d.ts +6 -0
  15. package/dist/calendar/provider-relation-store.d.ts +9 -0
  16. package/dist/calendar/provider-relation-store.js +1 -0
  17. package/dist/calendar/resolver.d.ts +10 -0
  18. package/dist/calendar/resolver.js +1 -0
  19. package/dist/calendar/system-schemas.d.ts +3 -0
  20. package/dist/calendar/system-schemas.js +1 -0
  21. package/dist/calendar/types.d.ts +31 -0
  22. package/dist/compatibility/index.d.ts +2 -0
  23. package/dist/compatibility/logicform.d.ts +13 -0
  24. package/dist/compatibility/logicform.js +1 -0
  25. package/dist/compiler/compile-cte.d.ts +12 -0
  26. package/dist/compiler/compile-cte.js +1 -0
  27. package/dist/compiler/compile-plan.d.ts +5 -0
  28. package/dist/compiler/compile-plan.js +1 -0
  29. package/dist/compiler/index.d.ts +4 -0
  30. package/dist/compiler/shorten-sql.d.ts +2 -0
  31. package/dist/compiler/shorten-sql.js +2 -0
  32. package/dist/compiler/types.d.ts +5 -0
  33. package/dist/custom-functions/custom-functions.d.ts +6 -0
  34. package/dist/custom-functions/custom-functions.js +1 -0
  35. package/dist/custom-functions/index.d.ts +3 -0
  36. package/dist/custom-functions/operator-adapter.d.ts +12 -0
  37. package/dist/custom-functions/operator-adapter.js +1 -0
  38. package/dist/custom-functions/types.d.ts +62 -0
  39. package/dist/errors.d.ts +5 -0
  40. package/dist/errors.js +1 -0
  41. package/dist/executor/compatibility.d.ts +6 -0
  42. package/dist/executor/compatibility.js +1 -0
  43. package/dist/executor/components.d.ts +9 -0
  44. package/dist/executor/components.js +1 -0
  45. package/dist/executor/connection-registry.d.ts +12 -0
  46. package/dist/executor/connection-registry.js +1 -0
  47. package/dist/executor/evaluate.d.ts +4 -0
  48. package/dist/executor/evaluate.js +1 -0
  49. package/dist/executor/execute-query.d.ts +13 -0
  50. package/dist/executor/execute-query.js +1 -0
  51. package/dist/executor/execute.d.ts +4 -0
  52. package/dist/executor/execute.js +1 -0
  53. package/dist/executor/fetch-entities.d.ts +26 -0
  54. package/dist/executor/fetch-entities.js +1 -0
  55. package/dist/executor/index.d.ts +3 -0
  56. package/dist/executor/result-hydrator/entity-loader.d.ts +6 -0
  57. package/dist/executor/result-hydrator/entity-loader.js +1 -0
  58. package/dist/executor/result-hydrator/format-values.d.ts +4 -0
  59. package/dist/executor/result-hydrator/format-values.js +1 -0
  60. package/dist/executor/result-hydrator/hydrate-result.d.ts +4 -0
  61. package/dist/executor/result-hydrator/hydrate-result.js +1 -0
  62. package/dist/executor/result-hydrator/index.d.ts +2 -0
  63. package/dist/executor/result-hydrator/missing-entity.d.ts +3 -0
  64. package/dist/executor/result-hydrator/missing-entity.js +1 -0
  65. package/dist/executor/result-hydrator/populate-entities.d.ts +3 -0
  66. package/dist/executor/result-hydrator/populate-entities.js +1 -0
  67. package/dist/executor/result-hydrator/types.d.ts +14 -0
  68. package/dist/executor/row-identity.d.ts +4 -0
  69. package/dist/executor/row-identity.js +1 -0
  70. package/dist/executor/types.d.ts +118 -0
  71. package/dist/index.d.ts +26 -0
  72. package/dist/index.js +1 -0
  73. package/dist/logicform-types.d.ts +125 -0
  74. package/dist/logicform-types.js +1 -0
  75. package/dist/normalizer/core.d.ts +19 -0
  76. package/dist/normalizer/core.js +1 -0
  77. package/dist/normalizer/default-pred-name.d.ts +6 -0
  78. package/dist/normalizer/default-pred-name.js +1 -0
  79. package/dist/normalizer/entity-id.d.ts +4 -0
  80. package/dist/normalizer/entity-id.js +1 -0
  81. package/dist/normalizer/groupby.d.ts +4 -0
  82. package/dist/normalizer/groupby.js +1 -0
  83. package/dist/normalizer/index.d.ts +3 -0
  84. package/dist/normalizer/normalize-logicform.d.ts +4 -0
  85. package/dist/normalizer/normalize-logicform.js +1 -0
  86. package/dist/normalizer/pagination.d.ts +2 -0
  87. package/dist/normalizer/pagination.js +1 -0
  88. package/dist/normalizer/pred-query-name.d.ts +1 -0
  89. package/dist/normalizer/pred-query-name.js +1 -0
  90. package/dist/normalizer/preds.d.ts +4 -0
  91. package/dist/normalizer/preds.js +1 -0
  92. package/dist/normalizer/query.d.ts +5 -0
  93. package/dist/normalizer/query.js +1 -0
  94. package/dist/normalizer/version.d.ts +3 -0
  95. package/dist/normalizer/version.js +1 -0
  96. package/dist/operators/builtins/abs.d.ts +2 -0
  97. package/dist/operators/builtins/abs.js +1 -0
  98. package/dist/operators/builtins/accumulate.d.ts +2 -0
  99. package/dist/operators/builtins/accumulate.js +1 -0
  100. package/dist/operators/builtins/add.d.ts +2 -0
  101. package/dist/operators/builtins/add.js +1 -0
  102. package/dist/operators/builtins/arithmetic.d.ts +3 -0
  103. package/dist/operators/builtins/arithmetic.js +1 -0
  104. package/dist/operators/builtins/average-per-period.d.ts +2 -0
  105. package/dist/operators/builtins/average-per-period.js +1 -0
  106. package/dist/operators/builtins/avg.d.ts +2 -0
  107. package/dist/operators/builtins/avg.js +1 -0
  108. package/dist/operators/builtins/case.d.ts +2 -0
  109. package/dist/operators/builtins/case.js +1 -0
  110. package/dist/operators/builtins/concat.d.ts +2 -0
  111. package/dist/operators/builtins/concat.js +1 -0
  112. package/dist/operators/builtins/count-distinct.d.ts +2 -0
  113. package/dist/operators/builtins/count-distinct.js +1 -0
  114. package/dist/operators/builtins/count.d.ts +2 -0
  115. package/dist/operators/builtins/count.js +1 -0
  116. package/dist/operators/builtins/date-bucket.d.ts +2 -0
  117. package/dist/operators/builtins/date-bucket.js +1 -0
  118. package/dist/operators/builtins/divide.d.ts +2 -0
  119. package/dist/operators/builtins/divide.js +1 -0
  120. package/dist/operators/builtins/index.d.ts +2 -0
  121. package/dist/operators/builtins/index.js +1 -0
  122. package/dist/operators/builtins/max.d.ts +2 -0
  123. package/dist/operators/builtins/max.js +1 -0
  124. package/dist/operators/builtins/min.d.ts +2 -0
  125. package/dist/operators/builtins/min.js +1 -0
  126. package/dist/operators/builtins/multiply.d.ts +2 -0
  127. package/dist/operators/builtins/multiply.js +1 -0
  128. package/dist/operators/builtins/newly.d.ts +2 -0
  129. package/dist/operators/builtins/newly.js +1 -0
  130. package/dist/operators/builtins/period-boundary.d.ts +2 -0
  131. package/dist/operators/builtins/period-boundary.js +1 -0
  132. package/dist/operators/builtins/period-difference.d.ts +2 -0
  133. package/dist/operators/builtins/period-difference.js +1 -0
  134. package/dist/operators/builtins/period-growth.d.ts +2 -0
  135. package/dist/operators/builtins/period-growth.js +1 -0
  136. package/dist/operators/builtins/period-name.d.ts +1 -0
  137. package/dist/operators/builtins/period-name.js +1 -0
  138. package/dist/operators/builtins/period-shift.d.ts +6 -0
  139. package/dist/operators/builtins/period-shift.js +1 -0
  140. package/dist/operators/builtins/rank.d.ts +2 -0
  141. package/dist/operators/builtins/rank.js +1 -0
  142. package/dist/operators/builtins/row-number.d.ts +2 -0
  143. package/dist/operators/builtins/row-number.js +1 -0
  144. package/dist/operators/builtins/share-of-total.d.ts +2 -0
  145. package/dist/operators/builtins/share-of-total.js +1 -0
  146. package/dist/operators/builtins/sql.d.ts +3 -0
  147. package/dist/operators/builtins/sql.js +1 -0
  148. package/dist/operators/builtins/substring.d.ts +2 -0
  149. package/dist/operators/builtins/substring.js +1 -0
  150. package/dist/operators/builtins/subtract.d.ts +2 -0
  151. package/dist/operators/builtins/subtract.js +1 -0
  152. package/dist/operators/builtins/sum.d.ts +2 -0
  153. package/dist/operators/builtins/sum.js +1 -0
  154. package/dist/operators/builtins/time-range.d.ts +13 -0
  155. package/dist/operators/builtins/time-range.js +1 -0
  156. package/dist/operators/groupby.d.ts +3 -0
  157. package/dist/operators/groupby.js +1 -0
  158. package/dist/operators/index.d.ts +7 -0
  159. package/dist/operators/index.js +1 -0
  160. package/dist/operators/registry.d.ts +10 -0
  161. package/dist/operators/registry.js +1 -0
  162. package/dist/operators/sql-expression.d.ts +1 -0
  163. package/dist/operators/sql-expression.js +1 -0
  164. package/dist/operators/types.d.ts +277 -0
  165. package/dist/permissions/index.d.ts +3 -0
  166. package/dist/permissions/permissions.d.ts +10 -0
  167. package/dist/permissions/permissions.js +1 -0
  168. package/dist/permissions/types.d.ts +12 -0
  169. package/dist/physical/clickhouse-provider.d.ts +44 -0
  170. package/dist/physical/clickhouse-provider.js +1 -0
  171. package/dist/physical/connection.d.ts +32 -0
  172. package/dist/physical/connection.js +1 -0
  173. package/dist/physical/display-query.d.ts +4 -0
  174. package/dist/physical/display-query.js +1 -0
  175. package/dist/physical/doris-provider.d.ts +9 -0
  176. package/dist/physical/doris-provider.js +1 -0
  177. package/dist/physical/index.d.ts +18 -0
  178. package/dist/physical/mysql-compatible-sql.d.ts +6 -0
  179. package/dist/physical/mysql-compatible-sql.js +1 -0
  180. package/dist/physical/mysql-protocol-provider.d.ts +34 -0
  181. package/dist/physical/mysql-protocol-provider.js +1 -0
  182. package/dist/physical/mysql-provider.d.ts +8 -0
  183. package/dist/physical/mysql-provider.js +1 -0
  184. package/dist/physical/oracle-provider.d.ts +53 -0
  185. package/dist/physical/oracle-provider.js +1 -0
  186. package/dist/physical/postgresql-provider.d.ts +37 -0
  187. package/dist/physical/postgresql-provider.js +1 -0
  188. package/dist/physical/provider.d.ts +40 -0
  189. package/dist/physical/snowflake-provider.d.ts +45 -0
  190. package/dist/physical/snowflake-provider.js +1 -0
  191. package/dist/physical/starrocks-provider.d.ts +9 -0
  192. package/dist/physical/starrocks-provider.js +1 -0
  193. package/dist/planner/build-lineage.d.ts +5 -0
  194. package/dist/planner/build-lineage.js +1 -0
  195. package/dist/planner/create-logical-plan.d.ts +15 -0
  196. package/dist/planner/create-logical-plan.js +1 -0
  197. package/dist/planner/index.d.ts +7 -0
  198. package/dist/planner/select-schema-mapping.d.ts +14 -0
  199. package/dist/planner/select-schema-mapping.js +1 -0
  200. package/dist/planner/semantics/index.d.ts +5 -0
  201. package/dist/planner/semantics/lifecycle/classification.d.ts +7 -0
  202. package/dist/planner/semantics/lifecycle/classification.js +1 -0
  203. package/dist/planner/semantics/lifecycle/index.d.ts +3 -0
  204. package/dist/planner/semantics/lifecycle/query-policy.d.ts +3 -0
  205. package/dist/planner/semantics/lifecycle/query-policy.js +1 -0
  206. package/dist/planner/semantics/lifecycle/rule.d.ts +2 -0
  207. package/dist/planner/semantics/lifecycle/rule.js +1 -0
  208. package/dist/planner/semantics/observation/classification.d.ts +3 -0
  209. package/dist/planner/semantics/observation/classification.js +1 -0
  210. package/dist/planner/semantics/observation/index.d.ts +4 -0
  211. package/dist/planner/semantics/observation/operator-policy.d.ts +11 -0
  212. package/dist/planner/semantics/observation/operator-policy.js +1 -0
  213. package/dist/planner/semantics/observation/rule.d.ts +2 -0
  214. package/dist/planner/semantics/observation/rule.js +1 -0
  215. package/dist/planner/semantics/observation/types.d.ts +3 -0
  216. package/dist/planner/semantics/registry-defaults.d.ts +2 -0
  217. package/dist/planner/semantics/registry-defaults.js +1 -0
  218. package/dist/planner/semantics/registry.d.ts +32 -0
  219. package/dist/planner/semantics/registry.js +1 -0
  220. package/dist/planner/types.d.ts +202 -0
  221. package/dist/planner/types.js +1 -0
  222. package/dist/plugins/hierarchy/compatibility.d.ts +2 -0
  223. package/dist/plugins/hierarchy/compatibility.js +1 -0
  224. package/dist/plugins/hierarchy/entity-identity.d.ts +2 -0
  225. package/dist/plugins/hierarchy/entity-identity.js +1 -0
  226. package/dist/plugins/hierarchy/index.d.ts +3 -0
  227. package/dist/plugins/hierarchy/index.js +1 -0
  228. package/dist/plugins/hierarchy/operator.d.ts +2 -0
  229. package/dist/plugins/hierarchy/operator.js +1 -0
  230. package/dist/plugins/hierarchy/resolve-schema.d.ts +2 -0
  231. package/dist/plugins/hierarchy/resolve-schema.js +1 -0
  232. package/dist/plugins/hierarchy/types.d.ts +28 -0
  233. package/dist/plugins/index.d.ts +5 -0
  234. package/dist/plugins/index.js +1 -0
  235. package/dist/plugins/types.d.ts +20 -0
  236. package/dist/schema/entity-identity.d.ts +5 -0
  237. package/dist/schema/entity-identity.js +1 -0
  238. package/dist/schema/index.d.ts +4 -0
  239. package/dist/schema/resolve-property-path.d.ts +15 -0
  240. package/dist/schema/resolve-property-path.js +1 -0
  241. package/dist/schema/schema-registry.d.ts +4 -0
  242. package/dist/schema/schema-registry.js +1 -0
  243. package/dist/schema-mappings/freshness.d.ts +7 -0
  244. package/dist/schema-mappings/freshness.js +1 -0
  245. package/dist/schema-mappings/index.d.ts +4 -0
  246. package/dist/schema-mappings/registry.d.ts +9 -0
  247. package/dist/schema-mappings/registry.js +1 -0
  248. package/dist/schema-mappings/types.d.ts +46 -0
  249. package/dist/semantic-types/builtins/boolean.d.ts +2 -0
  250. package/dist/semantic-types/builtins/boolean.js +1 -0
  251. package/dist/semantic-types/builtins/category.d.ts +2 -0
  252. package/dist/semantic-types/builtins/category.js +1 -0
  253. package/dist/semantic-types/builtins/currency.d.ts +2 -0
  254. package/dist/semantic-types/builtins/currency.js +1 -0
  255. package/dist/semantic-types/builtins/date.d.ts +2 -0
  256. package/dist/semantic-types/builtins/date.js +1 -0
  257. package/dist/semantic-types/builtins/duration.d.ts +2 -0
  258. package/dist/semantic-types/builtins/duration.js +1 -0
  259. package/dist/semantic-types/builtins/end-date.d.ts +2 -0
  260. package/dist/semantic-types/builtins/end-date.js +1 -0
  261. package/dist/semantic-types/builtins/entity.d.ts +2 -0
  262. package/dist/semantic-types/builtins/entity.js +1 -0
  263. package/dist/semantic-types/builtins/file.d.ts +2 -0
  264. package/dist/semantic-types/builtins/file.js +1 -0
  265. package/dist/semantic-types/builtins/human-name.d.ts +2 -0
  266. package/dist/semantic-types/builtins/human-name.js +1 -0
  267. package/dist/semantic-types/builtins/id.d.ts +2 -0
  268. package/dist/semantic-types/builtins/id.js +1 -0
  269. package/dist/semantic-types/builtins/image.d.ts +2 -0
  270. package/dist/semantic-types/builtins/image.js +1 -0
  271. package/dist/semantic-types/builtins/index.d.ts +2 -0
  272. package/dist/semantic-types/builtins/index.js +1 -0
  273. package/dist/semantic-types/builtins/int.d.ts +2 -0
  274. package/dist/semantic-types/builtins/int.js +1 -0
  275. package/dist/semantic-types/builtins/name.d.ts +2 -0
  276. package/dist/semantic-types/builtins/name.js +1 -0
  277. package/dist/semantic-types/builtins/number.d.ts +2 -0
  278. package/dist/semantic-types/builtins/number.js +1 -0
  279. package/dist/semantic-types/builtins/object.d.ts +3 -0
  280. package/dist/semantic-types/builtins/object.js +1 -0
  281. package/dist/semantic-types/builtins/order.d.ts +2 -0
  282. package/dist/semantic-types/builtins/order.js +1 -0
  283. package/dist/semantic-types/builtins/percentage.d.ts +2 -0
  284. package/dist/semantic-types/builtins/percentage.js +1 -0
  285. package/dist/semantic-types/builtins/start-date.d.ts +2 -0
  286. package/dist/semantic-types/builtins/start-date.js +1 -0
  287. package/dist/semantic-types/builtins/string.d.ts +2 -0
  288. package/dist/semantic-types/builtins/string.js +1 -0
  289. package/dist/semantic-types/builtins/timestamp.d.ts +2 -0
  290. package/dist/semantic-types/builtins/timestamp.js +1 -0
  291. package/dist/semantic-types/index.d.ts +9 -0
  292. package/dist/semantic-types/index.js +1 -0
  293. package/dist/semantic-types/primal-types/date.d.ts +2 -0
  294. package/dist/semantic-types/primal-types/date.js +1 -0
  295. package/dist/semantic-types/primal-types/index.d.ts +2 -0
  296. package/dist/semantic-types/primal-types/index.js +1 -0
  297. package/dist/semantic-types/registry.d.ts +14 -0
  298. package/dist/semantic-types/registry.js +1 -0
  299. package/dist/semantic-types/resolve-schema.d.ts +4 -0
  300. package/dist/semantic-types/resolve-schema.js +1 -0
  301. package/dist/semantic-types/types.d.ts +90 -0
  302. package/dist/semantic-types/validate-resolved-schema.d.ts +6 -0
  303. package/dist/semantic-types/validate-resolved-schema.js +1 -0
  304. package/dist/utils/clone.d.ts +1 -0
  305. package/dist/utils/clone.js +1 -0
  306. package/package.json +62 -0
@@ -0,0 +1,13 @@
1
+ import type { LogicformType } from '../logicform-types';
2
+ type SchemaRegistry = Readonly<Record<string, unknown>>;
3
+ /** Converts a legacy LogicForm tree into the v2 wire shape without mutating input. */
4
+ export declare const normalizeLegacyLogicform: (logicform: unknown) => LogicformType;
5
+ /**
6
+ * Converts the legacy `pred.schema` fan-out into v2 composition. The planner
7
+ * intentionally rejects cross-schema PredItems, so this has to happen before
8
+ * the v2 normalizer sees the tree.
9
+ */
10
+ export declare const splitLegacySchemas: (logicform: LogicformType, schemas?: SchemaRegistry) => LogicformType;
11
+ /** Rejects legacy wire fields when a caller explicitly declares a v2 LogicForm. */
12
+ export declare const assertNoLegacyLogicformFields: (logicform: unknown) => void;
13
+ export {};
@@ -0,0 +1 @@
1
+ import{SemanticDBError as m}from"../errors.js";const p=r=>!a(r)||!Array.isArray(r.properties)?[]:r.properties.filter(a),$=(r,n)=>r.id===n||r._id===n||r.name===n,h=(r,n,e,o=new Set)=>{if(r===n)return[];if(!o.has(r)){o.add(r);for(const t of p(e[r])){if(typeof t.ref!="string"||e[t.ref]===void 0)continue;const f=h(t.ref,n,e,o);if(f)return[String(t.name??t.id),...f]}o.delete(r)}},w=(r,n,e)=>{if(p(e[r]).some(d=>$(d,n)))return n;const t=n.split("_");for(let d=1;d<t.length;d+=1){const c=t.slice(d).join("_");if(p(e[r]).some(i=>$(i,c)))return c}const f=t.at(-1)??n;for(const[d,c]of Object.entries(e)){if(!p(c).some(u=>$(u,f)))continue;const i=h(r,d,e);if(i)return[...i,f].join("_")}},O=r=>Object.keys(r).filter(n=>n!=="$and"&&n!=="$or"),a=r=>typeof r=="object"&&r!==null&&!Array.isArray(r),b=r=>{if(!a(r))return r;if(a(r.$offset)){const n=Object.entries(r.$offset),e=n[0];if(n.length===1&&e&&Number.isInteger(e[1]))return{granularity:e[0],offset:e[1]}}return r},L=(r,n)=>{const o=r&&({$sply:"$periodShift",$splm:"$periodShift",$splw:"$periodShift",$yoy:"$periodGrowth",$mom:"$periodGrowth",$wow:"$periodGrowth",$yoyd:"$periodDifference",$momd:"$periodDifference",$dailyavg:"$averagePerPeriod",$weeklyavg:"$averagePerPeriod",$monthlyavg:"$averagePerPeriod",$startOfPeriod:"$periodBoundary",$endOfPeriod:"$periodBoundary",$dateLevel:"$dateBucket",$uniq:"$countDistinct"}[r]??r),t={...n};return r==="$sply"||r==="$yoy"||r==="$yoyd"?t.time??={granularity:"year",offset:-1}:r==="$splm"||r==="$mom"||r==="$momd"?t.time??={granularity:"month",offset:-1}:r==="$splw"||r==="$wow"?t.time??={granularity:"week",offset:-1}:r==="$dailyavg"?t.granularity??="day":r==="$weeklyavg"?t.granularity??="week":r==="$monthlyavg"?t.granularity??="month":r==="$startOfPeriod"?t.boundary??="start":r==="$endOfPeriod"&&(t.boundary??="end"),{...o?{operator:o}:{},args:t}},y=r=>{if(Array.isArray(r))return r.map(y);if(!a(r))return r;const n=r,e={};for(const[t,f]of Object.entries(n))t==="skip"||t==="_snapshot"||t==="_snapshots"||(t==="$offset"?e[t]=b(f):e[t]=y(f));if(typeof n.version=="string"&&/^1\./.test(n.version)&&(e.version="2.0"),Array.isArray(n.groupby)){const t=n.groupby;e.groupby=t.map(f=>{if(!a(f))return f;const{_id:d,level:c,...i}=f,u={...i,...i.pred===void 0&&typeof d=="string"?{pred:d}:{}};return typeof c=="string"&&(u.operator="$dateBucket",u.args={...a(u.args)?u.args:{},granularity:c}),u})}const o=n.skip;if(typeof o=="number"&&Number.isInteger(o)&&o>=0){const t=n.limit;o===0?delete e.skip:typeof t=="number"&&Number.isInteger(t)&&t>0&&o%t===0?e.page=o/t+1:e.skip=o}else o!==void 0&&(e.skip=y(o));if(n.operator&&typeof n.operator=="string"){const t=L(n.operator,a(e.args)?e.args:{});t.operator&&(e.operator=t.operator),e.args=t.args}return n.params!==void 0&&e.args===void 0&&(e.args=Array.isArray(n.params)?{values:y(n.params)}:y(n.params)),n.inputs!==void 0&&e.components===void 0&&Array.isArray(n.inputs)&&(e.components=n.inputs.map(y),a(e.args)&&delete e.args.inputs),n.pred===void 0&&typeof n.operator=="string"&&n.operator==="$sql"&&typeof n.sql=="string"&&(e.args={...a(e.args)?e.args:{},sql:n.sql},delete e.sql),n.$options!==void 0&&e.$regex!==void 0&&(e.args={...a(e.args)?e.args:{},options:n.$options},delete e.$options),n.query&&a(n.query)&&(e.query=k(n.query)),e},k=r=>{const n=y(r);for(const[e,o]of Object.entries(n))n[e]=b(o);return n},v=r=>{const n=a(r)?r:void 0,e=y(r);if(!a(e))return e;if(n&&typeof n.operator=="string"&&n.preds===void 0){const o={};for(const d of["version","schema","query","groupby","having","sort","limit","page","skip","output","representation","currency"])e[d]!==void 0&&(o[d]=e[d]);const t=new Set(["version","schema","query","groupby","having","sort","limit","page","skip","output","representation","currency"]),f=Object.fromEntries(Object.entries(e).filter(([d])=>!t.has(d)));return o.preds=[f],v(o)}return(e.version===void 0||typeof e.version=="string"&&/^1\./.test(e.version))&&(e.version="2.0"),e},_=(r,n)=>{const e=r;if(Array.isArray(e.logicforms)||!Array.isArray(e.preds))return r;const o=e.preds,t=typeof e.schema=="string"?e.schema:void 0;if(!t)return r;const f=new Set([t]);for(const i of o)a(i)&&typeof i.schema=="string"&&f.add(i.schema);if(f.size<2)return r;if(!n)throw new Error("Cannot migrate cross-Schema LogicForm without Schema metadata for field alignment");const d=[...f].map(i=>{const u={...e,schema:i,preds:[]};if(u.preds=o.filter(s=>a(s)?(s.schema??t)===i:i===t).map(s=>{if(!a(s))return s;const{schema:g,...l}=s;return l}),Array.isArray(e.groupby)&&(u.groupby=e.groupby.map(s=>{if(!a(s)||typeof s.pred!="string")return s;const g=w(i,s.pred,n);if(!g)throw new Error(`Cannot align legacy groupby field ${s.pred} in Schema ${i}`);return{...s,pred:g}})),a(e.query)){u.query={};for(const s of O(e.query)){if(!Object.entries(n).find(([,A])=>p(A).some(q=>$(q,s)))?.[0])throw new Error(`Cannot align legacy query field ${s} to a Schema`);const l=w(i,s,n);if(!l)throw new Error(`Cannot align legacy query field ${s} in Schema ${i}`);u.query[l]=e.query[s]}for(const s of["$and","$or"])e.query[s]!==void 0&&(u.query[s]=e.query[s])}return u}),c={version:e.version,logicforms:d};for(const i of["output","representation","currency","sort"])e[i]!==void 0&&(c[i]=e[i]);return c},S=r=>{const n=(e,o)=>{if(Array.isArray(e)){e.forEach((t,f)=>n(t,`${o}[${f}]`));return}if(a(e))for(const[t,f]of Object.entries(e)){if(["is_snapshot","is_observation","_snapshot","_snapshots","$options","params","inputs"].includes(t))throw new m("LEGACY_LOGICFORM_NOT_ALLOWED",`Legacy LogicForm field is not supported in v2: ${o}.${t}`);if(t==="_id"&&(o.endsWith(".groupby")||o.includes(".groupby[")))throw new m("LEGACY_LOGICFORM_NOT_ALLOWED",`Legacy LogicForm field is not supported in v2: ${o}.${t}`);n(f,`${o}.${t}`)}};n(r,"$")};export{S as assertNoLegacyLogicformFields,v as normalizeLegacyLogicform,_ as splitLegacySchemas};
@@ -0,0 +1,12 @@
1
+ import type { OperatorCteCalculation, OperatorGroupKeyShift } from '../operators/index';
2
+ import type { CoreComputeProvider } from '../physical/index';
3
+ import type { LogicalPlan } from '../planner/index';
4
+ import type { CompiledQuery } from './types';
5
+ import type { OperatorRegistry } from '../operators/index';
6
+ export interface PreparedCteComponent {
7
+ readonly name: string;
8
+ readonly plan: LogicalPlan;
9
+ readonly groupKeyShifts?: readonly OperatorGroupKeyShift[];
10
+ readonly joinKeys?: readonly string[];
11
+ }
12
+ export declare const compileCteCalculation: (calculation: OperatorCteCalculation, components: readonly PreparedCteComponent[], outputPlan: LogicalPlan, provider: CoreComputeProvider, operators: OperatorRegistry) => CompiledQuery;
@@ -0,0 +1 @@
1
+ import{compilePlan as d}from"./compile-plan.js";const w=o=>`__semanticdb_cte_${o}`,h=o=>{const i=o.projections[o.groupBy.length];if(!i)throw new Error("CTE component must produce one metric projection");return i.name},y=(o,i)=>o?.find(c=>c.name===i),T=(o,i,c,e,g)=>{const s=[];let l=0;for(const t of i){const n=d(t.plan,e,g,l);l+=n.parameters.length,s.push({input:t,sql:n,alias:w(t.name)})}const j=s.map(({sql:t,alias:n})=>`${e.quoteIdentifier(n)} AS (${t.sql})`).join(", "),m=s[0];if(!m)throw new Error("CTE calculation requires a current component");const a=e.quoteIdentifier(m.alias),p=c.groupBy.map(({name:t})=>t),E=p.map(t=>`${a}.${e.quoteIdentifier(t)} AS ${e.quoteIdentifier(t)}`);let $="";for(const t of s.slice(1)){const n=e.quoteIdentifier(t.alias),u=(t.input.joinKeys??p).map(r=>{const f=y(t.input.groupKeyShifts,r),N=f?e.dateShift(`${n}.${e.quoteIdentifier(r)}`,f.granularity,f.offset):`${n}.${e.quoteIdentifier(r)}`;return`${a}.${e.quoteIdentifier(r)} = ${N}`});$+=` LEFT JOIN ${n} ON ${u.length>0?u.join(" AND "):"1 = 1"}`}const A=Object.fromEntries(s.map(({input:t,alias:n})=>[t.name,`${e.quoteIdentifier(n)}.${e.quoteIdentifier(h(t.plan))}`])),S=o.toSQL({values:A,quoteIdentifier:t=>e.quoteIdentifier(t)}),q=o.outputName??c.projections[c.groupBy.length]?.name;if(!q)throw new Error("CTE output projection is missing");const C=[...E,...o.exposeComponents?s.map(({input:t,alias:n})=>`${`${e.quoteIdentifier(n)}.${e.quoteIdentifier(h(t.plan))}`} AS ${e.quoteIdentifier(t.name)}`):[],`${S} AS ${e.quoteIdentifier(q)}`].join(", ");let I=`WITH ${j} SELECT ${C} FROM ${a}`;return I+=$,{sql:I,parameters:s.flatMap(({sql:t})=>t.parameters)}};export{T as compileCteCalculation};
@@ -0,0 +1,5 @@
1
+ import type { OperatorRegistry } from '../operators/index';
2
+ import type { CoreComputeProvider } from '../physical/index';
3
+ import type { LogicalPlan } from '../planner/index';
4
+ import type { CompiledQuery } from './types';
5
+ export declare const compilePlan: (plan: LogicalPlan, provider: CoreComputeProvider, operators?: OperatorRegistry, parameterOffset?: number) => CompiledQuery;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as N}from"../errors.js";import{createOperatorRegistry as X}from"../operators/index.js";import{isLogicalOrdinalQuery as z,isLogicalRecursiveQuery as K,isLogicalQuerySubquery as B}from"../planner/types.js";import{bindTrustedSqlExpression as Z}from"../operators/sql-expression.js";class x{provider;parameterOffset;values=[];constructor(e,n=0){this.provider=e,this.parameterOffset=n}add(e){const n=this.parameterOffset+this.values.length;return this.values.push(e),this.provider.parameter(n,e)}get nextParameterOffset(){return this.parameterOffset+this.values.length}append(e){this.values.push(...e)}}const v=(t,e)=>{const n=e.split(".");if(n.some(r=>r.length===0))throw new N("INVALID_SOURCE",`Invalid physical source: ${e}`);return n.map(r=>t.quoteIdentifier(r)).join(".")},C=(t,e,n)=>n===void 0?v(t,e):`(${n.trim().replace(/;+\s*$/,"")})`,tt=t=>/^(select|with)\b/i.test(t.trim()),P=(t,e,n,r,i)=>{const a=Z(t,[],String,`Property ${e} udf.sql`);if(!a.includes("$TS"))return a;if(!r)throw new N("PROPERTY_UDF_TIMESTAMP_REQUIRED",`Property ${e} udf.sql uses $TS but its Schema has no timestamp Property`,{property:e});const $=(i?`${n.quoteIdentifier(i)}.`:"")+n.quoteIdentifier(r);return a.replace(/\$TS/g,$)},y=(t,e,n,r=!1,i,a,$,o)=>{const u=(c,m)=>r&&m?`${e.quoteIdentifier(m)}.${e.quoteIdentifier(c)}`:e.quoteIdentifier(c);switch(t.kind){case"array-element":if(!o)throw new N("ARRAY_EXPANSION_UNAVAILABLE","Array expansion compiler is unavailable");return o(t.expansionPath);case"column":return u(t.column,t.qualifier);case"property-sql":return P(t.sql,t.property,e,t.timestampColumn,r?t.qualifier:void 0);case"window":{if(l(t.input,n))throw new N("UNSUPPORTED_MIXED_OPERATOR","Window operators cannot consume a JavaScript operator");const c=t.partitionBy.length>0?`PARTITION BY ${t.partitionBy.map(f=>y(f,e,n,r,i,a,$,o)).join(", ")} `:"",m=y(t.input,e,n,r,i,a,$,o);return`${t.function==="rank"?"RANK":"ROW_NUMBER"}() OVER (${c}ORDER BY ${m} ${t.direction})`}case"cumulative":{if(l(t.input,n))throw new N("UNSUPPORTED_MIXED_OPERATOR","Cumulative expressions cannot consume a JavaScript operator");const c=y(t.input,e,n,r,i,a,$,o),m=t.partitionBy.length>0?`PARTITION BY ${t.partitionBy.map(f=>y(f,e,n,r,i,a,$,o)).join(", ")} `:"",A=t.orderBy.map(f=>`${y(f.expression,e,n,r,i,a,$,o)} ${f.direction}`).join(", ");return`${e.aggregateFunction(t.function,c)} OVER (${m}ORDER BY ${A} ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)`}case"ordinal-encode":{if(!a)throw new N("SQL_BINDER_UNAVAILABLE","Ordinal encoding requires a value binder");return`CASE ${t.comparable.values.map((m,A)=>`WHEN ${y(t.input,e,n,r,i,a,$,o)} = ${a(m)} THEN ${t.comparable.direction*A}`).join(" ")} END`}case"ordinal-decode":{if(!a)throw new N("SQL_BINDER_UNAVAILABLE","Ordinal decoding requires a value binder");return`CASE ${t.comparable.values.map((m,A)=>`WHEN ${y(t.input,e,n,r,i,a,$,o)} = ${t.comparable.direction*A} THEN ${a(m)}`).join(" ")} END`}case"operator":{const c=n.get(t.operator);if(c.kind==="component")throw new N("COMPONENT_OPERATOR_REQUIRES_EXECUTOR",`${t.operator} must be compiled through the executor component pipeline`);if(c.toSQL&&(t.input&&l(t.input,n)||t.components?.some(f=>l(f,n))))throw new N("UNSUPPORTED_MIXED_OPERATOR",`${t.operator} cannot consume a JavaScript operator in SQL`);let m=t.input?y(t.input,e,n,r,i,a,$,o):t.column?u(t.column,t.qualifier):void 0;const A=t.components?.map(f=>y(f,e,n,r,i,a,$,o));if(t.query){if(c.kind!=="aggregate")throw new N("OPERATOR_QUERY_REQUIRES_AGGREGATION",`Pred query is only supported by aggregation operators: ${t.operator}`);if(!i)throw new N("INVALID_OPERATOR_QUERY","Operator query compiler is unavailable");m=`CASE WHEN ${i(t.query)} THEN ${m??"1"} END`}if(c.requiresProperty!==!1&&!m)throw new N("PRED_PROPERTY_REQUIRED",`${t.operator} requires a column`);return c.toSQL?c.toSQL({sql:{aggregateFunction:e.aggregateFunction.bind(e),quoteIdentifier:e.quoteIdentifier.bind(e),concat:e.concat.bind(e),substring:e.substring.bind(e),dateBucket:e.dateBucket.bind(e),value:f=>{if(!a)throw new N("SQL_BINDER_UNAVAILABLE","SQL value binder is unavailable");return a(f)},condition:(f,_)=>{if(!$)throw new N("SQL_CONDITION_UNAVAILABLE","SQL condition compiler is unavailable");return $(f,_)}},...m?{expression:m,column:m}:{},...A?{expressions:A}:{},args:t.args}):m??"NULL"}}},l=(t,e)=>t.kind==="window"?l(t.input,e)||t.partitionBy.some(n=>l(n,e)):t.kind==="cumulative"?l(t.input,e)||t.partitionBy.some(n=>l(n,e))||t.orderBy.some(n=>l(n.expression,e)):t.kind==="ordinal-encode"||t.kind==="ordinal-decode"?l(t.input,e):t.kind==="operator"&&(!e.get(t.operator).toSQL&&!!e.get(t.operator).evaluate||(t.input?l(t.input,e):!1)||(t.components?.some(n=>l(n,e))??!1)),et=(t,e)=>t.sourceSql?P(t.sourceSql,t.sourceColumn,e,t.sourceTimestampColumn,t.sourceAlias):`${e.quoteIdentifier(t.sourceAlias)}.${e.quoteIdentifier(t.sourceColumn)}`,H=t=>typeof t=="object"&&t!==null&&!Array.isArray(t)&&Object.keys(t).some(e=>e.startsWith("$")),nt=(t,e,n)=>{if(!n.supportsRecursiveCte)throw new N("RECURSIVE_QUERY_UNSUPPORTED",`Provider ${n.kind} does not support recursive queries`);if(t.roots.length===0)return"(SELECT NULL WHERE 1 = 0)";const r=n.quoteIdentifier("__recursive_tree__"),i=n.quoteIdentifier("__recursive_id__"),a=n.quoteIdentifier("__recursive_node__"),$=n.quoteIdentifier("__recursive_child__"),o=n.quoteIdentifier(t.idColumn),u=n.quoteIdentifier(t.parentColumn),c=C(n,t.source,t.sourceSql),m=()=>t.roots.map(w=>e.add(w)).join(", "),A=(w,T=!1)=>t.roots.length===1?`${w} ${T?"<>":"="} ${m()}`:`${w} ${T?"NOT IN":"IN"} (${m()})`,f=`${a}.${o}`,_=t.includeSelf?A(f):`${A(`${a}.${u}`)} AND ${A(f,!0)}`;return`(WITH RECURSIVE ${r}(${i}) AS ( SELECT ${f} FROM ${n.tableAlias(c,"__recursive_node__")} WHERE ${_} UNION SELECT ${$}.${o} FROM ${n.tableAlias(c,"__recursive_child__")} JOIN ${r} ON ${$}.${u} = ${r}.${i}) SELECT DISTINCT ${i} FROM ${r})`},D=(t,e,n,r,i,a,$)=>{if(e==="$recursive"){if(!K(n))throw new N("INVALID_RECURSIVE_QUERY","$recursive query was not planned");return`${t} IN ${nt(n,r,i)}`}if(e==="$eq"&&n===null)return`${t} IS NULL`;if(e==="$ne"&&n===null)return`${t} IS NOT NULL`;const u={$eq:"=",$ne:"<>",$gt:">",$gte:">=",$lt:"<",$lte:"<="}[e];if(u){const c=B(n)?`(${a(n)})`:r.add(n);return`${t} ${u} ${c}`}if(e==="$in"||e==="$nin"){const c=e==="$in"?"IN":"NOT IN";if(B(n))return`${t} ${c} (${a(n)})`;if(!Array.isArray(n))throw new N("INVALID_QUERY_VALUE",`${e} requires an array or query LogicForm`);if(n.length===0)return e==="$in"?"0 = 1":"1 = 1";const m=n.filter(B);if(m.length>0){if(m.length!==n.length)throw new N("MIXED_SUBQUERY_VALUES",`${e} cannot mix query LogicForms and literal values`);return`${t} ${c} (${m.map(a).join(" UNION ALL ")})`}const A=n.map(f=>r.add(f)).join(", ");return`${t} ${c} (${A})`}if(B(n))throw new N("UNSUPPORTED_SUBQUERY_OPERATOR",`Query LogicForm is not supported by ${e}`);if(e==="$exists")return`${t} IS ${n?"NOT ":""}NULL`;if(e==="$contains")return`${t} LIKE ${r.add(`%${String(n)}%`)}`;if(e==="$regex"){if(typeof n!="string"||$!==void 0&&typeof $!="string")throw new N("INVALID_QUERY_VALUE","$regex requires a string pattern and args.options must be a string");return i.regex(t,r.add(n),$)}throw new N("UNSUPPORTED_QUERY_OPERATOR",`Unsupported query operator: ${e}`)},b=(t,e,n,r,i)=>{if(z(e)){const u=()=>`CASE ${e.comparable.values.map((f,_)=>`WHEN ${t} = ${n.add(f)} THEN ${e.comparable.direction*_}`).join(" ")} END`,c=new Set(["$gt","$gte","$lt","$lte"]),m=A=>typeof A!="object"||A===null||Array.isArray(A)?b(t,A,n,r,i):Object.entries(A).filter(([f])=>f!=="args").map(([f,_])=>(f==="$and"||f==="$or")&&Array.isArray(_)?`(${_.map(m).join(f==="$and"?" AND ":" OR ")})`:c.has(f)?D(u(),f,e.comparable.direction*e.comparable.values.indexOf(String(_)),n,r,i):D(t,f,_,n,r,i)).join(" AND ");return m(e.condition)}if(Array.isArray(e))return D(t,"$in",e,n,r,i);if(!H(e))return D(t,"$eq",e,n,r,i);const a=[],$=e.args;if($!==void 0){if(typeof $!="object"||$===null||Array.isArray($))throw new N("INVALID_QUERY_VALUE","Query args.options must be a string");const u=$.options;if(u!==void 0&&typeof u!="string")throw new N("INVALID_QUERY_VALUE","Query args.options must be a string")}const o=$?.options;for(const[u,c]of Object.entries(e))if(u==="$and"||u==="$or"){if(!Array.isArray(c))throw new N("INVALID_QUERY_VALUE",`${u} requires an array`);const m=c.map(A=>b(t,A,n,r,i));a.push(`(${m.join(u==="$and"?" AND ":" OR ")})`)}else u!=="args"&&a.push(D(t,u,c,n,r,i,u==="$regex"?o:void 0));if(a.length===0)throw new N("EMPTY_QUERY_CONDITION","Query condition contains no operators");return a.join(" AND ")},W=(t,e,n,r)=>{if(!r.arrayContains)throw new N("ARRAY_CONDITION_UNSUPPORTED",`Provider ${r.kind} does not support array conditions`);const i=r.arrayContains.bind(r),a=o=>i(t,n.add(o));if(Array.isArray(e))return`(${e.map(a).join(" OR ")})`;if(!H(e))return a(e);const $=[];for(const[o,u]of Object.entries(e))if(o==="$and"||o==="$or"){if(!Array.isArray(u))throw new N("INVALID_QUERY_VALUE",`${o} requires an array`);const c=u.map(m=>W(t,m,n,r));$.push(`(${c.join(o==="$and"?" AND ":" OR ")})`)}else if(o==="$eq")$.push(a(u));else if(o==="$ne")$.push(`NOT (${a(u)})`);else if(o==="$in"||o==="$nin"){if(!Array.isArray(u))throw new N("INVALID_QUERY_VALUE",`${o} requires an array`);const c=u.map(a),m=c.length===0?o==="$in"?"0 = 1":"1 = 1":c.join(o==="$in"?" OR ":" AND NOT ");$.push(o==="$nin"&&c.length>0?`NOT (${c.join(" OR ")})`:`(${m})`)}else if(o==="$exists")$.push(`${t} IS ${u?"NOT ":""}NULL`);else if(o!=="args")throw new N("UNSUPPORTED_ARRAY_QUERY_OPERATOR",`Unsupported array query operator: ${o}`);if($.length===0)throw new N("EMPTY_QUERY_CONDITION","Query condition contains no operators");return $.join(" AND ")},Q=(t,e,n,r,i,a)=>{const $=[];for(const[o,u]of Object.entries(t)){if(o==="$and"||o==="$or"){if(!Array.isArray(u))throw new N("INVALID_QUERY_VALUE",`${o} requires an array`);const m=u.map(A=>{if(typeof A!="object"||A===null||Array.isArray(A))throw new N("INVALID_QUERY_VALUE",`${o} items must be query objects`);return Q(A,e,n,r,i,a)});$.push(`(${m.join(o==="$and"?" AND ":" OR ")})`);continue}const c=e(o);$.push(n(o)?W(c,u,r,i):b(c,u,r,i,a))}return $.join(" AND ")},Y=(t,e,n,r,i)=>t.orderBy.map(a=>{const $=e.quoteIdentifier(a.name),o=`${r?`${r}.`:""}${$}`,u=a.comparable,c=!r&&i&&a.expression?i(a.expression):o;return`${u?`CASE ${u.values.map((A,f)=>`WHEN ${c} = ${n.add(A)} THEN ${u.direction*f}`).join(" ")} END`:o} ${a.direction}`}).join(", "),M=(t,e)=>{let n=t;for(;e.has(n);)n=`_${n}`;return n},st=(t,e,n,r,i)=>{const a=new Set(e.projections.map(({name:h})=>h)),$="__semanticdb_page_source",o="__semanticdb_page",u=r.quoteIdentifier($),c=r.quoteIdentifier(o),m=M("__semanticdb_row_number",a),A=M("__semanticdb_total_rows",a),f=r.quoteIdentifier(m),_=r.quoteIdentifier(A),w=Y(e,r,i,u),T=w?`ORDER BY ${w}`:"",d=`CEIL(${_} * ${n.ratio})`,U=n.page-1,O=n.page,s=[...e.projections.map(({name:h})=>h),...e.rowIdentity.kind==="property"?[e.rowIdentity.internalName]:[]].map(h=>`${c}.${r.quoteIdentifier(h)}`).join(", "),E=Y(e,r,i,c),I=`SELECT ${u}.*, ROW_NUMBER() OVER (${T}) AS ${f}, COUNT(*) OVER () AS ${_} FROM ${r.tableAlias(`(${t})`,$)}`;let S=`SELECT ${s} FROM ${r.tableAlias(`(${I})`,o)} WHERE ${c}.${f} > ${U} * ${d} AND ${c}.${f} <= ${O} * ${d}`;return E&&(S+=` ORDER BY ${E}`),S},V=(t,e,n,r)=>{const i=e.groupLimit;if(!i)return t;const a="__semanticdb_limit_by_source",$="__semanticdb_limit_by_ranked",o=n.quoteIdentifier(a),u=n.quoteIdentifier($),c=new Set(e.projections.map(({name:O})=>O)),m=M("__semanticdb_limit_by_row_number",c),A=n.quoteIdentifier(m),f=i.partitionBy.map(O=>`${o}.${n.quoteIdentifier(O)}`).join(", "),_=i.orderBy.map(({name:O,direction:R,comparable:s})=>{const E=`${o}.${n.quoteIdentifier(O)}`;return`${s?`CASE ${s.values.map((S,h)=>`WHEN ${E} = ${r.add(S)} THEN ${s.direction*h}`).join(" ")} END`:E} ${R}`}).join(", "),T=[...e.projections.map(({name:O})=>O),...e.rowIdentity.kind==="property"?[e.rowIdentity.internalName]:[]].map(O=>`${u}.${n.quoteIdentifier(O)}`).join(", "),d=`PARTITION BY ${f} ORDER BY ${_}`,U=`SELECT ${o}.*, ROW_NUMBER() OVER (${d}) AS ${A} FROM ${n.tableAlias(`(${t})`,a)}`;return`SELECT ${T} FROM ${n.tableAlias(`(${U})`,$)} WHERE ${u}.${A} <= ${i.count}`},k=(t,e,n=X(),r=0)=>{const i=new x(e,r);if(t.composition){const s=t.projections.map(({name:g})=>g),E=t.groupBy.map(({name:g})=>g),I=t.composition.map((g,j)=>{const F=k(g,e,n,i.nextParameterOffset);i.append(F.parameters);const p=`__composition_child_${j}`,G=e.quoteIdentifier(p),J=new Set(g.projections.map(({name:L})=>L));return`SELECT ${s.map(L=>J.has(L)?`${G}.${e.quoteIdentifier(L)} AS ${e.quoteIdentifier(L)}`:`NULL AS ${e.quoteIdentifier(L)}`).join(", ")} FROM ${e.tableAlias(`(${F.sql})`,p)}`}),S="__composition_union",h=e.quoteIdentifier(S);let q=`SELECT ${s.map(g=>{const j=`${h}.${e.quoteIdentifier(g)}`;return E.includes(g)?`${j} AS ${e.quoteIdentifier(g)}`:`MAX(${j}) AS ${e.quoteIdentifier(g)}`}).join(", ")} FROM ${e.tableAlias(`(${I.join(" UNION ALL ")})`,S)}`;return E.length>0&&(q+=` GROUP BY ${E.map(g=>`${h}.${e.quoteIdentifier(g)}`).join(", ")}`),t.groupLimit&&(q=V(q,t,e,i)),t.orderBy.length>0&&(q+=` ORDER BY ${Y(t,e,i)}`),t.pagination?.kind==="rows"&&(q=e.paginate(q,t.pagination.pageSize,0)),{sql:q,parameters:i.values}}const a=s=>{if(s.plan.projections.some(({expression:I})=>l(I,n)))throw new N("JAVASCRIPT_OPERATOR_IN_SUBQUERY","A query LogicForm cannot use a JavaScript-only operator");const E=k(s.plan.rowIdentity.kind==="property"?{...s.plan,rowIdentity:{kind:"generated"}}:s.plan,e,n,i.nextParameterOffset);return i.append(E.parameters),E.sql},$=(t.joins?.length??0)>0,o=(t.arrayExpansions?.length??0)>0,u=$||o||t.sourcePlan!==void 0||t.sourceSql!==void 0,c=new Map,m=(t.arrayExpansions??[]).map(s=>{if(!e.expandArray)throw new N("ARRAY_EXPANSION_UNSUPPORTED",`Provider ${e.kind} does not support array expansion`);const E=e.expandArray(et(s,e),s.alias,"value");return c.set(s.path,E.valueExpression),E}),A=s=>{const E=t.fieldReferences?.[s];if(E?.sql)return P(E.sql,E.property,e,E.timestampColumn,u?E.qualifier:void 0);if(E&&u)return`${e.quoteIdentifier(E.qualifier)}.${e.quoteIdentifier(E.column)}`;const I=t.fields[s];if(!I)throw new N("PROPERTY_NOT_FOUND",`Query property not found: ${s}`);return e.quoteIdentifier(I)},f=s=>y(s,e,n,u,E=>Q(E,A,I=>t.fieldReferences?.[I]?.isArray===!0,i,e,a),E=>i.add(E),(E,I)=>b(E,I,i,e,a),E=>{const I=c.get(E);if(!I)throw new N("ARRAY_EXPANSION_NOT_FOUND",`Array expansion not found: ${E}`);return I}),_=t.projections.map(s=>`${f(s.expression)} AS ${e.quoteIdentifier(s.name)}`),w=t.rowIdentity.kind==="property"?`${u&&t.sourceAlias?`${e.quoteIdentifier(t.sourceAlias)}.`:""}${e.quoteIdentifier(t.rowIdentity.column)} AS ${e.quoteIdentifier(t.rowIdentity.internalName)}`:void 0,T=[..._,...w?[w]:[]].join(", "),d=!t.sourcePlan&&t.sourceSql!==void 0&&tt(t.sourceSql)?{name:e.quoteIdentifier(t.schemaId),sql:t.sourceSql.trim().replace(/;+\s*$/,"")}:void 0,U=t.sourcePlan?(()=>{const s=k(t.sourcePlan,e,n,i.nextParameterOffset);return i.append(s.parameters),`(${s.sql})`})():d?d.name:C(e,t.source,t.sourceSql),O=u&&t.sourceAlias?e.tableAlias(U,t.sourceAlias):U;let R=`SELECT ${T} FROM ${O}`;for(const s of m)R+=` ${s.joinSql}`;for(const s of t.joins??[]){R+=` LEFT JOIN ${e.tableAlias(C(e,s.targetSource,s.targetSourceSql),s.targetAlias)}`;const E=s.sourceArrayExpansionPath?c.get(s.sourceArrayExpansionPath):s.sourceSql?P(s.sourceSql,s.sourceColumn,e,s.sourceTimestampColumn,s.sourceAlias):`${e.quoteIdentifier(s.sourceAlias)}.${e.quoteIdentifier(s.sourceColumn)}`,I=s.targetSql?P(s.targetSql,s.targetColumn,e,s.targetTimestampColumn,s.targetAlias):`${e.quoteIdentifier(s.targetAlias)}.${e.quoteIdentifier(s.targetColumn)}`;if(!E)throw new N("ARRAY_EXPANSION_NOT_FOUND",`Array expansion not found: ${s.path}`);if(R+=` ON ${E} = ${I}`,s.sourceTimestampColumn&&s.targetTimestampColumn&&s.sourceTimestampGranularity&&s.targetTimestampGranularity){const S=`${e.quoteIdentifier(s.sourceAlias)}.${e.quoteIdentifier(s.sourceTimestampColumn)}`,h=`${e.quoteIdentifier(s.targetAlias)}.${e.quoteIdentifier(s.targetTimestampColumn)}`;R+=` AND ${e.dateBucket(S,s.sourceTimestampGranularity)} = ${e.dateBucket(h,s.targetTimestampGranularity)}`}}if(t.query&&Object.keys(t.query).length>0&&(R+=` WHERE ${Q(t.query,A,s=>t.fieldReferences?.[s]?.isArray===!0,i,e,a)}`),t.groupBy.length>0&&(R+=` GROUP BY ${t.groupBy.map(s=>f(s.expression)).join(", ")}`),t.having&&Object.keys(t.having).length>0){const s=E=>{const I=t.projections.find(S=>S.name===E);if(!I)throw new N("INVALID_HAVING",`Having field is not an output: ${E}`);return e.supportsHavingAlias===!1?f(I.expression):e.quoteIdentifier(E)};R+=` HAVING ${Q(t.having,s,()=>!1,i,e,a)}`}if(t.groupLimit&&(R=V(R,t,e,i)),t.pagination?.kind==="ratio")R=st(R,t,t.pagination,e,i);else if(t.orderBy.length>0&&(R+=` ORDER BY ${Y(t,e,i,void 0,f)}`),t.pagination?.kind==="rows"){const s=(t.pagination.page-1)*t.pagination.pageSize;R=e.paginate(R,t.pagination.pageSize,s)}return d&&(R=`WITH ${d.name} AS (${d.sql}) ${R}`),{sql:R,parameters:i.values}};export{k as compilePlan};
@@ -0,0 +1,4 @@
1
+ export { compilePlan } from './compile-plan';
2
+ export { compileCteCalculation } from './compile-cte';
3
+ export { shortenSQL } from './shorten-sql';
4
+ export type { CompiledQuery } from './types';
@@ -0,0 +1,2 @@
1
+ /** Conservatively remove unused aliased columns from nested SELECT projections. */
2
+ export declare const shortenSQL: (sql: string) => string;
@@ -0,0 +1,2 @@
1
+ const h=e=>{if(typeof e!="string"||!/\bSELECT\b/i.test(e))return e;try{const c=d(e),i=[];for(const t of c){const s=$(e,t.selectEnd,t.fromStart);if(!s||s.length<2||s.some(u=>u.trim()==="*"))continue;const n=g(e.slice(t.fromStart,t.close),t,c),l=S(e,t,c),r=s.filter(u=>{const p=E(u);if(!p)return!0;const a=new RegExp(`(^|[^\\w$])${x(p)}([^\\w$]|$)`,"i");return a.test(n)||a.test(l)});if(r.length===s.length||r.length===0)continue;const f=e.slice(t.selectEnd,t.fromStart);i.push({start:t.selectEnd,end:t.fromStart,value:f.match(/^\s*/)[0]+r.map(u=>u.trim()).join(", ")+f.match(/\s*$/)[0]})}i.sort((t,s)=>s.start-t.start);let o=e;for(const t of i)o=o.slice(0,t.start)+t.value+o.slice(t.end);return o}catch{return e}},g=(e,c,i)=>m(e,i.filter(o=>o.open>c.open&&o.close<c.close).map(o=>({start:o.open-c.fromStart,end:o.close-c.fromStart+1}))),S=(e,c,i)=>{const o=i.filter(n=>n.open<c.open&&n.close>c.close).sort((n,l)=>n.close-n.open-(l.close-l.open))[0],t=o?o.open+1:0,s=o?o.close:e.length;return m(e.slice(t,s),i.filter(n=>n.open>=t&&n.close<s).map(n=>({start:n.open-t,end:n.close-t+1})))},m=(e,c)=>{if(!c.length)return e;const i=e.split("");for(const o of c)for(let t=Math.max(0,o.start);t<Math.min(i.length,o.end);t+=1)i[t]=" ";return i.join("")},d=e=>{const c=[],i=[];let o="",t="";for(let s=0;s<e.length;s+=1){const n=e[s],l=e[s+1];if(t==="--"){n===`
2
+ `&&(t="");continue}if(t==="/*"){n==="*"&&l==="/"&&(t="",s+=1);continue}if(o){n===o&&e[s-1]!=="\\"&&(o="");continue}if(n==="-"&&l==="-"){t="--",s+=1;continue}if(n==="/"&&l==="*"){t="/*",s+=1;continue}if(n==="`"||n==='"'||n==="'"){o=n;continue}if(n==="("){i.push({open:s});continue}if(n!==")")continue;const r=i.pop();if(!r)continue;const f=/\bSELECT\b/i.exec(e.slice(r.open+1,s));if(!f)continue;const u=r.open+1+f.index,p=/\bFROM\b/i.exec(e.slice(u+6,s));p&&c.push({open:r.open,close:s,selectEnd:u+6,fromStart:u+6+p.index})}return c},$=(e,c,i)=>{const o=e.slice(c,i),t=[];let s=0,n=0,l="";for(let r=0;r<o.length;r+=1){const f=o[r];if(l){f===l&&o[r-1]!=="\\"&&(l="");continue}if(f==="`"||f==='"'||f==="'"){l=f;continue}f==="("?n+=1:f===")"?n-=1:f===","&&n===0&&(t.push(o.slice(s,r)),s=r+1)}return l||n!==0?null:(t.push(o.slice(s)),t)},E=e=>e.trim().match(/\bAS\s+(`[^`]+`|"[^"]+"|[A-Za-z_][\w$]*)\s*$/i)?.[1]?.replace(/^`|`$/g,"").replace(/^"|"$/g,"")??null,x=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");export{h as shortenSQL};
@@ -0,0 +1,5 @@
1
+ import type { SqlParameters } from '../physical/index';
2
+ export interface CompiledQuery {
3
+ readonly sql: string;
4
+ readonly parameters: SqlParameters;
5
+ }
@@ -0,0 +1,6 @@
1
+ import type { PredItemType } from '../logicform-types';
2
+ import type { CustomFunctions, GenMetricComponentsOptions, MetricComponentNode, RuntimeCustomFunctionDefinition } from './types';
3
+ export declare const loadCustomFunctions: (definitions: CustomFunctions) => readonly RuntimeCustomFunctionDefinition[];
4
+ export declare const findCustomFunction: (definitions: readonly RuntimeCustomFunctionDefinition[], schemaId: string, name: string) => RuntimeCustomFunctionDefinition | undefined;
5
+ export declare const nameForPredNode: (pred: PredItemType) => string;
6
+ export declare const genMetricComponents: (pred: PredItemType, options: GenMetricComponentsOptions) => MetricComponentNode;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as m}from"../errors.js";import{defaultPredName as w}from"../normalizer/default-pred-name.js";import{createOperatorRegistry as S}from"../operators/index.js";const M=n=>Array.isArray(n)?n:Object.values(n),f=(n,e,r)=>{if(r!==void 0){if(typeof r=="function")return r;try{const s=Function(`return (${r})`)();if(typeof s!="function")throw new Error("source did not evaluate to a function");return s}catch(o){throw new m("INVALID_CUSTOM_FUNCTION_CALLBACK",`Cannot load ${n.name}.${e}: ${o instanceof Error?o.message:String(o)}`,{function:n.name,field:e})}}},i=n=>M(n).map(e=>{const{genComponents:r,mergeComponents:o,genMergeSQL:s,...a}=e;return{...a,genComponents:f(e,"genComponents",r),...o?{mergeComponents:f(e,"mergeComponents",o)}:{},...s?{genMergeSQL:f(e,"genMergeSQL",s)}:{}}}),N=(n,e,r)=>n.find(o=>o.name===r&&o.schema===e)??n.find(o=>o.name===r&&o.schema===void 0),y=n=>w(n,S()),T=(n,e)=>({version:"2.0",schema:n,preds:[e]}),l=(n,e)=>{const r=i(e.customFunctions),o=e.maxDepth??32,s={schemas:e.schemas,customFunctions:e.customFunctions,...e.permissions?{permissions:e.permissions}:{}},a=(c,O,C,d)=>{if(d>o)throw new m("CUSTOM_FUNCTION_MAX_DEPTH",`Custom function component depth exceeds ${o}`);const t=c.schema??O,u=c.operator?N(r,t,c.operator):void 0;if(!u)return{pred:c,schema:t,components:[]};const p=`${t}:${u.name}`;if(C.includes(p))throw new m("CUSTOM_FUNCTION_CYCLE",`Custom function component cycle: ${[...C,p].join(" -> ")}`);const h=e.schemas[t];if(!h)throw new m("SCHEMA_NOT_FOUND",`Schema is not registered: ${t}`);const F=e.logicform??T(t,c),g=u.genComponents(c,{schema:h,logicform:F,nameForPredNode:y,helperFunctions:s});if(!Array.isArray(g))throw new m("INVALID_CUSTOM_FUNCTION_COMPONENTS",`${u.name}.genComponents must return an array`);return{pred:c,schema:t,components:g.map(_=>a(_,t,[...C,p],d+1))}};return a(n,e.schema,[],0)};export{N as findCustomFunction,l as genMetricComponents,i as loadCustomFunctions,y as nameForPredNode};
@@ -0,0 +1,3 @@
1
+ export { findCustomFunction, genMetricComponents, loadCustomFunctions, nameForPredNode, } from './custom-functions';
2
+ export { registerCustomFunctionOperators } from './operator-adapter';
3
+ export type { CustomFunctionCallback, CustomFunctionColumnProperty, CustomFunctionDefinition, CustomFunctionHelpers, CustomFunctionSqlContext, CustomFunctions, GenComponents, GenComponentsContext, GenMergeSQL, GenMetricComponentsOptions, MergeComponents, MetricComponentNode, RuntimeCustomFunctionDefinition, } from './types';
@@ -0,0 +1,12 @@
1
+ import type { OperatorRegistry } from '../operators/index';
2
+ import type { CustomFunctionHelpers, CustomFunctions, RuntimeCustomFunctionDefinition } from './types';
3
+ interface AdapterOptions {
4
+ readonly schemas: CustomFunctionHelpers['schemas'];
5
+ readonly customFunctions: CustomFunctions;
6
+ readonly definitions: readonly RuntimeCustomFunctionDefinition[];
7
+ readonly config: Readonly<Record<string, unknown>>;
8
+ readonly permissions?: CustomFunctionHelpers['permissions'];
9
+ readonly locale?: string;
10
+ }
11
+ export declare const registerCustomFunctionOperators: (registry: OperatorRegistry, options: AdapterOptions) => OperatorRegistry;
12
+ export {};
@@ -0,0 +1 @@
1
+ import{SemanticDBError as m}from"../errors.js";import{defaultPredName as w}from"../normalizer/default-pred-name.js";import{clone as O}from"../utils/clone.js";import{findCustomFunction as T}from"./custom-functions.js";const E=e=>{const n=O(e);return delete n.having,delete n.sort,delete n.limit,delete n.page,n},y=(e,n)=>{const r=[e,n].filter(o=>o!==void 0&&Object.keys(o).length>0);if(r.length!==0)return r.length===1?r[0]:{$and:r}},F=(e,n)=>{if(!e.schema)throw new m("CUSTOM_FUNCTION_SCHEMA_REQUIRED","Custom functions require a physical LogicForm schema");const r=E(e),o=O(n);r.schema=o.schema??e.schema,delete o.schema,r.preds=[o];const t=y(e.query,o.query);return delete o.query,t?r.query=t:delete r.query,r},R=(e,n)=>{if(!Array.isArray(n)||n.length===0)throw new m("INVALID_CUSTOM_FUNCTION_COMPONENTS",`${e.name}.genComponents must return a non-empty array`);return n},_=(e,n)=>({name:n,type:e.type??"number",primal_type:e.primal_type??"number",isArray:!1}),I=e=>{const n=e.mergeMode??"auto";if(n==="sql"&&!e.genMergeSQL)throw new m("CUSTOM_FUNCTION_SQL_MERGER_REQUIRED",`${e.name} uses mergeMode sql but does not define genMergeSQL`);if(n==="js"&&!e.mergeComponents)throw new m("CUSTOM_FUNCTION_JS_MERGER_REQUIRED",`${e.name} uses mergeMode js but does not define mergeComponents`);if(n==="sql"||n==="auto"&&e.genMergeSQL)return"sql";if(e.mergeComponents)return"js";throw new m("CUSTOM_FUNCTION_MERGER_REQUIRED",`${e.name} must define genMergeSQL or mergeComponents`)},$=(e,n,r,o)=>({name:e,defaultName:({operandName:t,locale:c})=>c.toLowerCase().startsWith("en")?`${e.replace(/^\$/,"")} of ${t}`:`${t}${e.replace(/^\$/,"")}`,kind:"component",requiresProperty:!1,createComponent(t){const c=t.sourceLogicform??t.logicform;if(!c.schema)throw new m("CUSTOM_FUNCTION_SCHEMA_REQUIRED","Custom functions require a physical LogicForm schema");const a=T(r.definitions,t.pred.schema??c.schema,e);if(!a)throw new m("CUSTOM_FUNCTION_NOT_FOUND",`Custom function is not registered for schema ${c.schema}: ${e}`);const i=r.schemas[c.schema];if(!i)throw new m("SCHEMA_NOT_FOUND",`Schema is not registered: ${c.schema}`);const p={schemas:r.schemas,customFunctions:r.customFunctions,...r.permissions?{permissions:r.permissions}:{}},f=s=>w(s,o,{...r.locale?{locale:r.locale}:{}}),M=a.genComponents(t.pred,{schema:i,logicform:c,nameForPredNode:f,helperFunctions:p}),u=R(a,M).map(s=>({...s,name:s.name??f(s)})),l=new Set;for(const s of u){if(l.has(s.name))throw new m("DUPLICATE_CUSTOM_FUNCTION_COMPONENT",`Duplicate component name in ${a.name}: ${s.name}`);l.add(s.name)}const C=u.map(s=>({name:s.name,component:{kind:"query",logicform:F(c,s),prepare:!0}})),g={..._(a,t.outputName),components:u,baseProperty:t.pred},h=a.exposeComponents??!0;if(I(a)==="sql"){const s=a.genMergeSQL;return{kind:"cte",components:C,outputName:t.outputName,exposeComponents:h,toSQL:({values:d,quoteIdentifier:U})=>s(g,{...p,values:d,q:N=>d[N]??U(N)},r.config)}}const S=a.mergeComponents;return{kind:"js",components:C,outputName:t.outputName,exposeComponents:h,mergeRow:s=>S(s,g,r.config)}},getOutputProperty({name:t}){return _(n[0],t)}}),q=(e,n)=>{const r=new Set(n.definitions.map(({name:o})=>o));for(const o of r){if(e.has(o))throw new m("CUSTOM_FUNCTION_OPERATOR_CONFLICT",`Custom function conflicts with an existing operator: ${o}`);e.register($(o,n.definitions.filter(t=>t.name===o),n,e))}return e};export{q as registerCustomFunctionOperators};
@@ -0,0 +1,62 @@
1
+ import type { LogicformType, PredItemType } from '../logicform-types';
2
+ import type { ResultProperty } from '../operators/index';
3
+ import type { Permissions } from '../permissions/index';
4
+ import type { SemanticSchemaDraft } from '../semantic-types/index';
5
+ export type CustomFunctionCallback<T extends (...args: never[]) => unknown> = T | string;
6
+ export interface CustomFunctionHelpers {
7
+ readonly schemas: Readonly<Record<string, SemanticSchemaDraft>>;
8
+ readonly customFunctions: CustomFunctions;
9
+ /** The execution permissions inherited by every generated component query. */
10
+ readonly permissions?: Permissions;
11
+ }
12
+ export interface GenComponentsContext {
13
+ readonly schema: SemanticSchemaDraft;
14
+ readonly logicform: LogicformType;
15
+ readonly nameForPredNode: (pred: PredItemType, schema?: SemanticSchemaDraft, helperFunctions?: CustomFunctionHelpers) => string;
16
+ readonly helperFunctions: CustomFunctionHelpers;
17
+ }
18
+ export interface CustomFunctionColumnProperty extends ResultProperty {
19
+ readonly components: readonly PredItemType[];
20
+ readonly baseProperty: PredItemType;
21
+ }
22
+ export interface CustomFunctionSqlContext extends CustomFunctionHelpers {
23
+ /** Quote a name, or resolve a component name to its qualified CTE expression. */
24
+ readonly q: (name: string) => string;
25
+ readonly values: Readonly<Record<string, string>>;
26
+ }
27
+ export type GenComponents = (self: PredItemType, context: GenComponentsContext) => PredItemType[];
28
+ export type MergeComponents = (values: Record<string, unknown>, columnProperty: CustomFunctionColumnProperty, config: Readonly<Record<string, unknown>>) => unknown;
29
+ export type GenMergeSQL = (columnProperty: CustomFunctionColumnProperty, context: CustomFunctionSqlContext, config: Readonly<Record<string, unknown>>) => string;
30
+ export interface CustomFunctionDefinition {
31
+ readonly name: string;
32
+ /** Optional Schema scope. Definitions without a schema are global. */
33
+ readonly schema?: string;
34
+ readonly type?: string;
35
+ readonly primal_type?: ResultProperty['primal_type'];
36
+ readonly genComponents: CustomFunctionCallback<GenComponents>;
37
+ readonly mergeComponents?: CustomFunctionCallback<MergeComponents>;
38
+ readonly genMergeSQL?: CustomFunctionCallback<GenMergeSQL>;
39
+ /** auto prefers SQL and falls back to JavaScript when no SQL merger is supplied. */
40
+ readonly mergeMode?: 'auto' | 'sql' | 'js';
41
+ /** Keep named component values on result rows, matching the legacy executor. */
42
+ readonly exposeComponents?: boolean;
43
+ }
44
+ export type CustomFunctions = readonly CustomFunctionDefinition[] | Readonly<Record<string, CustomFunctionDefinition>>;
45
+ export interface GenMetricComponentsOptions {
46
+ readonly schemas: Readonly<Record<string, SemanticSchemaDraft>>;
47
+ readonly customFunctions: CustomFunctions;
48
+ readonly permissions?: Permissions;
49
+ readonly schema: string;
50
+ readonly logicform?: LogicformType;
51
+ readonly maxDepth?: number;
52
+ }
53
+ export interface MetricComponentNode {
54
+ readonly pred: PredItemType;
55
+ readonly schema: string;
56
+ readonly components: readonly MetricComponentNode[];
57
+ }
58
+ export interface RuntimeCustomFunctionDefinition extends Omit<CustomFunctionDefinition, 'genComponents' | 'mergeComponents' | 'genMergeSQL'> {
59
+ readonly genComponents: GenComponents;
60
+ readonly mergeComponents?: MergeComponents;
61
+ readonly genMergeSQL?: GenMergeSQL;
62
+ }
@@ -0,0 +1,5 @@
1
+ export declare class SemanticDBError extends Error {
2
+ readonly code: string;
3
+ readonly details?: Readonly<Record<string, unknown>> | undefined;
4
+ constructor(code: string, message: string, details?: Readonly<Record<string, unknown>> | undefined);
5
+ }
package/dist/errors.js ADDED
@@ -0,0 +1 @@
1
+ class s extends Error{code;details;constructor(r,e,t){super(e),this.code=r,this.details=t,this.name="SemanticDBError"}}export{s as SemanticDBError};
@@ -0,0 +1,6 @@
1
+ import type { SemanticSchemaDraft } from '../semantic-types/index';
2
+ import type { SemanticDBPlugin } from '../plugins/index';
3
+ export { normalizeLegacyLogicform } from '../compatibility/logicform';
4
+ /** Converts legacy Schema/Property identifiers without mutating caller data. */
5
+ export declare const normalizeSchemas: (input: Readonly<Record<string, SemanticSchemaDraft>>, externalPlugins?: readonly SemanticDBPlugin[], legacy?: boolean) => Readonly<Record<string, SemanticSchemaDraft>>;
6
+ export { normalizeLegacyLogicform as normalizeLogicform } from '../compatibility/logicform';
@@ -0,0 +1 @@
1
+ import{resolvePlugins as E}from"../plugins/index.js";const p=e=>{if(Array.isArray(e))return e.map(p).filter(t=>t!==void 0);if(typeof e!="object"||e===null||Object.prototype.toString.call(e)!=="[object Object]")return e;const o=Object.entries(e),n=o.filter(([,t])=>t!==null).map(([t,a])=>[t,p(a)]).filter(([,t])=>t!==void 0);if(!(o.length>0&&n.length===0))return Object.fromEntries(n)},F=e=>{if(e.comparable!=null)return e.comparable;if(e.is_comparable!==!0||e.isArray===!0||e.type!=="string"&&e.type!=="category"||!Array.isArray(e.constraints?.enum))return;const n=e.constraints.enum.map(t=>Array.isArray(t)?t[0]:t);if(!(n.length===0||n.some(t=>typeof t!="string")))return{values:[...new Set(n)],direction:e.comparable_order===-1?-1:1}},K=e=>{if(typeof e!="object"||e===null||Array.isArray(e))return e;const o=e;if(o.sql!=null)return Object.keys(o).every(n=>n==="sql")?e:{sql:o.sql}},v=(e,o=[],n=!0)=>{const t=E(o),a={},h=new Set(t.flatMap(d=>[...d.schemaMetadata?.keys??[],...d.legacySchemaKeys??[]]));for(const[d,_]of Object.entries(e)){const s=p(_),l=s,j=(Array.isArray(l.properties)?l.properties:[]).some(i=>i.is_observation===!0)||l.is_observation===!0,A=l.is_snapshot===!0,f=typeof s.id=="string"&&s.id.length>0?s.id:n&&typeof s._id=="string"&&s._id.length>0?s._id:s.id,{properties:O}=s,S=Object.fromEntries(Object.entries(s).filter(([i])=>(n?!["_id","_sid","sid","is_observation","is_snapshot"].includes(i):i!=="properties")&&i!=="properties"&&!h.has(i))),m=O.map(i=>{const r=i,y=typeof r.id=="string"&&r.id.length>0?r.id:n&&typeof r._id=="string"&&r._id.length>0?r._id:r.id,{udf:P,...b}=r,u=F(r),g=K(P),M=u!==void 0&&r.comparable==null?"category":r.type==="object"?"entity":r.type;return{...n?Object.fromEntries(Object.entries(b).filter(([q])=>!["_id","_sid","sid","is_observation","is_comparable","comparable_order"].includes(q))):b,type:M,...y!==void 0?{id:y}:{},...g!==void 0?{udf:g}:{},...u!==void 0?{comparable:u}:{}}});let c={};for(const i of t)for(const r of i.schemaMetadata?.keys??[])s[r]!==void 0&&(c={...c,[r]:s[r]});for(const i of t)c={...c,...i.normalizeLegacySchema?.({source:s,properties:m})};const z={...S,...f!==void 0?{id:f}:{},properties:m,...n&&(A||j)?{temporalSemantics:"snapshot"}:{},...c};a[d]=z}return a};export{v as normalizeSchemas};
@@ -0,0 +1,9 @@
1
+ import type { LogicformType } from '../logicform-types';
2
+ import type { OperatorExecutionComponent, OperatorRegistry } from '../operators/index';
3
+ import type { DataRow } from '../physical/index';
4
+ import type { LogicalPlan } from '../planner/index';
5
+ import type { ResolvedSemanticSchema } from '../semantic-types/index';
6
+ export type ExecutionUnit = OperatorExecutionComponent;
7
+ export declare const createExecutionUnits: (logicform: LogicformType, plan: LogicalPlan, schema: ResolvedSemanticSchema, operators: OperatorRegistry, resolveSchema: (schemaId: string) => ResolvedSemanticSchema, sourceLogicform?: LogicformType) => readonly ExecutionUnit[] | undefined;
8
+ export declare const mergeComponentRows: (results: readonly (readonly DataRow[])[], groupNames: readonly string[]) => DataRow[];
9
+ export declare const mergeExecutionResults: (results: readonly (readonly DataRow[])[], plan: LogicalPlan) => DataRow[];
@@ -0,0 +1 @@
1
+ import{SemanticDBError as l}from"../errors.js";import{clone as P}from"../utils/clone.js";import{groupRowIdentity as b}from"./row-identity.js";const R=r=>{const e=P(r);return delete e.having,delete e.sort,delete e.limit,delete e.page,e},m=(r,e)=>r.operator&&e.get(r.operator).kind==="component"?!0:typeof r.pred=="object"&&m(r.pred,e)||(r.components?.some(i=>m(i,e))??!1),j=(r,e,i,o,n,t)=>{const s=r.preds??[],c=s.map((u,p)=>({pred:u,index:p,definition:u.operator?o.get(u.operator):void 0})).filter(({definition:u})=>u?.kind==="component");if(c.length===0)return;for(const u of s)if((!u.operator||o.get(u.operator).kind!=="component")&&(typeof u.pred=="object"&&m(u.pred,o)||(u.components?.some(p=>m(p,o))??!1)))throw new l("UNSUPPORTED_COMPONENT_NESTING","A component operator must currently be the top-level projection operator");const a=[],d=s.filter((u,p)=>!c.some(y=>y.index===p));if(d.length>0){const u=R(r);u.preds=d,a.push({kind:"query",logicform:u})}const g=r.groupby?.length??0;for(const{pred:u,index:p,definition:y}of c){const A=y?.createComponent;if(!A)continue;const w=e.projections[g+p]?.name;if(!w)throw new l("INVALID_COMPONENT_PLAN","Component output projection is missing");const C=t?.preds?.[p],h=A({logicform:r,pred:C??u,outputName:w,schema:i,resolveSchema:n,...t?{sourceLogicform:t}:{}});if(h.kind==="query"&&(h.logicform.preds??[]).some(E=>m(E,o)))throw new l("UNSUPPORTED_COMPONENT_NESTING","Nested component operators are not supported yet");a.push(h)}return a},f=r=>r instanceof Date?r.getTime():r,v=(r,e,i,o)=>{const n=f(r),t=f(i);switch(e){case"$eq":return n===t;case"$ne":return n!==t;case"$gt":return n!=null&&t!==void 0&&t!==null&&n>t;case"$gte":return n!=null&&t!==void 0&&t!==null&&n>=t;case"$lt":return n!=null&&t!==void 0&&t!==null&&n<t;case"$lte":return n!=null&&t!==void 0&&t!==null&&n<=t;case"$in":return Array.isArray(i)&&i.some(s=>f(s)===n);case"$nin":return Array.isArray(i)&&i.every(s=>f(s)!==n);case"$exists":return i?r!=null:r==null;case"$contains":return String(r).includes(String(i));case"$regex":return typeof i=="string"&&new RegExp(i,o).test(String(r));default:throw new l("UNSUPPORTED_QUERY_OPERATOR",`Unsupported having operator: ${e}`)}},S=(r,e)=>{if(!e||typeof e!="object"||Array.isArray(e))return f(r)===f(e);const i=Object.entries(e),o=e.args,n=o&&typeof o=="object"&&!Array.isArray(o)?o.options:void 0;return i.every(([t,s])=>{if(t==="args")return!0;if(t==="$and"||t==="$or"){if(!Array.isArray(s))return!1;const c=s.map(a=>S(r,a));return t==="$and"?c.every(Boolean):c.some(Boolean)}return v(r,t,s,typeof n=="string"?n:void 0)})},$=(r,e)=>Object.entries(e).every(([i,o])=>{if(i==="$and"||i==="$or"){if(!Array.isArray(o))return!1;const n=o.map(t=>$(r,t));return i==="$and"?n.every(Boolean):n.some(Boolean)}return S(r[i],o)}),N=(r,e)=>e.length===0?"0":b(r,e),O=(r,e)=>{const i=new Map;for(const o of r)for(const n of o){const t=N(n,e);i.set(t,{...i.get(t)??{},...n})}return[...i.values()]},B=(r,e)=>{const i=e.groupBy.map(({name:n})=>n);let o=O(r,i);if(e.having&&(o=o.filter(n=>$(n,e.having))),e.groupLimit){const n=e.groupLimit,t=new Map;for(const s of o){const c=N(s,n.partitionBy);t.set(c,[...t.get(c)??[],s])}o=[...t.values()].flatMap(s=>s.sort((c,a)=>{for(const d of n.orderBy){const g=f(c[d.name]),u=f(a[d.name]);if(g!==u)return g==null?d.direction==="ASC"?-1:1:u==null?d.direction==="ASC"?1:-1:(g<u?-1:1)*(d.direction==="ASC"?1:-1)}return 0}).slice(0,n.count))}if(e.orderBy.length>0&&o.sort((n,t)=>{for(const s of e.orderBy){const c=f(n[s.name]),a=f(t[s.name]);if(c!==a)return c==null?s.direction==="ASC"?-1:1:a==null?s.direction==="ASC"?1:-1:(c<a?-1:1)*(s.direction==="ASC"?1:-1)}return 0}),e.pagination?.kind==="rows"){const n=(e.pagination.page-1)*e.pagination.pageSize;o=o.slice(n,n+e.pagination.pageSize)}else if(e.pagination?.kind==="ratio"){const n=Math.ceil(o.length*e.pagination.ratio),t=(e.pagination.page-1)*n;o=o.slice(t,t+n)}return o};export{j as createExecutionUnits,O as mergeComponentRows,B as mergeExecutionResults};
@@ -0,0 +1,12 @@
1
+ import type { CoreComputeProvider, DatabaseConnection } from '../physical/index';
2
+ type ProviderFactory = (connection: DatabaseConnection) => CoreComputeProvider;
3
+ export declare class ConnectionRegistry {
4
+ #private;
5
+ private readonly create;
6
+ constructor(create?: ProviderFactory);
7
+ get(connection: DatabaseConnection): CoreComputeProvider;
8
+ close(): Promise<void>;
9
+ }
10
+ export declare const getConnectionProvider: (connection: DatabaseConnection) => CoreComputeProvider;
11
+ export declare const closeConnections: () => Promise<void>;
12
+ export {};
@@ -0,0 +1 @@
1
+ import{isDeepStrictEqual as c}from"node:util";import{SemanticDBError as n}from"../errors.js";import{createProvider as p}from"../physical/connection.js";import"@clickhouse/client";import"mysql2/promise";import"mysql2";import"oracledb";import"pg";import"snowflake-sdk";class i{create;#r=new Map;constructor(r=p){this.create=r}get(r){const o=this.#r.get(r.id);if(o){if(!c(o.connection,r))throw new n("DATABASE_CONNECTION_CONFIGURATION_MISMATCH",`Database connection configuration changed for id: ${r.id}`,{connectionId:r.id});return o.provider}const t=this.create(r);return this.#r.set(r.id,{connection:r,provider:t}),t}async close(){const r=[...this.#r.values()].map(({provider:e})=>e);this.#r.clear();const o=await Promise.allSettled(r.map(async e=>e.close())),t=[];for(const e of o)e.status==="rejected"&&t.push(e.reason);if(t.length>0)throw new AggregateError(t,"Failed to close one or more database connections")}}const a=new i,d=s=>a.get(s),m=async()=>a.close();export{i as ConnectionRegistry,m as closeConnections,d as getConnectionProvider};
@@ -0,0 +1,4 @@
1
+ import type { OperatorRegistry } from '../operators/index';
2
+ import type { DataRow } from '../physical/index';
3
+ import type { ProjectionPlan } from '../planner/index';
4
+ export declare const evaluateJavaScriptProjections: (rows: readonly DataRow[], projections: readonly ProjectionPlan[], operators: OperatorRegistry) => Promise<DataRow[]>;
@@ -0,0 +1 @@
1
+ const c=(t,n)=>{if(t.kind!=="operator")return!1;const e=n.get(t.operator);return!e.toSQL&&!!e.evaluate||(t.input?c(t.input,n):!1)||(t.components?.some(a=>c(a,n))??!1)},u=(t,n,e,a)=>{if(t.kind!=="operator")return n[e];const r=a.get(t.operator),i=t.input?u(t.input,n,e,a):n[e];return r.evaluate?Promise.resolve(i).then(o=>r.evaluate?.({input:o,args:t.args})):i},l=async(t,n,e)=>{const a=n.filter(({expression:r})=>c(r,e));return a.length===0?[...t]:Promise.all(t.map(async r=>{const i={...r};for(const o of a)i[o.name]=await u(o.expression,i,o.name,e);return i}))};export{l as evaluateJavaScriptProjections};
@@ -0,0 +1,13 @@
1
+ import type { CompiledQuery } from '../compiler/index';
2
+ import type { DataRow } from '../physical/index';
3
+ import type { LogicalPlan } from '../planner/index';
4
+ import type { InternalExecuteOptions } from './types';
5
+ export interface PhysicalQuerySource {
6
+ readonly schemaId: string;
7
+ readonly source: string;
8
+ }
9
+ export declare const collectPlanSources: (plan: LogicalPlan) => readonly PhysicalQuerySource[];
10
+ export declare const mergePhysicalSources: (groups: readonly (readonly PhysicalQuerySource[])[]) => readonly PhysicalQuerySource[];
11
+ export declare const executeCompiledQuery: (compiled: CompiledQuery, sources: readonly PhysicalQuerySource[], options: Pick<InternalExecuteOptions, "cache" | "provider" | "schemaMappings" | "signal">) => Promise<DataRow[]>;
12
+ /** Apply final SQL shaping after all plans, views, and derived sources are compiled. */
13
+ export declare const shortenCompiledQuery: (compiled: CompiledQuery) => CompiledQuery;
@@ -0,0 +1 @@
1
+ import{resolveQueryExpiration as d}from"../cache/expiry.js";import"node:crypto";import"../operators/index.js";import{isLogicalQuerySubquery as m,isLogicalRecursiveQuery as y}from"../planner/types.js";import{shortenSQL as g}from"../compiler/shorten-sql.js";const i=(e,t,r)=>{if(m(e)){t.push(e.plan);return}if(y(e)){r.set(`${e.schemaId}:${e.source}`,{schemaId:e.schemaId,source:e.source});return}if(Array.isArray(e)){for(const o of e)i(o,t,r);return}if(!(typeof e!="object"||e===null||e instanceof Date))for(const o of Object.values(e))i(o,t,r)},f=(e,t,r)=>{if(e.kind==="window"){f(e.input,t,r);for(const o of e.partitionBy)f(o,t,r);return}if(e.kind==="operator"){i(e.query,t,r),e.input&&f(e.input,t,r);for(const o of e.components??[])f(o,t,r)}},a=e=>{const t=new Map,r=c=>{t.set(`${c.schemaId}:${c.source}`,c)};if(e.composition)for(const c of e.composition)for(const s of a(c))r(s);else if(e.sourcePlan)for(const c of a(e.sourcePlan))r(c);else r({schemaId:e.schemaId,source:e.source});for(const c of e.joins??[])r({schemaId:c.targetSchemaId,source:c.targetSource});const o=[];i(e.query,o,t),i(e.having,o,t);for(const c of e.projections)f(c.expression,o,t);for(const c of o)for(const s of a(c))r(s);return[...t.values()]},w=e=>{const t=new Map;for(const r of e.flat())t.set(`${r.schemaId}:${r.source}`,r);return[...t.values()]},I=(e,t)=>{const r=[];for(const o of e){const c=t.findSource(o.schemaId,o.source);if(!c?.freshness)return;r.push(c.freshness)}return r},l=async(e,t,r)=>{e=u(e),r.signal?.throwIfAborted();const o=r.cache?I(t,r.schemaMappings):void 0;if(!r.cache||!o)return r.provider.execute({...e,...r.signal?{signal:r.signal}:{}});const c={namespace:r.cache.namespace,provider:r.provider.kind,sql:e.sql,parameters:e.parameters};try{const n=await r.cache.store.get(c);if(r.signal?.throwIfAborted(),n)return[...n]}catch{r.signal?.throwIfAborted()}const s=await r.provider.execute({...e,...r.signal?{signal:r.signal}:{}});try{const n=d(o,new Date);await r.cache.store.set(c,s,{sources:[...new Set(t.map(({source:h})=>h))],...n?{expiresAt:n}:{}})}catch{}return s},u=e=>({...e,sql:g(e.sql)});export{a as collectPlanSources,l as executeCompiledQuery,w as mergePhysicalSources,u as shortenCompiledQuery};
@@ -0,0 +1,4 @@
1
+ import type { LogicformType } from '../logicform-types';
2
+ import type { ExecuteOptions, ExecuteResult, ExecuteSuccessResult, InternalExecuteOptions } from './types';
3
+ export declare const executeWithProvider: (inputLogicform: LogicformType, inputOptions: InternalExecuteOptions) => Promise<ExecuteSuccessResult>;
4
+ export declare const execute: (inputLogicform: LogicformType, inputOptions: ExecuteOptions) => Promise<ExecuteResult>;
@@ -0,0 +1 @@
1
+ import{performance as ae}from"node:perf_hooks";import{SemanticDBError as S}from"../errors.js";import{compilePlan as Z}from"../compiler/compile-plan.js";import{compileCteCalculation as ie}from"../compiler/compile-cte.js";import{evaluateJavaScriptProjections as ee}from"./evaluate.js";import{createExecutionUnits as ce,mergeExecutionResults as fe,mergeComponentRows as ge}from"./components.js";import{fetchEntities as he}from"./fetch-entities.js";import{hydrateResult as we}from"./result-hydrator/hydrate-result.js";import{addRowIdentities as ye}from"./row-identity.js";import{mergePhysicalSources as me,collectPlanSources as Q,executeCompiledQuery as B,shortenCompiledQuery as Se}from"./execute-query.js";import{normalizeLogicform as G}from"../normalizer/normalize-logicform.js";import{assertSupportedLogicformVersion as ve}from"../normalizer/version.js";import{createOperatorRegistry as Re}from"../operators/index.js";import{buildLineage as Ee}from"../planner/build-lineage.js";import{createLogicalPlan as z,createResultSchema as Pe,createDerivedSourceSchema as De}from"../planner/create-logical-plan.js";import{getSchema as Ie}from"../schema/schema-registry.js";import{createSemanticTypeRegistry as Ne}from"../semantic-types/index.js";import{validatePermissions as _e,applyPermissions as oe,isColumnAllowed as V,getSchemaPermissions as Ce}from"../permissions/permissions.js";import{getConnectionProvider as Oe}from"./connection-registry.js";import{loadCustomFunctions as Ae}from"../custom-functions/custom-functions.js";import{registerCustomFunctionOperators as Le}from"../custom-functions/operator-adapter.js";import{assertNoLegacyLogicformFields as qe,splitLegacySchemas as Te,normalizeLegacyLogicform as je}from"../compatibility/logicform.js";import{normalizeSchemas as Ue}from"./compatibility.js";import{OperatorRegistry as Fe}from"../operators/registry.js";import{resolveSchema as Me}from"../semantic-types/resolve-schema.js";const le=n=>n instanceof Error?n:new Error(String(n)),xe=n=>n.stack?`${n.message} [stack: ${n.stack}]`:n.message,Ke=(n,i,s={})=>{const a=le(n);return{errorCode:"100",error:xe(a),result:[],...s.schema?{schema:s.schema}:{},normedLogicform:s.normedLogicform??i,sqls:s.sqls??[],...s.provider?{provider:s.provider}:{},...s.lineage?{lineage:s.lineage}:{}}},$e=async(n,i,s)=>{await n?.({...i,partialResult:s})},be=(n,i,s)=>({type:s,sql:n.sql,parameters:[...n.parameters],displaySql:i.displayQuery(n.sql,n.parameters)}),pe=(n,i)=>{if(i.connectionId)for(const s of Q(n)){const a=i.schemaMappings.findSource(s.schemaId,s.source);if(!a)throw new S("SCHEMA_MAPPING_NOT_FOUND",`Schema mapping is not registered: ${s.schemaId}:${s.source}`,{schemaId:s.schemaId,source:s.source});if(a.connectionId!==i.connectionId)throw new S("CROSS_CONNECTION_QUERY_UNSUPPORTED",`One physical query cannot use multiple database connections: ${i.connectionId}, ${a.connectionId}`,{schemaId:s.schemaId,source:s.source,connectionId:a.connectionId})}},ke=n=>{const i=new Set,s=a=>{a.schema&&i.add(a.schema),a.from&&s(a.from);for(const P of a.logicforms??[])s(P)};return s(n),[...i]},de=async(n,i)=>{const s=i.plugins??[],a=n.version,P=typeof a=="string"&&(/^2\./.test(a)||/^[3-9]\d*\./.test(a)),N=a===void 0||typeof a=="string"&&/^1\./.test(a);P&&qe(n);const v=N?Te(je(n),i.schemas):n,e={...i,schemas:Ue(i.schemas,s,N)},f=ae.now(),D=e.semanticTypes??Ne(),c=e.operators?new Fe(e.operators.definitions()):Re(s);if(e.operators)for(const t of s)for(const r of t.operators??[])if(c.has(r.name)){if(c.get(r.name)!==r)throw new S("PLUGIN_OPERATOR_ALREADY_REGISTERED",`Plugin Operator is already registered: ${r.name}`,{operator:r.name,plugin:t.name})}else c.register(r);e.customFunctions&&Le(c,{schemas:e.schemas,customFunctions:e.customFunctions,definitions:Ae(e.customFunctions),config:{...e.customFunctionConfig??{},...e.permissions?{permissions:e.permissions}:{}},...e.permissions?{permissions:e.permissions}:{},...e.locale?{locale:e.locale}:{}});const L=e.schemaMappings,se=new Map;let q={provider:e.provider.kind};const O=[],T=(t,r)=>{O.push(be(Se(t),e.provider,r)),q={...q,sqls:[...O]}},w=async(t,r={})=>{q={...q,...r},await $e(e.onProgress,t,q)},te=t=>Me(Ie(t,e.schemas),D,s),Y=new Map,g=t=>{const r=Y.get(t);return r||(Ce(e.permissions,t),te(t))},j=t=>{if(t.schema)return g(t.schema);if(t.from)return j(t.from);const r=t.logicforms?.[0];if(r)return j(r);throw new S("LOGICFORM_SCHEMA_REQUIRED","A LogicForm must contain a physical schema leaf")},x={resolveSchema:g,canUsePropertyRowIdentity:(t,r)=>V(e.permissions,t.id,r)},H=(t,r)=>{const h=De(z(t,j(t),c,L,x),r);return Y.set(h.id,h),h},J=async(t,r)=>{const h=`${t.id}:${r}`,K=se.get(h);if(K)return K;const d=(async()=>{const W=oe({version:v.version,schema:t.id,preds:[{operator:"$max",pred:r,name:"__latestDataDate__"}]},e.permissions,g,!1,new Set,s),A=await G(W,t,{semanticTypes:D,operators:c,plugins:s,...e.locale?{locale:e.locale}:{},resolveSchema:g}),_=z(A,t,c,L,x);pe(_,e);const U=Z(_,e.provider,c);T(U,"semantic-resolution");const I=(await B(U,Q(_),e))[0],y=I?.__latestDataDate__??Object.values(I??{})[0];if(y==null||!(y instanceof Date)&&typeof y!="string"&&typeof y!="number")return;const $=y instanceof Date?y:new Date(y);if(!Number.isNaN($.getTime()))return $})();return se.set(h,d),d};try{e.signal?.throwIfAborted(),ve(v),await w({stage:"started",logicform:v}),_e(e.permissions,te);const t=j(v);await w({stage:"validated",schema:t});const r=oe(v,e.permissions,g,!0,new Set,s),h=await G(r,t,{semanticTypes:D,operators:c,plugins:s,...e.locale?{locale:e.locale}:{},resolveSchema:g,resolveFromSchema:H,canProjectProperty:(o,l)=>V(e.permissions,o.id,l),requestLatestDataDate:(o,l)=>J(o,l.id)}),K=e.customFunctions?await G(v,t,{semanticTypes:D,operators:c,plugins:s,...e.locale?{locale:e.locale}:{},resolveSchema:g,resolveFromSchema:H,canProjectProperty:(o,l)=>V(e.permissions,o.id,l),requestLatestDataDate:(o,l)=>J(o,l.id)}):void 0;await w({stage:"normalized",normedLogicform:h},{normedLogicform:h});const d=z(h,t,c,L,x);pe(d,e);const W=d.columnProperties??[],A=Pe(d,t);Y.set(A.id,A),await w({stage:"planned",plan:d},{schema:A});const _=Ee(d,t,e.provider,c);await w({stage:"lineage",lineage:_},{lineage:_});const U=ce(h,d,t,c,g,K),F=async o=>{const l=j(o.logicform),R=o.prepare?await G(oe(o.logicform,e.permissions,g,!0,new Set,s),l,{semanticTypes:D,operators:c,plugins:s,...e.locale?{locale:e.locale}:{},resolveSchema:g,resolveFromSchema:H,canProjectProperty:(m,E)=>V(e.permissions,m.id,E),requestLatestDataDate:(m,E)=>J(m,E.id)}):o.logicform,p=z(R,l,c,L,x),C=ce(R,p,l,c,g,o.logicform);if(C){if(C.length!==1)throw new Error("A generated component must produce exactly one execution unit");const m=C[0];if(m.kind==="query"){const u=await F(m),b=u.component.mapResult,k=o.mapResult;return{...u,component:{...o,logicform:u.component.logicform,...b||k?{mapResult:ne=>{const re=b?.(ne)??[...ne];return k?.(re)??[...re]}}:{}}}}if(m.kind==="js")throw new S("UNSUPPORTED_NESTED_JS_COMPONENT","A JavaScript composite metric cannot currently be nested as a generated component");const E=await Promise.all(m.components.map(async u=>({name:u.name,prepared:await F(u.component),...u.component.groupKeyShifts?{groupKeyShifts:u.component.groupKeyShifts}:{},...u.joinKeys?{joinKeys:u.joinKeys}:{}}))),M=ie(m,E.map(({name:u,prepared:b,...k})=>({name:u,plan:b.plan,...k})),p,e.provider,c);return{component:{...o,logicform:R},plan:p,compiled:M,sources:me(E.map(({prepared:u})=>u.sources))}}return{component:{...o,logicform:R},plan:p,compiled:Z(p,e.provider,c),sources:Q(p)}},I=U?await Promise.all(U.map(async o=>{if(o.kind==="query")return{kind:"query",unit:o,...await F(o)};const l=await Promise.all(o.components.map(async p=>({name:p.name,prepared:await F(p.component),...p.component.groupKeyShifts?{groupKeyShifts:p.component.groupKeyShifts}:{},...p.joinKeys?{joinKeys:p.joinKeys}:{}})));if(o.kind==="js")return{kind:"js",unit:o,components:l.map(({prepared:p})=>p)};const R=l.map(({name:p,prepared:C,...m})=>({name:p,plan:C.plan,...m}));return{kind:"cte",unit:o,plan:d,compiled:ie(o,R,d,e.provider,c),sources:me(l.map(({prepared:p})=>p.sources))}})):void 0,y=I?void 0:Z(d,e.provider,c);if(I)for(const o of I)if(o.kind==="js")for(const l of o.components)T(l.compiled,"computation");else T(o.compiled,"computation");else T(y,"computation");await w({stage:"compiled",sqls:[...O]},{sqls:[...O]}),await w({stage:"executing",provider:e.provider.kind});const $=I?fe(await Promise.all(I.map(async o=>{if(o.kind==="js"){const p=await Promise.all(o.components.map(async m=>{const E=await B(m.compiled,m.sources,e),M=await ee(E,m.plan.projections,c);return m.component.mapResult?.(M)??M})),C=o.unit.components.map(({name:m})=>m);return Promise.all(ge(p,d.groupBy.map(({name:m})=>m)).map(async m=>{const E=await o.unit.mergeRow(m);return{...o.unit.exposeComponents?m:Object.fromEntries(Object.entries(m).filter(([u])=>!C.includes(u))),[o.unit.outputName]:E}}))}const l=await B(o.compiled,o.sources,e),R=o.kind==="query"?await ee(l,o.plan.projections,c):l;return o.kind==="query"?o.unit.mapResult?.(R)??R:R})),d):await(async()=>{const o=await B(y,Q(d),e);return ee(o,d.projections,c)})();await w({stage:"hydrating"});const ue=await we($,W,{semanticTypes:D,resolveSchema:g,fetchEntities:o=>he(o,{version:h.version,operators:c,schemaMappings:L,semanticTypes:D,plugins:s,...e.locale?{locale:e.locale}:{},resolveSchema:g,...e.permissions?{permissions:e.permissions}:{},provider:e.provider,...e.cache?{cache:e.cache}:{},...e.signal?{signal:e.signal}:{},onCompiled:l=>T(l,"semantic-resolution")})}),X=ye(ue,d.rowIdentity);return await w({stage:"result",result:X},{result:X,sqls:[...O]}),await w({stage:"completed",durationMs:ae.now()-f}),{result:X,schema:A,normedLogicform:h,sqls:[...O],lineage:_,provider:e.provider.kind}}catch(t){const r=le(t);try{await w({stage:"failed",error:r})}catch{}throw r}},Qe=async(n,i)=>{let s={};try{if(i.connections.length===0)throw new S("DATABASE_CONNECTION_REQUIRED","At least one database connection is required");const a=new Map;for(const f of i.connections){if(f.id.trim().length===0)throw new S("INVALID_DATABASE_CONNECTION","Database connection id must not be empty");if(a.has(f.id))throw new S("DATABASE_CONNECTION_ALREADY_REGISTERED",`Database connection id is duplicated: ${f.id}`,{connectionId:f.id});a.set(f.id,f)}const P=new Set;for(const f of ke(n))for(const D of i.schemaMappings.list(f))P.add(D.connectionId);if(P.size>1)throw new S("CROSS_CONNECTION_QUERY_UNSUPPORTED",`One LogicForm cannot compile into SQL for multiple database connections: ${[...P].join(", ")}`,{connectionIds:[...P]});const[N]=P;if(!N)throw new S("LOGICFORM_SCHEMA_REQUIRED","A LogicForm must contain at least one physical Schema leaf");const v=a.get(N);if(!v)throw new S("DATABASE_CONNECTION_NOT_FOUND",`Database connection is not registered: ${N}`,{connectionId:N});const e=Oe(v);return s={provider:e.kind},await de(n,{...i,provider:e,connectionId:v.id,onProgress:async f=>{s=f.partialResult,await i.onProgress?.(f)}})}catch(a){return Ke(a,n,s)}};export{Qe as execute,de as executeWithProvider};
@@ -0,0 +1,26 @@
1
+ import type { OperatorRegistry } from '../operators/index';
2
+ import type { DataRow } from '../physical/index';
3
+ import type { SchemaMappingRegistry } from '../schema-mappings/index';
4
+ import type { QueryCacheExecutionOptions } from '../cache/index';
5
+ import type { CoreComputeProvider } from '../physical/index';
6
+ import type { CompiledQuery } from '../compiler/index';
7
+ import type { Permissions } from '../permissions/index';
8
+ import type { ResolvedSemanticSchema, SemanticTypeRegistry } from '../semantic-types/index';
9
+ import type { EntityFetchRequest } from './result-hydrator/index';
10
+ import type { SemanticDBPlugin } from '../plugins/index';
11
+ interface FetchEntityOptions {
12
+ readonly version: string;
13
+ readonly operators: OperatorRegistry;
14
+ readonly locale?: string;
15
+ readonly schemaMappings: SchemaMappingRegistry;
16
+ readonly semanticTypes: SemanticTypeRegistry;
17
+ readonly plugins?: readonly SemanticDBPlugin[];
18
+ readonly resolveSchema: (schemaId: string) => ResolvedSemanticSchema;
19
+ readonly permissions?: Permissions;
20
+ readonly provider: CoreComputeProvider;
21
+ readonly cache?: QueryCacheExecutionOptions;
22
+ readonly signal?: AbortSignal;
23
+ readonly onCompiled?: (compiled: CompiledQuery) => void;
24
+ }
25
+ export declare const fetchEntities: (request: EntityFetchRequest, options: FetchEntityOptions) => Promise<DataRow[]>;
26
+ export {};
@@ -0,0 +1 @@
1
+ import{compilePlan as h}from"../compiler/compile-plan.js";import"../operators/index.js";import{SemanticDBError as d}from"../errors.js";import{createLogicalPlan as y}from"../planner/create-logical-plan.js";import{normalizeLogicform as f}from"../normalizer/normalize-logicform.js";import{isColumnAllowed as l,applyPermissions as g}from"../permissions/permissions.js";import{addRowIdentities as v}from"./row-identity.js";import{executeCompiledQuery as u,collectPlanSources as w}from"./execute-query.js";const P=r=>{if(r.every(e=>typeof e=="string"))return[...r];if(r.every(e=>typeof e=="number"))return[...r];if(r.every(e=>typeof e=="boolean"))return[...r];throw new TypeError("Entity IDs must have one scalar type")},S=(r,e,a)=>{const c=P(e);if(!a||c.length<=a)return{[r]:{$in:c}};const n=[];for(let m=0;m<c.length;m+=a)n.push({[r]:{$in:c.slice(m,m+a)}});return{$or:n}},E=async(r,e)=>{if(!l(e.permissions,r.schema.id,r.idProperty))throw new d("COLUMN_PERMISSION_DENIED",`Entity hydration requires the ID property in the column permissions: ${r.schema.id}.${r.idProperty.name}`,{schemaId:r.schema.id,property:r.idProperty.name});const a=r.schema.properties.filter(i=>l(e.permissions,r.schema.id,i)),c={version:e.version,schema:r.schema.id,query:S(r.idProperty.name,r.ids,e.provider.maxInListItems),preds:a.map(i=>({pred:i.name,name:i.name}))},n=g(c,e.permissions,e.resolveSchema,!0,new Set,e.plugins),m=await f(n,r.schema,{semanticTypes:e.semanticTypes,operators:e.operators,...e.plugins?{plugins:e.plugins}:{},...e.locale?{locale:e.locale}:{},resolveSchema:e.resolveSchema}),o=y(m,r.schema,e.operators,e.schemaMappings,{resolveSchema:e.resolveSchema,canUsePropertyRowIdentity:(i,p)=>l(e.permissions,i.id,p)}),s=h(o,e.provider,e.operators);e.onCompiled?.(s);const t=await u(s,w(o),{provider:e.provider,schemaMappings:e.schemaMappings,...e.cache?{cache:e.cache}:{},...e.signal?{signal:e.signal}:{}});return v(t,o.rowIdentity)};export{E as fetchEntities};
@@ -0,0 +1,3 @@
1
+ export { execute } from './execute';
2
+ export { closeConnections } from './connection-registry';
3
+ export type { ExecuteOptions, ExecuteFailureResult, ExecuteProgressEvent, ExecuteResult, ExecuteSuccessResult, ExecutedSql, ExecutedSqlType, PartialExecuteResult, ProgressCallback, } from './types';
@@ -0,0 +1,6 @@
1
+ import type { ResultHydratorOptions } from './types';
2
+ export declare class EntityLoader {
3
+ #private;
4
+ constructor(options: ResultHydratorOptions);
5
+ load: (schemaId: string, id: unknown) => Promise<unknown>;
6
+ }
@@ -0,0 +1 @@
1
+ import{SemanticDBError as m}from"../../errors.js";import{createMissingEntity as u}from"./missing-entity.js";const y=(r,t)=>`${r}:${String(t)}`,w=r=>{const t=r.properties.filter(({type:e})=>e==="ID"),i=t[0];if(t.length!==1||!i)throw new m("RELATION_TARGET_ID_REQUIRED",`Relation target ${r.id} must contain exactly one ID property`,{schemaId:r.id,count:t.length});return i};class P{#s;#o=new Map;#t=new Map;#e=new Map;#i=!1;constructor(t){this.#s=t}load=(t,i)=>{const e=y(t,i),n=this.#o.get(e);if(n)return Promise.resolve(n);const s=this.#t.get(e);if(s)return s;const o=this.#s.resolveSchema(t),a=w(o);let d,l;const h=new Promise((c,p)=>{d=c,l=p}),f=this.#e.get(t)??{schema:o,idProperty:a,loads:new Map};return f.loads.set(e,{id:i,resolve:c=>d?.(c),reject:c=>l?.(c)}),this.#e.set(t,f),this.#t.set(e,h),this.#n(),h};#n(){this.#i||(this.#i=!0,queueMicrotask(()=>{this.#r()}))}async#r(){this.#i=!1;const t=this.#e;this.#e=new Map,await Promise.all([...t.values()].map(i=>this.#c(i)))}async#c(t){const i={schema:t.schema,idProperty:t.idProperty,ids:[...t.loads.values()].map(({id:e})=>e)};try{const e=await this.#s.fetchEntities(i),n=new Map;for(const s of e){const o=s[t.idProperty.name]??s._id;o!=null&&n.set(y(t.schema.id,o),s)}for(const[s,o]of t.loads){const a=n.get(s)??u(t.schema,t.idProperty,o.id);this.#o.set(s,a),this.#t.delete(s),o.resolve(a)}}catch(e){for(const[n,s]of t.loads)this.#t.delete(n),s.reject(e)}}}export{P as EntityLoader};
@@ -0,0 +1,4 @@
1
+ import type { DataRow } from '../../physical/index';
2
+ import type { SemanticTypeRegistry } from '../../semantic-types/index';
3
+ import type { HydrationProperty } from './types';
4
+ export declare const formatResultValues: (rows: readonly DataRow[], properties: readonly HydrationProperty[], semanticTypes: SemanticTypeRegistry, requestEntity: (schemaId: string, id: unknown) => Promise<unknown>) => Promise<void>;
@@ -0,0 +1 @@
1
+ import{SemanticDBError as l}from"../../errors.js";const A=(n,s)=>{if(!s.isArray||typeof n!="string")return n;const t=n.trim();if(!t.startsWith("[")||!t.endsWith("]"))return n;try{const r=JSON.parse(t);if(!Array.isArray(r))throw new Error("JSON result is not an array");return r}catch(r){throw new l("INVALID_ARRAY_RESULT",`Result column ${s.name} contains invalid array JSON`,{property:s.name,cause:r})}},o=async(n,s,t,r)=>{await Promise.all(n.map(async i=>{await Promise.all(s.map(async a=>{if(!(a.name in i))return;const e=A(i[a.name],a),m=t.get(a.type).hydrateResult;if(!m){i[a.name]=e;return}i[a.name]=a.isArray&&Array.isArray(e)?await Promise.all(e.map(c=>m(c,{property:a,requestEntity:r}))):await m(e,{property:a,requestEntity:r})}))}))};export{o as formatResultValues};
@@ -0,0 +1,4 @@
1
+ import type { ResultProperty } from '../../operators/index';
2
+ import type { DataRow } from '../../physical/index';
3
+ import type { ResultHydratorOptions } from './types';
4
+ export declare const hydrateResult: (rows: readonly DataRow[], properties: readonly ResultProperty[], options: ResultHydratorOptions) => Promise<DataRow[]>;
@@ -0,0 +1 @@
1
+ import{populateEntities as n}from"./populate-entities.js";const p=async(a,e,r)=>{const t=a.map(o=>({...o}));return await n(t,e,r),t};export{p as hydrateResult};
@@ -0,0 +1,2 @@
1
+ export { hydrateResult } from './hydrate-result';
2
+ export type { EntityFetchRequest, ResultHydratorOptions } from './types';
@@ -0,0 +1,3 @@
1
+ import type { DataRow } from '../../physical/index';
2
+ import type { ResolvedSemanticProperty, ResolvedSemanticSchema } from '../../semantic-types/index';
3
+ export declare const createMissingEntity: (schema: ResolvedSemanticSchema, idProperty: ResolvedSemanticProperty, id: unknown) => DataRow;
@@ -0,0 +1 @@
1
+ const r=n=>String(n),a=(n,i,s)=>{const o=`\u6570\u636E\u5E93\u4E2D\u672A\u627E\u5230 ID \u4E3A\u300C${r(s)}\u300D\u7684\u5B9E\u4F53`,t={};for(const e of n.properties)e.id===i.id?t[e.name]=s:e.isArray?t[e.name]=[]:t[e.name]=e.primal_type==="string"?o:null;return t._id=r(s),t};export{a as createMissingEntity};
@@ -0,0 +1,3 @@
1
+ import type { DataRow } from '../../physical/index';
2
+ import type { HydrationProperty, ResultHydratorOptions } from './types';
3
+ export declare const populateEntities: (rootRows: DataRow[], rootProperties: readonly HydrationProperty[], options: ResultHydratorOptions) => Promise<void>;
@@ -0,0 +1 @@
1
+ import{EntityLoader as A}from"./entity-loader.js";import{formatResultValues as x}from"./format-values.js";const m=5,E=t=>typeof t=="object"&&t!==null&&!Array.isArray(t)&&!(t instanceof Date),_=(t,o)=>{const e=o.properties.find(({type:n})=>n==="ID");return e?t[e.name]:void 0},h=(t,o)=>{const e=structuredClone(t);if(!("_id"in e)){const n=_(e,o);(typeof n=="string"||typeof n=="number"||typeof n=="boolean")&&(e._id=String(n))}return e},b=(t,o,e,n)=>{const s=`${o.id}:${n?"recursive":"leaf"}`,a=t.get(s);if(a){a.rows.push(e);return}t.set(s,{rows:[e],properties:o.properties,expandEntities:n})},g=async(t,o,e)=>{const n=new A(e);let s=[{rows:t,properties:o,expandEntities:!0}];for(let a=0;s.length>0;a+=1){if(await Promise.all(s.map(i=>{const r=i.expandEntities&&a<m;return x(i.rows,i.properties,e.semanticTypes,r?n.load:(p,c)=>Promise.resolve(c))})),a>=m)return;const u=new Map;for(const i of s)if(i.expandEntities)for(const r of i.properties){if(r.primal_type!=="object"||!r.ref)continue;const p=e.resolveSchema(r.ref);for(const c of i.rows){if(!(r.name in c))continue;const f=c[r.name],d=r.isArray?Array.isArray(f)?f:[f]:[f];for(const[w,y]of d.entries()){if(!E(y))continue;const l=h(y,p);r.isArray?d[w]=l:c[r.name]=l,b(u,p,l,!r.isArray)}r.isArray&&(c[r.name]=d)}}s=[...u.values()]}};export{g as populateEntities};
@@ -0,0 +1,14 @@
1
+ import type { ResultProperty } from '../../operators/index';
2
+ import type { DataRow } from '../../physical/index';
3
+ import type { ResolvedSemanticProperty, ResolvedSemanticSchema, SemanticTypeRegistry } from '../../semantic-types/index';
4
+ export type HydrationProperty = Pick<ResultProperty, 'isArray' | 'name' | 'primal_type' | 'ref' | 'type'> | ResolvedSemanticProperty;
5
+ export interface EntityFetchRequest {
6
+ readonly schema: ResolvedSemanticSchema;
7
+ readonly idProperty: ResolvedSemanticProperty;
8
+ readonly ids: readonly unknown[];
9
+ }
10
+ export interface ResultHydratorOptions {
11
+ readonly semanticTypes: SemanticTypeRegistry;
12
+ readonly resolveSchema: (schemaId: string) => ResolvedSemanticSchema;
13
+ readonly fetchEntities: (request: EntityFetchRequest) => Promise<readonly DataRow[]>;
14
+ }
@@ -0,0 +1,4 @@
1
+ import type { DataRow } from '../physical/index';
2
+ import type { RowIdentityPlan } from '../planner/index';
3
+ export declare const groupRowIdentity: (row: DataRow, names: readonly string[]) => string;
4
+ export declare const addRowIdentities: (rows: readonly DataRow[], identity: RowIdentityPlan) => DataRow[];
@@ -0,0 +1 @@
1
+ import{randomUUID as e}from"node:crypto";const p=n=>{if(n&&typeof n=="object"){if("_id"in n)return String(n._id);if("id"in n)return String(n.id)}return String(n)},t=(n,r)=>r.map(i=>p(n[i])).join(""),s=(n,r)=>n.map(i=>{if(r.kind==="property"){const{[r.internalName]:o,...d}=i;return{...d,_id:String(o)}}return r.kind==="group"?{...i,_id:t(i,r.names)}:{...i,_id:r.kind==="singleton"?"0":e()}});export{s as addRowIdentities,t as groupRowIdentity};