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,518 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.concat = concat;
4
+ exports.substring = substring;
5
+ exports.trim = trim;
6
+ exports.ltrim = ltrim;
7
+ exports.rtrim = rtrim;
8
+ exports.upper = upper;
9
+ exports.lower = lower;
10
+ exports.length = length;
11
+ exports.replace = replace;
12
+ exports.lpad = lpad;
13
+ exports.rpad = rpad;
14
+ exports.split = split;
15
+ exports.repeat = repeat;
16
+ exports.reverse = reverse;
17
+ /**
18
+ * Typed string-function builders.
19
+ *
20
+ * These helpers produce dialect-correct SQL fragments for common string
21
+ * operations (CONCAT, SUBSTRING, TRIM, padding, etc.) so callers never need
22
+ * to hand-write raw SQL for the handful of functions that genuinely differ
23
+ * between dialects (Postgres `||` vs `CONCAT()`, Oracle `SUBSTR` vs the
24
+ * standard `SUBSTRING`, MSSQL `LEN` vs `LENGTH`/`CHAR_LENGTH`, etc.)
25
+ *
26
+ * This module is intentionally self-contained: it does not modify
27
+ * `src/operators.ts` or `src/query-builders/sql-compiler.ts`. It only reads
28
+ * the `literal`, `ColExpression`, `FnExpression`, and `LiteralExpression`
29
+ * primitives from `../../operators` and returns plain `{ $literal: string }`
30
+ * values (via `literal()`) that can be dropped into `attributes`, `where`,
31
+ * etc. exactly like any other literal expression.
32
+ */
33
+ const operators_1 = require("../../operators");
34
+ // ==================== Internal rendering helpers ====================
35
+ /**
36
+ * Quote/escape a raw string as a SQL string literal.
37
+ * Doubling the single quote is valid escaping syntax across all 11
38
+ * supported dialects (standard SQL escaping).
39
+ */
40
+ function quoteStringLiteral(value) {
41
+ return `'${value.replace(/'/g, "''")}'`;
42
+ }
43
+ /**
44
+ * Quote an identifier (column name), honoring dialect-specific quoting
45
+ * characters and supporting dotted `table.column` references.
46
+ */
47
+ function quoteIdentifier(dialect, name) {
48
+ const parts = name.split('.');
49
+ return parts.map((part) => quoteIdentifierPart(dialect, part)).join('.');
50
+ }
51
+ function quoteIdentifierPart(dialect, part) {
52
+ switch (dialect) {
53
+ case 'mysql':
54
+ case 'mariadb':
55
+ case 'clickhouse':
56
+ return `\`${part.replace(/`/g, '``')}\``;
57
+ case 'mssql':
58
+ return `[${part.replace(/\]/g, ']]')}]`;
59
+ case 'oracle':
60
+ case 'sqlite':
61
+ case 'postgres':
62
+ case 'cockroachdb':
63
+ case 'redshift':
64
+ case 'db2':
65
+ case 'snowflake':
66
+ return `"${part.replace(/"/g, '""')}"`;
67
+ default:
68
+ return `"${part.replace(/"/g, '""')}"`;
69
+ }
70
+ }
71
+ /**
72
+ * Render a `SqlExpr` (column-like argument) into a raw SQL fragment.
73
+ *
74
+ * Plain strings are treated as literal string VALUES and are quoted.
75
+ * `ColExpression`/`FnExpression`/`LiteralExpression` objects are unwrapped
76
+ * and rendered as expressions/identifiers.
77
+ */
78
+ function toSqlFragment(dialect, arg) {
79
+ if (typeof arg === 'number') {
80
+ return String(arg);
81
+ }
82
+ if (typeof arg === 'string') {
83
+ return quoteStringLiteral(arg);
84
+ }
85
+ if (arg && typeof arg === 'object') {
86
+ if (arg.__type === 'col') {
87
+ return quoteIdentifier(dialect, arg.col);
88
+ }
89
+ if (arg.__type === 'fn') {
90
+ const fnExpr = arg;
91
+ const args = fnExpr.args.map((a) => toSqlFragment(dialect, a));
92
+ return `${fnExpr.fn}(${args.join(', ')})`;
93
+ }
94
+ if (arg.__type === 'literal') {
95
+ return arg.sql;
96
+ }
97
+ }
98
+ // Fallback - should not normally be reached given the SqlExpr type.
99
+ return String(arg);
100
+ }
101
+ function unsupported(fnName, dialect, reason) {
102
+ throw new Error(`[query-builders/functions/string] ${fnName}() is not supported for dialect "${dialect}": ${reason}`);
103
+ }
104
+ // ==================== concat ====================
105
+ /**
106
+ * String concatenation.
107
+ *
108
+ * - MySQL, MariaDB, MSSQL, Snowflake, ClickHouse: use the variadic
109
+ * `CONCAT(a, b, c, ...)` function (all support 2+ arguments).
110
+ * - Postgres, CockroachDB, Redshift, SQLite, Oracle, DB2: use the `||`
111
+ * operator. These dialects' `CONCAT()` function (where it exists at all)
112
+ * is limited to exactly 2 arguments (Oracle, DB2), so `||` is used
113
+ * uniformly for correctness with any number of parts. Postgres/CockroachDB/
114
+ * SQLite treat `||` as the idiomatic concatenation operator.
115
+ *
116
+ * @param parts - Column-like arguments (columns via `col()`, nested
117
+ * expressions via `fn()`, or literal string values as plain strings).
118
+ */
119
+ function concat(dialect, ...parts) {
120
+ if (parts.length === 0) {
121
+ throw new Error('[query-builders/functions/string] concat() requires at least one argument');
122
+ }
123
+ const rendered = parts.map((p) => toSqlFragment(dialect, p));
124
+ switch (dialect) {
125
+ case 'mysql':
126
+ case 'mariadb':
127
+ case 'mssql':
128
+ case 'snowflake':
129
+ case 'clickhouse':
130
+ return wrap(`CONCAT(${rendered.join(', ')})`);
131
+ case 'postgres':
132
+ case 'cockroachdb':
133
+ case 'redshift':
134
+ case 'sqlite':
135
+ case 'oracle':
136
+ case 'db2':
137
+ return wrap(rendered.join(' || '));
138
+ default:
139
+ return wrap(`CONCAT(${rendered.join(', ')})`);
140
+ }
141
+ }
142
+ function wrap(sql) {
143
+ // `literal()` returns { $literal: string }. We also attach __type/sql so
144
+ // callers who want the LiteralExpression shape can use it interchangeably;
145
+ // both shapes are recognized by isLiteralExpression()/isRawLiteral().
146
+ const lit = (0, operators_1.literal)(sql);
147
+ return Object.assign(lit, { __type: 'literal', sql });
148
+ }
149
+ // ==================== substring ====================
150
+ /**
151
+ * Extract a substring.
152
+ *
153
+ * - Oracle, DB2, SQLite: use `SUBSTR(expr, start, length)`. SQLite has no
154
+ * built-in `SUBSTRING` function (only `substr`); Oracle/DB2 use `SUBSTR`
155
+ * as their canonical name (both also happen to accept the same argument
156
+ * order as the standard `SUBSTRING(expr, start, length)` form).
157
+ * - MSSQL: `SUBSTRING(expr, start, length)`, but MSSQL requires the length
158
+ * argument. When `length` is omitted, `LEN(expr)` is used as a safe upper
159
+ * bound so the result runs to the end of the string.
160
+ * - MySQL, MariaDB, Postgres, CockroachDB, Redshift, Snowflake, ClickHouse:
161
+ * `SUBSTRING(expr, start, length)` comma-argument form, length optional.
162
+ *
163
+ * @param expr - The column/expression to extract from.
164
+ * @param start - 1-based start position (SQL substring indices are 1-based).
165
+ * @param length - Optional number of characters to extract.
166
+ */
167
+ function substring(dialect, expr, start, length) {
168
+ const rendered = toSqlFragment(dialect, expr);
169
+ switch (dialect) {
170
+ case 'oracle':
171
+ case 'db2':
172
+ case 'sqlite':
173
+ return wrap(length !== undefined ? `SUBSTR(${rendered}, ${start}, ${length})` : `SUBSTR(${rendered}, ${start})`);
174
+ case 'mssql': {
175
+ const len = length !== undefined ? String(length) : `LEN(${rendered})`;
176
+ return wrap(`SUBSTRING(${rendered}, ${start}, ${len})`);
177
+ }
178
+ case 'mysql':
179
+ case 'mariadb':
180
+ case 'postgres':
181
+ case 'cockroachdb':
182
+ case 'redshift':
183
+ case 'snowflake':
184
+ case 'clickhouse':
185
+ default:
186
+ return wrap(length !== undefined
187
+ ? `SUBSTRING(${rendered}, ${start}, ${length})`
188
+ : `SUBSTRING(${rendered}, ${start})`);
189
+ }
190
+ }
191
+ /**
192
+ * Trim whitespace (or specific characters) from a string.
193
+ *
194
+ * - Postgres, CockroachDB, Redshift, Oracle, DB2, Snowflake, MySQL, MariaDB,
195
+ * ClickHouse: support the standard
196
+ * `TRIM([BOTH|LEADING|TRAILING] [chars FROM] expr)` syntax.
197
+ * - SQLite: has no `[BOTH|LEADING|TRAILING] FROM` syntax; instead uses
198
+ * `trim(expr[, chars])` / `ltrim(expr[, chars])` / `rtrim(expr[, chars])`.
199
+ * - MSSQL: `TRIM` (2017+) only trims both sides; for one-sided trimming we
200
+ * fall back to `LTRIM`/`RTRIM`. Native `LTRIM`/`RTRIM` in MSSQL only
201
+ * support a `chars` argument starting with SQL Server 2022, so when
202
+ * `chars` is supplied on an older-compatible codepath it is still passed
203
+ * through (SQL Server will error at runtime on versions that don't
204
+ * support it — this is a documented MSSQL version limitation, not a
205
+ * limitation of this helper).
206
+ */
207
+ function trim(dialect, expr, options) {
208
+ const side = options?.side ?? 'both';
209
+ const rendered = toSqlFragment(dialect, expr);
210
+ const chars = options?.chars;
211
+ switch (dialect) {
212
+ case 'sqlite': {
213
+ const fnName = side === 'leading' ? 'ltrim' : side === 'trailing' ? 'rtrim' : 'trim';
214
+ return wrap(chars !== undefined ? `${fnName}(${rendered}, ${quoteStringLiteral(chars)})` : `${fnName}(${rendered})`);
215
+ }
216
+ case 'mssql': {
217
+ if (side === 'leading') {
218
+ return wrap(chars !== undefined ? `LTRIM(${rendered}, ${quoteStringLiteral(chars)})` : `LTRIM(${rendered})`);
219
+ }
220
+ if (side === 'trailing') {
221
+ return wrap(chars !== undefined ? `RTRIM(${rendered}, ${quoteStringLiteral(chars)})` : `RTRIM(${rendered})`);
222
+ }
223
+ return wrap(chars !== undefined ? `TRIM(${quoteStringLiteral(chars)} FROM ${rendered})` : `TRIM(${rendered})`);
224
+ }
225
+ case 'postgres':
226
+ case 'cockroachdb':
227
+ case 'redshift':
228
+ case 'oracle':
229
+ case 'db2':
230
+ case 'snowflake':
231
+ case 'mysql':
232
+ case 'mariadb':
233
+ case 'clickhouse':
234
+ default: {
235
+ const sideKeyword = side === 'leading' ? 'LEADING' : side === 'trailing' ? 'TRAILING' : 'BOTH';
236
+ if (chars !== undefined) {
237
+ return wrap(`TRIM(${sideKeyword} ${quoteStringLiteral(chars)} FROM ${rendered})`);
238
+ }
239
+ return wrap(`TRIM(${sideKeyword} FROM ${rendered})`);
240
+ }
241
+ }
242
+ }
243
+ /** Trim from the left only. Equivalent to `trim(dialect, expr, { side: 'leading' })`. */
244
+ function ltrim(dialect, expr, chars) {
245
+ return trim(dialect, expr, { side: 'leading', chars });
246
+ }
247
+ /** Trim from the right only. Equivalent to `trim(dialect, expr, { side: 'trailing' })`. */
248
+ function rtrim(dialect, expr, chars) {
249
+ return trim(dialect, expr, { side: 'trailing', chars });
250
+ }
251
+ // ==================== upper / lower ====================
252
+ /**
253
+ * Uppercase a string. Identical (`UPPER(expr)`) across all 11 dialects.
254
+ */
255
+ function upper(dialect, expr) {
256
+ return wrap(`UPPER(${toSqlFragment(dialect, expr)})`);
257
+ }
258
+ /**
259
+ * Lowercase a string. Identical (`LOWER(expr)`) across all 11 dialects.
260
+ */
261
+ function lower(dialect, expr) {
262
+ return wrap(`LOWER(${toSqlFragment(dialect, expr)})`);
263
+ }
264
+ // ==================== length ====================
265
+ /**
266
+ * Get the character length of a string.
267
+ *
268
+ * - MySQL, MariaDB, Postgres, CockroachDB, DB2, Snowflake: use
269
+ * `CHAR_LENGTH(expr)`. This is deliberately chosen over `LENGTH()` on
270
+ * MySQL/MariaDB because `LENGTH()` there counts BYTES, which is wrong for
271
+ * multi-byte (e.g. UTF-8) text; `CHAR_LENGTH()` always counts characters.
272
+ * - MSSQL: has no `CHAR_LENGTH`/`LENGTH` function at all; uses `LEN(expr)`
273
+ * (already character-counting).
274
+ * - Redshift: uses `LEN(expr)`, its documented/idiomatic string-length
275
+ * function (Redshift's SQL dialect favors `LEN` even though it is
276
+ * Postgres-derived).
277
+ * - Oracle: uses `LENGTH(expr)` (Oracle has no `CHAR_LENGTH` keyword;
278
+ * `LENGTH` already counts characters for CHAR/VARCHAR2 data).
279
+ * - SQLite: uses `length(expr)`, which for TEXT values already counts
280
+ * characters, not bytes (SQLite has no separate `CHAR_LENGTH`).
281
+ * - ClickHouse: `length()` counts BYTES. For character-correct behavior
282
+ * with multi-byte text, `lengthUTF8(expr)` is used instead.
283
+ */
284
+ function length(dialect, expr) {
285
+ const rendered = toSqlFragment(dialect, expr);
286
+ switch (dialect) {
287
+ case 'mssql':
288
+ case 'redshift':
289
+ return wrap(`LEN(${rendered})`);
290
+ case 'oracle':
291
+ case 'sqlite':
292
+ return wrap(`LENGTH(${rendered})`);
293
+ case 'clickhouse':
294
+ return wrap(`lengthUTF8(${rendered})`);
295
+ case 'mysql':
296
+ case 'mariadb':
297
+ case 'postgres':
298
+ case 'cockroachdb':
299
+ case 'db2':
300
+ case 'snowflake':
301
+ default:
302
+ return wrap(`CHAR_LENGTH(${rendered})`);
303
+ }
304
+ }
305
+ // ==================== replace ====================
306
+ /**
307
+ * Replace all occurrences of a substring.
308
+ * `REPLACE(expr, search, replacement)` is identical across all 11 dialects.
309
+ */
310
+ function replace(dialect, expr, search, replacement) {
311
+ const rendered = toSqlFragment(dialect, expr);
312
+ return wrap(`REPLACE(${rendered}, ${quoteStringLiteral(search)}, ${quoteStringLiteral(replacement)})`);
313
+ }
314
+ // ==================== lpad / rpad ====================
315
+ /**
316
+ * Left-pad a string to a target length.
317
+ *
318
+ * - MySQL, MariaDB, Postgres, CockroachDB, Redshift, Oracle, Snowflake:
319
+ * native `LPAD(expr, length, pad)`.
320
+ * - ClickHouse: native `leftPad(expr, length, pad)`.
321
+ * - MSSQL: has no `LPAD`. Workaround using `RIGHT(REPLICATE(pad, length) +
322
+ * expr, length)` — replicate the pad string enough times to guarantee at
323
+ * least `length` characters, prepend it to `expr`, then take the
324
+ * rightmost `length` characters (matches LPAD's truncate-on-overflow
325
+ * semantics).
326
+ * - DB2: has no `LPAD` in Db2 for LUW. Workaround using a `CASE` expression:
327
+ * if the string is already >= target length, return it unchanged;
328
+ * otherwise prepend enough of the repeated pad string (via `REPEAT` +
329
+ * `SUBSTR`) to reach the target length.
330
+ * - SQLite: throws. SQLite has neither `LPAD` nor a `REPEAT` function, and
331
+ * there is no safe single-expression workaround without a recursive CTE,
332
+ * so this is not something a scalar SQL fragment can express correctly.
333
+ */
334
+ function lpad(dialect, expr, targetLength, padString = ' ') {
335
+ const rendered = toSqlFragment(dialect, expr);
336
+ const pad = quoteStringLiteral(padString);
337
+ switch (dialect) {
338
+ case 'mysql':
339
+ case 'mariadb':
340
+ case 'postgres':
341
+ case 'cockroachdb':
342
+ case 'redshift':
343
+ case 'oracle':
344
+ case 'snowflake':
345
+ return wrap(`LPAD(${rendered}, ${targetLength}, ${pad})`);
346
+ case 'clickhouse':
347
+ return wrap(`leftPad(${rendered}, ${targetLength}, ${pad})`);
348
+ case 'mssql':
349
+ return wrap(`RIGHT(REPLICATE(${pad}, ${targetLength}) + ${rendered}, ${targetLength})`);
350
+ case 'db2':
351
+ return wrap(`CASE WHEN CHAR_LENGTH(${rendered}) >= ${targetLength} THEN ${rendered} ` +
352
+ `ELSE SUBSTR(REPEAT(${pad}, ${targetLength}), 1, ${targetLength} - CHAR_LENGTH(${rendered})) || ${rendered} END`);
353
+ case 'sqlite':
354
+ return unsupported('lpad', dialect, 'SQLite has no LPAD/REPEAT function and no safe single-expression workaround');
355
+ default:
356
+ return wrap(`LPAD(${rendered}, ${targetLength}, ${pad})`);
357
+ }
358
+ }
359
+ /**
360
+ * Right-pad a string to a target length. See {@link lpad} for per-dialect
361
+ * notes; the same dialects that lack `LPAD` also lack `RPAD`.
362
+ */
363
+ function rpad(dialect, expr, targetLength, padString = ' ') {
364
+ const rendered = toSqlFragment(dialect, expr);
365
+ const pad = quoteStringLiteral(padString);
366
+ switch (dialect) {
367
+ case 'mysql':
368
+ case 'mariadb':
369
+ case 'postgres':
370
+ case 'cockroachdb':
371
+ case 'redshift':
372
+ case 'oracle':
373
+ case 'snowflake':
374
+ return wrap(`RPAD(${rendered}, ${targetLength}, ${pad})`);
375
+ case 'clickhouse':
376
+ return wrap(`rightPad(${rendered}, ${targetLength}, ${pad})`);
377
+ case 'mssql':
378
+ return wrap(`LEFT(${rendered} + REPLICATE(${pad}, ${targetLength}), ${targetLength})`);
379
+ case 'db2':
380
+ return wrap(`CASE WHEN CHAR_LENGTH(${rendered}) >= ${targetLength} THEN ${rendered} ` +
381
+ `ELSE ${rendered} || SUBSTR(REPEAT(${pad}, ${targetLength}), 1, ${targetLength} - CHAR_LENGTH(${rendered})) END`);
382
+ case 'sqlite':
383
+ return unsupported('rpad', dialect, 'SQLite has no RPAD/REPEAT function and no safe single-expression workaround');
384
+ default:
385
+ return wrap(`RPAD(${rendered}, ${targetLength}, ${pad})`);
386
+ }
387
+ }
388
+ // ==================== split ====================
389
+ /**
390
+ * Split a string on a delimiter, returning an array/collection expression
391
+ * where the dialect has a real mechanism for it.
392
+ *
393
+ * - Postgres, CockroachDB: `STRING_TO_ARRAY(expr, delimiter)` -> `text[]`.
394
+ * - Redshift: `SPLIT_TO_ARRAY(expr, delimiter)` -> `SUPER` array (Redshift's
395
+ * SUPER-type based array support).
396
+ * - Snowflake: `SPLIT(expr, delimiter)` -> `ARRAY` (variant).
397
+ * - ClickHouse: `splitByString(delimiter, expr)` -> `Array(String)`. Note
398
+ * the argument order is reversed compared to the others (separator comes
399
+ * first in ClickHouse).
400
+ * - MySQL, MariaDB, MSSQL, Oracle, DB2, SQLite: throw. None of these have a
401
+ * clean way to produce an array/collection from a scalar expression:
402
+ * - MySQL/MariaDB have no array type at all (only `SUBSTRING_INDEX` for
403
+ * extracting a single part by position, which is a different contract).
404
+ * - MSSQL's `STRING_SPLIT` is a table-valued function usable only in a
405
+ * `FROM` clause, not as a scalar expression.
406
+ * - Oracle/DB2/SQLite have no built-in split-to-array function; producing
407
+ * one requires `CONNECT BY`/recursive CTE tricks that cannot be
408
+ * expressed as a single SQL fragment.
409
+ */
410
+ function split(dialect, expr, delimiter) {
411
+ const rendered = toSqlFragment(dialect, expr);
412
+ const delim = quoteStringLiteral(delimiter);
413
+ switch (dialect) {
414
+ case 'postgres':
415
+ case 'cockroachdb':
416
+ return wrap(`STRING_TO_ARRAY(${rendered}, ${delim})`);
417
+ case 'redshift':
418
+ return wrap(`SPLIT_TO_ARRAY(${rendered}, ${delim})`);
419
+ case 'snowflake':
420
+ return wrap(`SPLIT(${rendered}, ${delim})`);
421
+ case 'clickhouse':
422
+ return wrap(`splitByString(${delim}, ${rendered})`);
423
+ case 'mysql':
424
+ case 'mariadb':
425
+ return unsupported('split', dialect, 'no array type / split-to-array function exists; use SUBSTRING_INDEX for extracting a single part instead');
426
+ case 'mssql':
427
+ return unsupported('split', dialect, 'STRING_SPLIT is table-valued (usable only in a FROM clause), not a scalar expression');
428
+ case 'oracle':
429
+ case 'db2':
430
+ case 'sqlite':
431
+ return unsupported('split', dialect, 'no built-in split-to-array function; would require CONNECT BY/recursive-CTE tricks that cannot be expressed as a single SQL fragment');
432
+ default:
433
+ return unsupported('split', dialect, 'no known split mechanism for this dialect');
434
+ }
435
+ }
436
+ // ==================== repeat ====================
437
+ /**
438
+ * Repeat a string N times.
439
+ *
440
+ * - MySQL, MariaDB, Postgres, CockroachDB, Redshift, DB2, Snowflake,
441
+ * ClickHouse: native `REPEAT(expr, n)` (ClickHouse: `repeat(expr, n)`).
442
+ * - MSSQL: has no `REPEAT`; uses `REPLICATE(expr, n)`, which is exactly
443
+ * equivalent.
444
+ * - Oracle: has no `REPEAT`. Workaround: `RPAD(expr, LENGTH(expr) * n,
445
+ * expr)` — `RPAD`'s first argument already contributes one copy of
446
+ * `expr`, and padding with `expr` itself out to `length(expr) * n`
447
+ * characters fills in the remaining `n - 1` copies, producing `expr`
448
+ * repeated exactly `n` times (requires `expr` to be non-empty, since
449
+ * Oracle treats `''` as `NULL`).
450
+ * - SQLite: throws. SQLite has no `REPEAT` function and no safe
451
+ * single-expression workaround (the zeroblob/hex tricks that exist are
452
+ * fragile and only work for single-character pad values).
453
+ */
454
+ function repeat(dialect, expr, n) {
455
+ const rendered = toSqlFragment(dialect, expr);
456
+ switch (dialect) {
457
+ case 'mysql':
458
+ case 'mariadb':
459
+ case 'postgres':
460
+ case 'cockroachdb':
461
+ case 'redshift':
462
+ case 'db2':
463
+ case 'snowflake':
464
+ return wrap(`REPEAT(${rendered}, ${n})`);
465
+ case 'clickhouse':
466
+ return wrap(`repeat(${rendered}, ${n})`);
467
+ case 'mssql':
468
+ return wrap(`REPLICATE(${rendered}, ${n})`);
469
+ case 'oracle':
470
+ return wrap(`RPAD(${rendered}, LENGTH(${rendered}) * ${n}, ${rendered})`);
471
+ case 'sqlite':
472
+ return unsupported('repeat', dialect, 'SQLite has no REPEAT function and no safe single-expression workaround');
473
+ default:
474
+ return wrap(`REPEAT(${rendered}, ${n})`);
475
+ }
476
+ }
477
+ // ==================== reverse ====================
478
+ /**
479
+ * Reverse a string.
480
+ *
481
+ * - MySQL, MariaDB, MSSQL, Postgres (9.1+), CockroachDB, Snowflake: native
482
+ * `REVERSE(expr)`.
483
+ * - ClickHouse: `reverse()` reverses BYTES, not characters, which breaks
484
+ * multi-byte text; `reverseUTF8(expr)` is used instead for correctness.
485
+ * - Oracle: no built-in `REVERSE` function for strings; there is no safe
486
+ * single-expression workaround (would require a hierarchical
487
+ * `CONNECT BY LEVEL` query), so this throws.
488
+ * - DB2: no built-in `REVERSE` scalar function in Db2 for LUW; throws for
489
+ * the same reason as Oracle.
490
+ * - Redshift: not present in Redshift's documented string-function list
491
+ * (Redshift's SQL dialect is derived from an old Postgres release that
492
+ * predates Postgres's `REVERSE`); throws rather than risk incorrect SQL.
493
+ * - SQLite: no built-in `REVERSE` function; throws.
494
+ */
495
+ function reverse(dialect, expr) {
496
+ const rendered = toSqlFragment(dialect, expr);
497
+ switch (dialect) {
498
+ case 'mysql':
499
+ case 'mariadb':
500
+ case 'mssql':
501
+ case 'postgres':
502
+ case 'cockroachdb':
503
+ case 'snowflake':
504
+ return wrap(`REVERSE(${rendered})`);
505
+ case 'clickhouse':
506
+ return wrap(`reverseUTF8(${rendered})`);
507
+ case 'oracle':
508
+ return unsupported('reverse', dialect, 'Oracle has no built-in REVERSE function for strings');
509
+ case 'db2':
510
+ return unsupported('reverse', dialect, 'Db2 for LUW has no built-in REVERSE scalar function');
511
+ case 'redshift':
512
+ return unsupported('reverse', dialect, 'REVERSE is not part of Redshift\'s documented string function set');
513
+ case 'sqlite':
514
+ return unsupported('reverse', dialect, 'SQLite has no built-in REVERSE function');
515
+ default:
516
+ return wrap(`REVERSE(${rendered})`);
517
+ }
518
+ }