ts-prorm-orm 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/CHANGELOG.md +1111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/dist/audit/history-query.js +180 -0
  5. package/dist/audit/index.js +23 -0
  6. package/dist/audit/logger.js +236 -0
  7. package/dist/cache/cache-manager.js +84 -0
  8. package/dist/cache/index.js +16 -0
  9. package/dist/cache/redis-cluster-cache.js +557 -0
  10. package/dist/cli.js +2200 -0
  11. package/dist/compliance/audit-trail.js +68 -0
  12. package/dist/compliance/backup-verification.js +685 -0
  13. package/dist/compliance/breach-detector.js +505 -0
  14. package/dist/compliance/consent-record.js +227 -0
  15. package/dist/compliance/consent-versioning.js +331 -0
  16. package/dist/compliance/cross-border-log.js +530 -0
  17. package/dist/compliance/data-classifier.js +258 -0
  18. package/dist/compliance/data-lineage.js +565 -0
  19. package/dist/compliance/data-masker.js +303 -0
  20. package/dist/compliance/data-portability.js +265 -0
  21. package/dist/compliance/data-retention.js +195 -0
  22. package/dist/compliance/dsar-workflow.js +342 -0
  23. package/dist/compliance/field-encryption.js +223 -0
  24. package/dist/compliance/immutable-record.js +148 -0
  25. package/dist/compliance/index.js +260 -0
  26. package/dist/compliance/privacy-impact-assessment.js +364 -0
  27. package/dist/compliance/pseudonymization.js +269 -0
  28. package/dist/compliance/query-firewall.js +1182 -0
  29. package/dist/compliance/rate-limiter.js +580 -0
  30. package/dist/compliance/right-to-erasure.js +117 -0
  31. package/dist/compliance/row-level-security.js +246 -0
  32. package/dist/compliance/security-decorator.js +574 -0
  33. package/dist/compliance/security-monitor.js +525 -0
  34. package/dist/compliance/sensitive-data-discovery.js +476 -0
  35. package/dist/compliance/session-isolation.js +472 -0
  36. package/dist/compliance/tls-enforcer.js +108 -0
  37. package/dist/compliance/worm-storage.js +712 -0
  38. package/dist/connection-manager.js +198 -0
  39. package/dist/connection-pool.js +519 -0
  40. package/dist/decorators/audit.js +136 -0
  41. package/dist/decorators/belongs-to-many.js +115 -0
  42. package/dist/decorators/belongs-to.js +115 -0
  43. package/dist/decorators/check.js +435 -0
  44. package/dist/decorators/collate.js +329 -0
  45. package/dist/decorators/comment.js +205 -0
  46. package/dist/decorators/database-settings.js +236 -0
  47. package/dist/decorators/default.js +244 -0
  48. package/dist/decorators/encryption.js +235 -0
  49. package/dist/decorators/engine.js +97 -0
  50. package/dist/decorators/fk-constraints.js +594 -0
  51. package/dist/decorators/foreign-table.js +136 -0
  52. package/dist/decorators/generated.js +274 -0
  53. package/dist/decorators/has-many.js +127 -0
  54. package/dist/decorators/has-one.js +116 -0
  55. package/dist/decorators/hstore.js +129 -0
  56. package/dist/decorators/index.js +355 -0
  57. package/dist/decorators/json-column.js +83 -0
  58. package/dist/decorators/jsonb.js +101 -0
  59. package/dist/decorators/orm-decorators.js +425 -0
  60. package/dist/decorators/permissions.js +294 -0
  61. package/dist/decorators/procedure.js +210 -0
  62. package/dist/decorators/query-options.js +556 -0
  63. package/dist/decorators/range.js +167 -0
  64. package/dist/decorators/set-column.js +83 -0
  65. package/dist/decorators/spatial.js +114 -0
  66. package/dist/decorators/storage.js +580 -0
  67. package/dist/decorators/timezone.js +512 -0
  68. package/dist/decorators/trigger.js +90 -0
  69. package/dist/decorators/uuid.js +135 -0
  70. package/dist/decorators/view.js +258 -0
  71. package/dist/diagrams/chen-diagram.js +354 -0
  72. package/dist/diagrams/class-diagram.js +384 -0
  73. package/dist/diagrams/dependency-diagram.js +432 -0
  74. package/dist/diagrams/er-diagram.js +605 -0
  75. package/dist/diagrams/flow-diagram.js +394 -0
  76. package/dist/diagrams/gantt-diagram.js +411 -0
  77. package/dist/diagrams/index-diagram.js +353 -0
  78. package/dist/diagrams/index.js +184 -0
  79. package/dist/diagrams/migration-diagram.js +316 -0
  80. package/dist/diagrams/model-diagram.js +616 -0
  81. package/dist/diagrams/package-diagram.js +376 -0
  82. package/dist/diagrams/palette.js +85 -0
  83. package/dist/diagrams/relational-diagram.js +455 -0
  84. package/dist/diagrams/schemadoc-diagram.js +309 -0
  85. package/dist/diagrams/sequence-diagram.js +307 -0
  86. package/dist/diagrams/state-diagram.js +344 -0
  87. package/dist/diagrams/svg-dom.js +111 -0
  88. package/dist/diagrams/tree-diagram.js +250 -0
  89. package/dist/dialects/clickhouse/index.js +1742 -0
  90. package/dist/dialects/cockroachdb/index.js +4677 -0
  91. package/dist/dialects/cratedb/index.js +441 -0
  92. package/dist/dialects/databricks/index.js +517 -0
  93. package/dist/dialects/db2/index.js +2225 -0
  94. package/dist/dialects/dialect.js +720 -0
  95. package/dist/dialects/duckdb/index.js +2014 -0
  96. package/dist/dialects/exasol/index.js +357 -0
  97. package/dist/dialects/firebird/index.js +495 -0
  98. package/dist/dialects/greenplum/index.js +457 -0
  99. package/dist/dialects/hana/index.js +1741 -0
  100. package/dist/dialects/mariadb/index.js +3590 -0
  101. package/dist/dialects/mssql/index.js +2296 -0
  102. package/dist/dialects/mysql/index.js +4058 -0
  103. package/dist/dialects/oracle/index.js +2999 -0
  104. package/dist/dialects/postgres/index.js +5319 -0
  105. package/dist/dialects/query-stream-helper.js +152 -0
  106. package/dist/dialects/questdb/index.js +433 -0
  107. package/dist/dialects/redshift/index.js +2277 -0
  108. package/dist/dialects/singlestore/index.js +354 -0
  109. package/dist/dialects/snowflake/index.js +2082 -0
  110. package/dist/dialects/spanner/index.js +1768 -0
  111. package/dist/dialects/sqlite/index.js +3382 -0
  112. package/dist/dialects/tidb/index.js +377 -0
  113. package/dist/dialects/timescaledb/index.js +164 -0
  114. package/dist/dialects/trino/index.js +420 -0
  115. package/dist/dialects/turso/index.js +227 -0
  116. package/dist/dialects/vertica/index.js +317 -0
  117. package/dist/dialects/yugabytedb/index.js +424 -0
  118. package/dist/errors/index.js +472 -0
  119. package/dist/errors/utils.js +340 -0
  120. package/dist/errors.js +21 -0
  121. package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
  122. package/dist/extensions/catalog/mssql-features.js +147 -0
  123. package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
  124. package/dist/extensions/catalog/oracle-db2-features.js +196 -0
  125. package/dist/extensions/catalog/postgres-extensions.js +516 -0
  126. package/dist/extensions/index.js +71 -0
  127. package/dist/extensions/types.js +13 -0
  128. package/dist/foreign-data.js +173 -0
  129. package/dist/hooks/hooks-manager.js +350 -0
  130. package/dist/hooks/index.js +37 -0
  131. package/dist/index.js +463 -0
  132. package/dist/logging.js +335 -0
  133. package/dist/migrations/index.js +40 -0
  134. package/dist/migrations/migration.js +196 -0
  135. package/dist/migrations/migrator.js +411 -0
  136. package/dist/migrations/prormmigration.js +275 -0
  137. package/dist/migrations/query-interface.js +435 -0
  138. package/dist/migrations/seeder.js +353 -0
  139. package/dist/models/associations.js +852 -0
  140. package/dist/models/constraints.js +288 -0
  141. package/dist/models/data-types.js +2518 -0
  142. package/dist/models/decorators.js +445 -0
  143. package/dist/models/index.js +33 -0
  144. package/dist/models/indexes.js +531 -0
  145. package/dist/models/methods.js +382 -0
  146. package/dist/models/model-manager.js +103 -0
  147. package/dist/models/model.js +5349 -0
  148. package/dist/models/operators.js +67 -0
  149. package/dist/models/scopes.js +189 -0
  150. package/dist/models/typescript-types.js +26 -0
  151. package/dist/nosql/aerospike/index.js +205 -0
  152. package/dist/nosql/allegrograph/index.js +169 -0
  153. package/dist/nosql/arangodb/index.js +364 -0
  154. package/dist/nosql/azure-blob/index.js +206 -0
  155. package/dist/nosql/beanstalkd/index.js +231 -0
  156. package/dist/nosql/beequeue/index.js +210 -0
  157. package/dist/nosql/bigchaindb/index.js +195 -0
  158. package/dist/nosql/bigtable/index.js +224 -0
  159. package/dist/nosql/blazegraph/index.js +173 -0
  160. package/dist/nosql/bullmq/index.js +191 -0
  161. package/dist/nosql/cassandra/index.js +174 -0
  162. package/dist/nosql/chroma/index.js +190 -0
  163. package/dist/nosql/cloudflare-kv/index.js +220 -0
  164. package/dist/nosql/coherence/index.js +200 -0
  165. package/dist/nosql/cosmosdb/index.js +157 -0
  166. package/dist/nosql/couchbase/index.js +213 -0
  167. package/dist/nosql/dax/index.js +212 -0
  168. package/dist/nosql/deno-kv/index.js +206 -0
  169. package/dist/nosql/dgraph/index.js +171 -0
  170. package/dist/nosql/doris/index.js +169 -0
  171. package/dist/nosql/druid/index.js +162 -0
  172. package/dist/nosql/dynamodb/index.js +937 -0
  173. package/dist/nosql/elasticsearch/index.js +377 -0
  174. package/dist/nosql/etcd/index.js +502 -0
  175. package/dist/nosql/eventhubs/index.js +213 -0
  176. package/dist/nosql/eventstore/index.js +254 -0
  177. package/dist/nosql/faunadb/index.js +188 -0
  178. package/dist/nosql/firestore/index.js +177 -0
  179. package/dist/nosql/fluree/index.js +148 -0
  180. package/dist/nosql/fuseki/index.js +170 -0
  181. package/dist/nosql/gcs/index.js +172 -0
  182. package/dist/nosql/gearman/index.js +160 -0
  183. package/dist/nosql/geode/index.js +196 -0
  184. package/dist/nosql/graphdb/index.js +169 -0
  185. package/dist/nosql/graylog/index.js +188 -0
  186. package/dist/nosql/gridgain/index.js +171 -0
  187. package/dist/nosql/hazelcast/index.js +162 -0
  188. package/dist/nosql/hbase/index.js +230 -0
  189. package/dist/nosql/ignite/index.js +173 -0
  190. package/dist/nosql/immudb/index.js +184 -0
  191. package/dist/nosql/index.js +232 -0
  192. package/dist/nosql/infinispan/index.js +200 -0
  193. package/dist/nosql/influxdb/index.js +0 -0
  194. package/dist/nosql/kafka/index.js +234 -0
  195. package/dist/nosql/keyspaces/index.js +189 -0
  196. package/dist/nosql/kinesis/index.js +253 -0
  197. package/dist/nosql/leveldb/index.js +153 -0
  198. package/dist/nosql/lmdb/index.js +160 -0
  199. package/dist/nosql/loki/index.js +201 -0
  200. package/dist/nosql/marklogic/index.js +204 -0
  201. package/dist/nosql/materialize/index.js +145 -0
  202. package/dist/nosql/meilisearch/index.js +154 -0
  203. package/dist/nosql/memcached/index.js +223 -0
  204. package/dist/nosql/milvus/index.js +410 -0
  205. package/dist/nosql/minio/index.js +265 -0
  206. package/dist/nosql/momento/index.js +179 -0
  207. package/dist/nosql/mongodb/index.js +461 -0
  208. package/dist/nosql/nats/index.js +247 -0
  209. package/dist/nosql/nedb/index.js +164 -0
  210. package/dist/nosql/neo4j/index.js +450 -0
  211. package/dist/nosql/neptune/index.js +470 -0
  212. package/dist/nosql/nsq/index.js +200 -0
  213. package/dist/nosql/opensearch/index.js +186 -0
  214. package/dist/nosql/orientdb/index.js +175 -0
  215. package/dist/nosql/papertrail/index.js +200 -0
  216. package/dist/nosql/pinecone/index.js +0 -0
  217. package/dist/nosql/pinot/index.js +133 -0
  218. package/dist/nosql/pouchdb/index.js +172 -0
  219. package/dist/nosql/prometheus/index.js +174 -0
  220. package/dist/nosql/provendb/index.js +147 -0
  221. package/dist/nosql/pubsub/index.js +187 -0
  222. package/dist/nosql/pulsar/index.js +232 -0
  223. package/dist/nosql/qdrant/index.js +295 -0
  224. package/dist/nosql/qldb/index.js +192 -0
  225. package/dist/nosql/r2/index.js +281 -0
  226. package/dist/nosql/rabbitmq/index.js +237 -0
  227. package/dist/nosql/ravendb/index.js +175 -0
  228. package/dist/nosql/redis/index.js +607 -0
  229. package/dist/nosql/redpanda/index.js +237 -0
  230. package/dist/nosql/resque/index.js +203 -0
  231. package/dist/nosql/rethinkdb/index.js +232 -0
  232. package/dist/nosql/rocksdb/index.js +152 -0
  233. package/dist/nosql/rockset/index.js +126 -0
  234. package/dist/nosql/s3/index.js +298 -0
  235. package/dist/nosql/scylladb/index.js +178 -0
  236. package/dist/nosql/signoz/index.js +227 -0
  237. package/dist/nosql/sns/index.js +201 -0
  238. package/dist/nosql/solr/index.js +231 -0
  239. package/dist/nosql/splunk/index.js +227 -0
  240. package/dist/nosql/sqs/index.js +246 -0
  241. package/dist/nosql/stardog/index.js +169 -0
  242. package/dist/nosql/starrocks/index.js +170 -0
  243. package/dist/nosql/store.js +2 -0
  244. package/dist/nosql/sumologic/index.js +213 -0
  245. package/dist/nosql/surrealdb/index.js +179 -0
  246. package/dist/nosql/terminusdb/index.js +151 -0
  247. package/dist/nosql/tigergraph/index.js +469 -0
  248. package/dist/nosql/typesense/index.js +148 -0
  249. package/dist/nosql/unqlite/index.js +157 -0
  250. package/dist/nosql/upstash/index.js +167 -0
  251. package/dist/nosql/vercel-kv/index.js +166 -0
  252. package/dist/nosql/victoriametrics/index.js +213 -0
  253. package/dist/nosql/virtuoso/index.js +169 -0
  254. package/dist/nosql/weaviate/index.js +276 -0
  255. package/dist/operators/index.js +108 -0
  256. package/dist/operators.js +2690 -0
  257. package/dist/prisma-migrate/index.js +38 -0
  258. package/dist/prisma-migrate/migration-generator.js +125 -0
  259. package/dist/prisma-migrate/model-generator.js +172 -0
  260. package/dist/prisma-migrate/relations.js +100 -0
  261. package/dist/prisma-migrate/schema-parser.js +167 -0
  262. package/dist/prisma-migrate/type-mapper.js +40 -0
  263. package/dist/prorm.js +6832 -0
  264. package/dist/query-builders/cte-builder.js +80 -0
  265. package/dist/query-builders/functions/aggregate.js +390 -0
  266. package/dist/query-builders/functions/conditional.js +503 -0
  267. package/dist/query-builders/functions/datetime.js +695 -0
  268. package/dist/query-builders/functions/fulltext.js +439 -0
  269. package/dist/query-builders/functions/index.js +93 -0
  270. package/dist/query-builders/functions/json.js +427 -0
  271. package/dist/query-builders/functions/math.js +399 -0
  272. package/dist/query-builders/functions/string.js +518 -0
  273. package/dist/query-builders/functions/window.js +328 -0
  274. package/dist/query-builders/include-builder.js +323 -0
  275. package/dist/query-builders/index-expression-builder.js +242 -0
  276. package/dist/query-builders/index.js +161 -0
  277. package/dist/query-builders/insert-builder.js +164 -0
  278. package/dist/query-builders/model-helpers.js +38 -0
  279. package/dist/query-builders/order-limit-builder.js +239 -0
  280. package/dist/query-builders/sql-compiler.js +2040 -0
  281. package/dist/query-builders/subquery-builder.js +152 -0
  282. package/dist/query-builders/update-builder.js +182 -0
  283. package/dist/query-builders/view-builder.js +218 -0
  284. package/dist/query-builders/where-builder.js +1532 -0
  285. package/dist/query-interface.js +622 -0
  286. package/dist/query-optimizers/batch-optimizer.js +426 -0
  287. package/dist/query-optimizers/explain-plans.js +415 -0
  288. package/dist/query-optimizers/index.js +51 -0
  289. package/dist/query-optimizers/prepared-statement-cache.js +423 -0
  290. package/dist/query-optimizers/query-hints.js +438 -0
  291. package/dist/query-optimizers/query-optimizer.js +278 -0
  292. package/dist/query-optimizers/slow-query-logger.js +271 -0
  293. package/dist/replica-manager.js +507 -0
  294. package/dist/schema/index.js +15 -0
  295. package/dist/schema/migration-generator.js +374 -0
  296. package/dist/schema/schema-differ.js +549 -0
  297. package/dist/schema/types.js +6 -0
  298. package/dist/sql-constants.js +300 -0
  299. package/dist/sqlite-advanced.js +1047 -0
  300. package/dist/streams/index.js +12 -0
  301. package/dist/streams/transforms.js +178 -0
  302. package/dist/transaction.js +456 -0
  303. package/dist/types/index.js +180 -0
  304. package/dist/user-management.js +127 -0
  305. package/dist/utils/date.js +300 -0
  306. package/dist/utils/index.js +1079 -0
  307. package/dist/utils/string.js +161 -0
  308. package/dist/validators/index.js +19 -0
  309. package/dist/validators/validator.js +911 -0
  310. package/package.json +190 -0
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * CTE (Common Table Expression) Builder
4
+ * Provides an ORM-like way to build CTEs without raw SQL
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CTEBuilder = void 0;
8
+ exports.createCTEBuilder = createCTEBuilder;
9
+ class CTEBuilder {
10
+ constructor() {
11
+ this.ctes = [];
12
+ }
13
+ /**
14
+ * Add a simple CTE with a base query
15
+ * @example
16
+ * cte.add('active_users', { model: User, baseCase: { where: { active: true } } })
17
+ * cte.add('active_users', { model: 'users', baseCase: { where: { active: true } } })
18
+ */
19
+ add(name, options) {
20
+ this.ctes.push({
21
+ name,
22
+ model: options?.model,
23
+ columns: options?.columns,
24
+ baseCase: options?.baseCase,
25
+ });
26
+ return this;
27
+ }
28
+ /**
29
+ * Add a recursive CTE for hierarchical data
30
+ * @example
31
+ * cte.addRecursive({
32
+ * name: 'org_chart',
33
+ * model: Employee,
34
+ * anchor: { where: { managerId: null } },
35
+ * recursive: { where: { '$org_chart.id$': { [Op.eq]: { [Op.col]: 'Employee.managerId' } } } }
36
+ * })
37
+ */
38
+ addRecursive(options) {
39
+ this.ctes.push({
40
+ name: options.name,
41
+ model: options.model,
42
+ columns: options.columns,
43
+ baseCase: options.anchor,
44
+ recursiveCase: options.recursive,
45
+ });
46
+ return this;
47
+ }
48
+ /**
49
+ * Get all CTEs
50
+ */
51
+ getCTEs() {
52
+ return this.ctes;
53
+ }
54
+ /**
55
+ * Get CTE names
56
+ */
57
+ getCTENames() {
58
+ return this.ctes.map(cte => cte.name);
59
+ }
60
+ /**
61
+ * Build the WITH clause SQL
62
+ */
63
+ toSQL(dialect) {
64
+ return this.ctes.map(cte => cte.name).join(', ');
65
+ }
66
+ /**
67
+ * Clear all CTEs
68
+ */
69
+ clear() {
70
+ this.ctes = [];
71
+ }
72
+ }
73
+ exports.CTEBuilder = CTEBuilder;
74
+ /**
75
+ * Create a new CTE builder
76
+ */
77
+ function createCTEBuilder() {
78
+ return new CTEBuilder();
79
+ }
80
+ exports.default = { CTEBuilder, createCTEBuilder };
@@ -0,0 +1,390 @@
1
+ "use strict";
2
+ /**
3
+ * Typed aggregate-function builder API.
4
+ *
5
+ * `COUNT`/`SUM`/`AVG`/`MIN`/`MAX` are already reachable through the generic
6
+ * `fn('SUM', col('amount'))` pattern in `src/operators.ts` because those
7
+ * names are ANSI-identical across every dialect this ORM supports. This
8
+ * module fills the real gap: aggregate functions whose *name* (and in some
9
+ * cases clause placement) differs per dialect, most notably string
10
+ * aggregation (`GROUP_CONCAT` / `STRING_AGG` / `LISTAGG` / ClickHouse's
11
+ * array-based approach) and array aggregation (`ARRAY_AGG` / `JSON_ARRAYAGG`
12
+ * / `groupArray`).
13
+ *
14
+ * This module is intentionally self-contained: it does not add any new
15
+ * dispatch branches to the shared SQL compiler (`src/query-builders/sql-compiler.ts`)
16
+ * or touch `src/operators.ts`. Every builder function computes a final,
17
+ * dialect-correct SQL fragment string directly and wraps it with the
18
+ * existing `literalExpr()` helper from `src/operators.ts` so it slots into
19
+ * `attributes: [...]` arrays exactly the way `fn()`/`col()`/`cast()` do
20
+ * today (see `attributeToSql()` in `sql-compiler.ts`, which already knows
21
+ * how to render `{ __type: 'literal', sql }` and `[expr, alias]` tuples).
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { count, countDistinct, sum, stringAgg, arrayAgg } from './query-builders/functions/aggregate';
26
+ * import { col } from '../../operators';
27
+ *
28
+ * User.findAll({
29
+ * attributes: [
30
+ * 'department',
31
+ * [count('postgres'), 'total'],
32
+ * [countDistinct('postgres', col('email')), 'uniqueEmails'],
33
+ * [stringAgg('postgres', col('name'), ', ', { orderBy: 'name' }), 'names'],
34
+ * [arrayAgg('postgres', col('id')), 'ids'],
35
+ * ],
36
+ * group: ['department'],
37
+ * });
38
+ * ```
39
+ */
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.count = count;
42
+ exports.countDistinct = countDistinct;
43
+ exports.sum = sum;
44
+ exports.avg = avg;
45
+ exports.min = min;
46
+ exports.max = max;
47
+ exports.stringAgg = stringAgg;
48
+ exports.arrayAgg = arrayAgg;
49
+ const operators_1 = require("../../operators");
50
+ // ---------------------------------------------------------------------------
51
+ // Shared helpers (mirrors the pattern used in ./window.ts)
52
+ // ---------------------------------------------------------------------------
53
+ function escapeIdentifier(name) {
54
+ // Support dotted "table.column" references, same convention as col().
55
+ if (name.includes('.')) {
56
+ return name
57
+ .split('.')
58
+ .map((part) => `"${part.replace(/"/g, '""')}"`)
59
+ .join('.');
60
+ }
61
+ return `"${name.replace(/"/g, '""')}"`;
62
+ }
63
+ /**
64
+ * Flatten an aggregate-function argument (string, ColExpression,
65
+ * FnExpression, LiteralExpression) into a raw SQL fragment string.
66
+ */
67
+ function toSqlFragment(arg) {
68
+ if (typeof arg === 'string') {
69
+ return escapeIdentifier(arg);
70
+ }
71
+ if ((0, operators_1.isFnExpression)(arg)) {
72
+ const args = arg.args.map((a) => toSqlFragment(a)).join(', ');
73
+ return `${arg.fn}(${args})`;
74
+ }
75
+ if ((0, operators_1.isColExpression)(arg)) {
76
+ return escapeIdentifier(arg.col);
77
+ }
78
+ if ((0, operators_1.isLiteralExpression)(arg)) {
79
+ // Handles both { __type: 'literal', sql } and { $literal: sql } shapes.
80
+ return arg.sql ?? arg.$literal;
81
+ }
82
+ // Fallback: stringify.
83
+ return String(arg);
84
+ }
85
+ /** Escape a string literal for embedding directly in SQL (single-quote doubling). */
86
+ function escapeStringLiteral(value) {
87
+ return `'${value.replace(/'/g, "''")}'`;
88
+ }
89
+ function normalizeOrderBy(orderBy) {
90
+ const entries = Array.isArray(orderBy) ? orderBy : [orderBy];
91
+ return entries.map((entry) => typeof entry === 'string' ? { column: entry } : entry);
92
+ }
93
+ /** Render `col ASC, col2 DESC` (no leading "ORDER BY" keyword). */
94
+ function renderOrderByList(orderBy) {
95
+ return normalizeOrderBy(orderBy)
96
+ .map((entry) => {
97
+ const colSql = escapeIdentifier(entry.column);
98
+ return entry.direction ? `${colSql} ${entry.direction}` : colSql;
99
+ })
100
+ .join(', ');
101
+ }
102
+ function unsupported(fnName, dialect, detail) {
103
+ throw new Error(`${fnName}() is not supported on dialect "${dialect}"${detail ? `: ${detail}` : ''}`);
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // count / countDistinct / sum / avg / min / max
107
+ // ---------------------------------------------------------------------------
108
+ /**
109
+ * `COUNT(*)` / `COUNT(expr)` — identical ANSI syntax across all 11 dialects.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * count('postgres') // -> COUNT(*)
114
+ * count('postgres', col('id')) // -> COUNT("id")
115
+ * ```
116
+ */
117
+ function count(_dialect, expr) {
118
+ const argSql = expr === undefined ? '*' : toSqlFragment(expr);
119
+ return (0, operators_1.literalExpr)(`COUNT(${argSql})`);
120
+ }
121
+ /**
122
+ * `COUNT(DISTINCT expr)`.
123
+ *
124
+ * Verified across all 11 dialects: MySQL, MariaDB, PostgreSQL, MSSQL,
125
+ * Oracle, SQLite, CockroachDB, Redshift, Db2, and Snowflake all support the
126
+ * exact ANSI `COUNT(DISTINCT expr)` syntax. ClickHouse also parses
127
+ * `COUNT(DISTINCT expr)` (it desugars to an internal uniq-exact
128
+ * implementation), though ClickHouse users may prefer the native
129
+ * `uniqExact(expr)` function for clarity/performance on very large
130
+ * cardinalities — that's a deliberate escape hatch, not a requirement, so
131
+ * `COUNT(DISTINCT expr)` is used here for consistency with the other
132
+ * dialects.
133
+ */
134
+ function countDistinct(_dialect, expr) {
135
+ return (0, operators_1.literalExpr)(`COUNT(DISTINCT ${toSqlFragment(expr)})`);
136
+ }
137
+ /**
138
+ * `SUM(expr)` — identical everywhere. Note: SUM of an all-NULL group (or
139
+ * zero input rows) returns SQL NULL (not 0) in every one of these dialects,
140
+ * so callers should COALESCE(...) explicitly if a numeric default is
141
+ * required.
142
+ */
143
+ function sum(_dialect, expr) {
144
+ return (0, operators_1.literalExpr)(`SUM(${toSqlFragment(expr)})`);
145
+ }
146
+ /**
147
+ * `AVG(expr)` — identical everywhere. Note: integer-typed columns are
148
+ * averaged as an exact/decimal type in PostgreSQL, MSSQL, Oracle, Db2, and
149
+ * Snowflake, but MySQL/MariaDB/SQLite/ClickHouse promote to floating point;
150
+ * cast explicitly (e.g. `cast(col('x'), 'DECIMAL(10,2)')`) if exact decimal
151
+ * averaging is required across dialects.
152
+ */
153
+ function avg(_dialect, expr) {
154
+ return (0, operators_1.literalExpr)(`AVG(${toSqlFragment(expr)})`);
155
+ }
156
+ /** `MIN(expr)` — identical everywhere. */
157
+ function min(_dialect, expr) {
158
+ return (0, operators_1.literalExpr)(`MIN(${toSqlFragment(expr)})`);
159
+ }
160
+ /** `MAX(expr)` — identical everywhere. */
161
+ function max(_dialect, expr) {
162
+ return (0, operators_1.literalExpr)(`MAX(${toSqlFragment(expr)})`);
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // stringAgg — the key, most syntax-divergent function in this module
166
+ // ---------------------------------------------------------------------------
167
+ /**
168
+ * String aggregation (`GROUP_CONCAT` / `STRING_AGG` / `LISTAGG` / ClickHouse
169
+ * array-concat), dispatched per-dialect. This is the single most
170
+ * error-prone aggregate across dialects, so each branch below documents the
171
+ * exact verified syntax.
172
+ *
173
+ * - **MySQL / MariaDB**:
174
+ * `GROUP_CONCAT([DISTINCT] expr [ORDER BY col [ASC|DESC]] SEPARATOR 'delim')`
175
+ * Clause order is fixed: DISTINCT, then the expression, then ORDER BY,
176
+ * then SEPARATOR — SEPARATOR must come last and is a keyword, not a comma
177
+ * argument.
178
+ *
179
+ * - **SQLite**: `GROUP_CONCAT(expr, 'delim')` (2-argument form; the
180
+ * separator defaults to `,` if omitted). SQLite's GROUP_CONCAT does
181
+ * **not** support an `ORDER BY` clause inside the function call at all —
182
+ * if `options.orderBy` is passed for SQLite this throws, since silently
183
+ * ignoring it would produce non-deterministic ordering that looks
184
+ * intentional. Pre-sort via a subquery/CTE if ordering is required.
185
+ * SQLite's DISTINCT variant (`GROUP_CONCAT(DISTINCT expr)`) is supported
186
+ * but forces the default comma separator (a custom separator combined
187
+ * with DISTINCT is not supported by SQLite) — this also throws if both
188
+ * `distinct` and a non-default delimiter are requested together.
189
+ *
190
+ * - **PostgreSQL / CockroachDB**: `STRING_AGG([DISTINCT] expr, 'delim' [ORDER BY col [ASC|DESC]])`
191
+ * — the ORDER BY clause sits *inside* the same parentheses as the
192
+ * delimiter argument (no WITHIN GROUP).
193
+ *
194
+ * - **MSSQL**: `STRING_AGG(expr, 'delim') WITHIN GROUP (ORDER BY col [ASC|DESC])`
195
+ * — note this is a genuinely different clause *placement* than Postgres:
196
+ * the ORDER BY is a separate `WITHIN GROUP (...)` clause appended after
197
+ * the function call, not inline inside the argument list. MSSQL's
198
+ * `STRING_AGG` also does **not** support a `DISTINCT` argument at all
199
+ * (unlike Postgres) — this throws if `distinct: true` is requested.
200
+ *
201
+ * - **Oracle / Db2**: `LISTAGG([DISTINCT] expr, 'delim') WITHIN GROUP (ORDER BY col [ASC|DESC])`
202
+ * — same WITHIN GROUP placement as MSSQL. Oracle supports `DISTINCT`
203
+ * inside LISTAGG since 19c; Db2 LUW's LISTAGG also supports `DISTINCT`.
204
+ *
205
+ * - **Redshift**: `LISTAGG([DISTINCT] expr, 'delim') WITHIN GROUP (ORDER BY col [ASC|DESC])`
206
+ * — Redshift's aggregate string function has always been `LISTAGG`
207
+ * (matching Oracle/Db2 syntax), not `STRING_AGG`. AWS did add a
208
+ * Postgres-compatible `STRING_AGG` alias to Redshift more recently, but
209
+ * `LISTAGG` is the long-standing, universally-available, and
210
+ * ORDER-BY-capable form, so it's used here for correctness.
211
+ *
212
+ * - **Snowflake**: `LISTAGG([DISTINCT] expr, 'delim') WITHIN GROUP (ORDER BY col [ASC|DESC])`
213
+ * — Snowflake's string aggregation function is `LISTAGG` (Oracle-style),
214
+ * *not* `STRING_AGG` — Snowflake has no `STRING_AGG` function.
215
+ *
216
+ * - **ClickHouse**: no native `GROUP_CONCAT`/`STRING_AGG`/`LISTAGG`. The
217
+ * verified, version-portable idiom is
218
+ * `arrayStringConcat(groupArray(expr), 'delim')` (distinct:
219
+ * `arrayStringConcat(groupUniqArray(expr), 'delim')`). Newer ClickHouse
220
+ * releases (24.x+) also ship a MySQL-compatible `groupConcat(expr)`
221
+ * function, but `arrayStringConcat(groupArray(...), ...)` works on every
222
+ * supported version so it's used as the default here. ClickHouse's
223
+ * `groupArray` has no inline `ORDER BY` sub-clause (it preserves block
224
+ * processing order, not a guaranteed sort) — `options.orderBy` therefore
225
+ * throws for ClickHouse; pre-sort via a subquery if ordering matters.
226
+ */
227
+ function stringAgg(dialect, expr, delimiter, options = {}) {
228
+ const { orderBy, distinct } = options;
229
+ const exprSql = toSqlFragment(expr);
230
+ const delimSql = escapeStringLiteral(delimiter);
231
+ switch (dialect) {
232
+ case 'mysql':
233
+ case 'mariadb': {
234
+ const parts = [];
235
+ if (distinct)
236
+ parts.push('DISTINCT');
237
+ parts.push(exprSql);
238
+ let sql = `GROUP_CONCAT(${parts.join(' ')}`;
239
+ if (orderBy) {
240
+ sql += ` ORDER BY ${renderOrderByList(orderBy)}`;
241
+ }
242
+ sql += ` SEPARATOR ${delimSql})`;
243
+ return (0, operators_1.literalExpr)(sql);
244
+ }
245
+ case 'sqlite': {
246
+ if (orderBy) {
247
+ unsupported('stringAgg', dialect, "SQLite's GROUP_CONCAT does not support an ORDER BY clause; pre-sort via a subquery instead");
248
+ }
249
+ if (distinct) {
250
+ if (delimiter !== ',') {
251
+ unsupported('stringAgg', dialect, 'SQLite GROUP_CONCAT(DISTINCT ...) only supports the default comma separator, not a custom delimiter');
252
+ }
253
+ return (0, operators_1.literalExpr)(`GROUP_CONCAT(DISTINCT ${exprSql})`);
254
+ }
255
+ return (0, operators_1.literalExpr)(`GROUP_CONCAT(${exprSql}, ${delimSql})`);
256
+ }
257
+ case 'postgres':
258
+ case 'cockroachdb': {
259
+ const argSql = distinct ? `DISTINCT ${exprSql}` : exprSql;
260
+ let sql = `STRING_AGG(${argSql}, ${delimSql}`;
261
+ if (orderBy) {
262
+ sql += ` ORDER BY ${renderOrderByList(orderBy)}`;
263
+ }
264
+ sql += ')';
265
+ return (0, operators_1.literalExpr)(sql);
266
+ }
267
+ case 'mssql': {
268
+ if (distinct) {
269
+ unsupported('stringAgg', dialect, 'MSSQL STRING_AGG does not support DISTINCT');
270
+ }
271
+ let sql = `STRING_AGG(${exprSql}, ${delimSql})`;
272
+ if (orderBy) {
273
+ sql += ` WITHIN GROUP (ORDER BY ${renderOrderByList(orderBy)})`;
274
+ }
275
+ return (0, operators_1.literalExpr)(sql);
276
+ }
277
+ case 'oracle':
278
+ case 'db2':
279
+ case 'redshift':
280
+ case 'snowflake': {
281
+ const argSql = distinct ? `DISTINCT ${exprSql}` : exprSql;
282
+ let sql = `LISTAGG(${argSql}, ${delimSql})`;
283
+ if (orderBy) {
284
+ sql += ` WITHIN GROUP (ORDER BY ${renderOrderByList(orderBy)})`;
285
+ }
286
+ return (0, operators_1.literalExpr)(sql);
287
+ }
288
+ case 'clickhouse': {
289
+ if (orderBy) {
290
+ unsupported('stringAgg', dialect, "ClickHouse's groupArray()/arrayStringConcat() has no inline ORDER BY; pre-sort via a subquery instead");
291
+ }
292
+ const arrayFn = distinct ? 'groupUniqArray' : 'groupArray';
293
+ return (0, operators_1.literalExpr)(`arrayStringConcat(${arrayFn}(${exprSql}), ${delimSql})`);
294
+ }
295
+ default: {
296
+ // Exhaustiveness guard for future Dialect additions.
297
+ throw new Error(`stringAgg(): unhandled dialect "${dialect}"`);
298
+ }
299
+ }
300
+ }
301
+ // ---------------------------------------------------------------------------
302
+ // arrayAgg
303
+ // ---------------------------------------------------------------------------
304
+ /**
305
+ * Aggregate values into an array/JSON-array, dispatched per-dialect.
306
+ *
307
+ * - **PostgreSQL / CockroachDB**: native `ARRAY_AGG([DISTINCT] expr [ORDER BY col [ASC|DESC]])`.
308
+ * - **Snowflake**: native `ARRAY_AGG([DISTINCT] expr) [WITHIN GROUP (ORDER BY col [ASC|DESC])]`
309
+ * — Snowflake's ARRAY_AGG uses the same WITHIN GROUP placement as LISTAGG,
310
+ * not Postgres's inline ORDER BY.
311
+ * - **ClickHouse**: native `groupArray(expr)` (distinct: `groupUniqArray(expr)`);
312
+ * returns ClickHouse's native Array(T) type. No inline ORDER BY support
313
+ * (same limitation as `stringAgg`) — throws if `orderBy` is requested.
314
+ * - **MySQL (5.7.22+) / MariaDB (10.5+)**: no `ARRAY_AGG`, but both support
315
+ * the real `JSON_ARRAYAGG(expr)` function, used here as a JSON-array
316
+ * fallback. Neither dialect's `JSON_ARRAYAGG` supports `DISTINCT` or
317
+ * `ORDER BY` — both throw if requested.
318
+ * - **Oracle (12.2+) / Db2 (11.5+)**: no `ARRAY_AGG`, but both support the
319
+ * real SQL:2016 `JSON_ARRAYAGG(expr)` function, used as a JSON-array
320
+ * fallback here too. `DISTINCT`/`ORDER BY` throw (not supported by either
321
+ * engine's JSON_ARRAYAGG).
322
+ * - **SQLite**: no `ARRAY_AGG`, but has the real native `json_group_array(expr)`
323
+ * aggregate, used as the fallback. `DISTINCT`/`ORDER BY` throw (not
324
+ * supported by SQLite's json_group_array).
325
+ * - **MSSQL / Redshift**: no real array-aggregation concept and no reliable
326
+ * scalar-aggregate JSON-array equivalent (MSSQL's JSON array construction
327
+ * is via `FOR JSON PATH` on a full query shape, not an aggregate function
328
+ * usable inline in a SELECT list; Redshift has no JSON_ARRAYAGG). Both
329
+ * throw a clear "not supported" error rather than faking an unreliable
330
+ * workaround.
331
+ */
332
+ function arrayAgg(dialect, expr, options = {}) {
333
+ const { orderBy, distinct } = options;
334
+ const exprSql = toSqlFragment(expr);
335
+ switch (dialect) {
336
+ case 'postgres':
337
+ case 'cockroachdb': {
338
+ const argSql = distinct ? `DISTINCT ${exprSql}` : exprSql;
339
+ let sql = `ARRAY_AGG(${argSql}`;
340
+ if (orderBy) {
341
+ sql += ` ORDER BY ${renderOrderByList(orderBy)}`;
342
+ }
343
+ sql += ')';
344
+ return (0, operators_1.literalExpr)(sql);
345
+ }
346
+ case 'snowflake': {
347
+ const argSql = distinct ? `DISTINCT ${exprSql}` : exprSql;
348
+ let sql = `ARRAY_AGG(${argSql})`;
349
+ if (orderBy) {
350
+ sql += ` WITHIN GROUP (ORDER BY ${renderOrderByList(orderBy)})`;
351
+ }
352
+ return (0, operators_1.literalExpr)(sql);
353
+ }
354
+ case 'clickhouse': {
355
+ if (orderBy) {
356
+ unsupported('arrayAgg', dialect, "ClickHouse's groupArray() has no inline ORDER BY; pre-sort via a subquery instead");
357
+ }
358
+ const arrayFn = distinct ? 'groupUniqArray' : 'groupArray';
359
+ return (0, operators_1.literalExpr)(`${arrayFn}(${exprSql})`);
360
+ }
361
+ case 'mysql':
362
+ case 'mariadb': {
363
+ if (distinct || orderBy) {
364
+ unsupported('arrayAgg', dialect, `${dialect === 'mysql' ? 'MySQL' : 'MariaDB'}'s JSON_ARRAYAGG (used as the ARRAY_AGG fallback) does not support DISTINCT or ORDER BY`);
365
+ }
366
+ return (0, operators_1.literalExpr)(`JSON_ARRAYAGG(${exprSql})`);
367
+ }
368
+ case 'oracle':
369
+ case 'db2': {
370
+ if (distinct || orderBy) {
371
+ unsupported('arrayAgg', dialect, `${dialect === 'oracle' ? 'Oracle' : 'Db2'}'s JSON_ARRAYAGG (used as the ARRAY_AGG fallback) does not support DISTINCT or ORDER BY`);
372
+ }
373
+ return (0, operators_1.literalExpr)(`JSON_ARRAYAGG(${exprSql})`);
374
+ }
375
+ case 'sqlite': {
376
+ if (distinct || orderBy) {
377
+ unsupported('arrayAgg', dialect, "SQLite's json_group_array (used as the ARRAY_AGG fallback) does not support DISTINCT or ORDER BY");
378
+ }
379
+ return (0, operators_1.literalExpr)(`json_group_array(${exprSql})`);
380
+ }
381
+ case 'mssql':
382
+ unsupported('arrayAgg', dialect, 'MSSQL has no ARRAY_AGG or scalar JSON-array aggregate function usable in a SELECT list (FOR JSON PATH operates on whole query shapes, not individual aggregate expressions)');
383
+ case 'redshift':
384
+ unsupported('arrayAgg', dialect, 'Redshift has no ARRAY_AGG and no JSON_ARRAYAGG equivalent');
385
+ default: {
386
+ // Exhaustiveness guard for future Dialect additions.
387
+ throw new Error(`arrayAgg(): unhandled dialect "${dialect}"`);
388
+ }
389
+ }
390
+ }