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,517 @@
1
+ "use strict";
2
+ /**
3
+ * Databricks SQL dialect implementation for the TypeScript ORM.
4
+ *
5
+ * Databricks SQL is built on Apache Spark SQL and the Delta Lake table format
6
+ * (a.k.a. the "lakehouse"). It uses backtick-quoted identifiers, exactly like
7
+ * MySQL/Spark SQL, so this dialect EXTENDS {@link MySQLDialect} purely to reuse
8
+ * the backtick quoting/escaping scaffolding and the general query-building
9
+ * skeleton, then overrides the pieces where Spark/Delta grammar genuinely
10
+ * differs from MySQL. A real deployment would connect over the Databricks SQL
11
+ * driver (Databricks SQL Warehouse / `@databricks/sql`) rather than mysql2 —
12
+ * the inherited connection code is not used against a real cluster.
13
+ *
14
+ * Notable differences from MySQL that this dialect overrides:
15
+ *
16
+ * - Default port is 443 (Databricks SQL Warehouses are reached over HTTPS),
17
+ * not 3306.
18
+ * - CREATE TABLE emits Delta/Spark grammar: `USING DELTA` (the table's data
19
+ * source/format, default DELTA; also PARQUET/CSV/JSON/etc.), `PARTITIONED BY
20
+ * (cols)`, `CLUSTERED BY (cols) INTO n BUCKETS`, `TBLPROPERTIES (...)`,
21
+ * `LOCATION 's3://...'` (external/unmanaged tables), and a trailing
22
+ * `COMMENT '...'`. There is no MySQL `ENGINE=`/`ROW_FORMAT=`/charset concept.
23
+ * - CTAS: {@link DatabricksDialect.buildCreateTableAsSelect} emits
24
+ * `CREATE TABLE ... USING DELTA AS SELECT ...`.
25
+ * - Upsert is expressed as a Delta Lake `MERGE INTO target USING source ON ...
26
+ * WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...`
27
+ * statement (see {@link DatabricksDialect.buildUpsertQuery}) rather than
28
+ * MySQL's `INSERT ... ON DUPLICATE KEY UPDATE`.
29
+ * - Auto-increment columns use Delta's `GENERATED ALWAYS AS IDENTITY` identity
30
+ * columns instead of MySQL's `AUTO_INCREMENT`.
31
+ * - Type mapping uses Spark SQL types: `STRING` (there is no `VARCHAR`/`TEXT`),
32
+ * `BIGINT`, `INT`, `DOUBLE`, `FLOAT`, `BOOLEAN`, `TIMESTAMP`, `DATE`,
33
+ * `BINARY`, `DECIMAL(p,s)`, and the complex types `ARRAY<>`, `MAP<>`,
34
+ * `STRUCT<>` (see {@link DatabricksDialect.getDataTypeSql}).
35
+ * - PRIMARY KEY / FOREIGN KEY constraints in Databricks are INFORMATIONAL only
36
+ * (they are declared `NOT ENFORCED` and used by the optimizer for query
37
+ * planning); they do not enforce uniqueness or referential integrity. This
38
+ * dialect emits them inline as informational constraints and never relies on
39
+ * them for correctness.
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.DatabricksDialect = void 0;
43
+ exports.createDatabricksDialect = createDatabricksDialect;
44
+ const index_1 = require("../mysql/index");
45
+ const prorm_1 = require("../../prorm");
46
+ /**
47
+ * Databricks SQL dialect. See the file header for the full list of
48
+ * Spark/Delta-specific overrides.
49
+ */
50
+ class DatabricksDialect extends index_1.MySQLDialect {
51
+ constructor(config) {
52
+ // Databricks SQL Warehouses are reached over HTTPS on port 443.
53
+ super({ port: 443, ...config });
54
+ this.name = 'databricks';
55
+ }
56
+ /**
57
+ * Map an ORM {@link DataType} to a Spark SQL / Delta type. The key
58
+ * difference from MySQL is that character types collapse to `STRING`
59
+ * (Spark SQL has no `VARCHAR(n)`/`TEXT`), and the complex types
60
+ * `ARRAY<>`/`MAP<>`/`STRUCT<>` are supported.
61
+ */
62
+ getDataTypeSql(dataType) {
63
+ if (typeof dataType === 'string') {
64
+ const upper = dataType.trim().toUpperCase();
65
+ // Normalize MySQL-ish character types written as raw strings to STRING.
66
+ if (/^(VARCHAR|CHARACTER VARYING|NVARCHAR|CHAR|N?TEXT|TINYTEXT|MEDIUMTEXT|LONGTEXT|CLOB)\b/.test(upper)) {
67
+ return 'STRING';
68
+ }
69
+ return dataType;
70
+ }
71
+ if (!dataType || typeof dataType !== 'object') {
72
+ return 'STRING';
73
+ }
74
+ const dt = dataType;
75
+ switch (dt.key) {
76
+ case 'STRING':
77
+ case 'CHAR':
78
+ case 'TEXT':
79
+ case 'ENUM':
80
+ case 'SET':
81
+ case 'UUID':
82
+ case 'JSON':
83
+ case 'JSONB':
84
+ // Spark SQL has no VARCHAR/TEXT/ENUM/JSON column types; store as STRING.
85
+ return 'STRING';
86
+ case 'INTEGER':
87
+ if (dt.length === 1)
88
+ return 'TINYINT';
89
+ if (dt.length === 2)
90
+ return 'SMALLINT';
91
+ if (dt.length === 8)
92
+ return 'BIGINT';
93
+ return 'INT';
94
+ case 'BIGINT':
95
+ return 'BIGINT';
96
+ case 'FLOAT':
97
+ return 'FLOAT';
98
+ case 'DOUBLE':
99
+ return 'DOUBLE';
100
+ case 'DECIMAL':
101
+ return `DECIMAL(${dt.precision || 10},${dt.scale || 0})`;
102
+ case 'BOOLEAN':
103
+ return 'BOOLEAN';
104
+ case 'DATE':
105
+ // A full timestamp (date + time) maps to Spark TIMESTAMP.
106
+ return 'TIMESTAMP';
107
+ case 'DATEONLY':
108
+ return 'DATE';
109
+ case 'TIME':
110
+ // Spark SQL has no standalone TIME type; represent as STRING.
111
+ return 'STRING';
112
+ case 'BLOB':
113
+ return 'BINARY';
114
+ case 'ARRAY':
115
+ return `ARRAY<${this.getComplexElementType(dt.type)}>`;
116
+ case 'MAP':
117
+ return `MAP<${this.getComplexElementType(dt.keyType) || 'STRING'}, ${this.getComplexElementType(dt.valueType)}>`;
118
+ case 'STRUCT': {
119
+ const fields = dt.fields || {};
120
+ const fieldSql = Object.entries(fields)
121
+ .map(([name, type]) => `${name}: ${this.getDataTypeSql(type)}`)
122
+ .join(', ');
123
+ return `STRUCT<${fieldSql}>`;
124
+ }
125
+ default:
126
+ // Anything not explicitly Spark-mapped falls through to STRING rather
127
+ // than an unsupported MySQL type like VARCHAR(255).
128
+ return 'STRING';
129
+ }
130
+ }
131
+ /**
132
+ * Resolve the element/value type for a complex (ARRAY/MAP) type, defaulting
133
+ * to `STRING` when the element type is unspecified.
134
+ */
135
+ getComplexElementType(type) {
136
+ if (type === undefined || type === null) {
137
+ return 'STRING';
138
+ }
139
+ return this.getDataTypeSql(type);
140
+ }
141
+ /**
142
+ * Build a single column definition for a Databricks CREATE TABLE. Emits
143
+ * Delta `GENERATED ALWAYS AS IDENTITY` for auto-increment columns and an
144
+ * informational (not-enforced) inline `PRIMARY KEY` where requested.
145
+ */
146
+ buildColumnDefinitionSql(columnName, definition) {
147
+ let sql = `${this.escapeId(columnName)} ${this.getDataTypeSql(definition.type)}`;
148
+ if (definition.allowNull === false) {
149
+ sql += ' NOT NULL';
150
+ }
151
+ if (definition.autoIncrement) {
152
+ // Delta identity columns; there is no MySQL-style AUTO_INCREMENT.
153
+ sql += ' GENERATED ALWAYS AS IDENTITY';
154
+ }
155
+ if (definition.defaultValue !== undefined && !definition.autoIncrement) {
156
+ sql += ` DEFAULT ${this.escape(definition.defaultValue)}`;
157
+ }
158
+ if (definition.primaryKey) {
159
+ // Informational only in Databricks (declared NOT ENFORCED). Kept for
160
+ // optimizer hints; never relied on for uniqueness.
161
+ sql += ' PRIMARY KEY';
162
+ }
163
+ if (definition.comment) {
164
+ sql += ` COMMENT ${this.escape(definition.comment)}`;
165
+ }
166
+ return sql;
167
+ }
168
+ /**
169
+ * Build the `CREATE TABLE` statement using Delta/Spark grammar. Exposed
170
+ * synchronously (separate from the async {@link createTable}) so callers can
171
+ * inspect the generated SQL without a live connection.
172
+ */
173
+ buildCreateTableSql(tableName, columns, options) {
174
+ const columnDefs = Object.entries(columns).map(([name, def]) => this.buildColumnDefinitionSql(name, def));
175
+ let sql = 'CREATE TABLE';
176
+ if (options?.ifNotExists) {
177
+ sql += ' IF NOT EXISTS';
178
+ }
179
+ sql += ` ${this.escapeId(tableName)} (${columnDefs.join(', ')})`;
180
+ // Data source / format. Delta is the default when unspecified.
181
+ const format = options?.using || 'DELTA';
182
+ sql += ` USING ${format}`;
183
+ if (options?.partitionedBy && options.partitionedBy.length > 0) {
184
+ sql += ` PARTITIONED BY (${options.partitionedBy.map((c) => this.escapeId(c)).join(', ')})`;
185
+ }
186
+ if (options?.clusteredBy && options.clusteredBy.columns.length > 0) {
187
+ const cols = options.clusteredBy.columns.map((c) => this.escapeId(c)).join(', ');
188
+ sql += ` CLUSTERED BY (${cols}) INTO ${options.clusteredBy.buckets} BUCKETS`;
189
+ }
190
+ if (options?.location) {
191
+ sql += ` LOCATION ${this.escape(options.location)}`;
192
+ }
193
+ if (options?.comment) {
194
+ sql += ` COMMENT ${this.escape(options.comment)}`;
195
+ }
196
+ if (options?.tblproperties && Object.keys(options.tblproperties).length > 0) {
197
+ const props = Object.entries(options.tblproperties)
198
+ .map(([k, v]) => `'${k}'=${this.escape(v)}`)
199
+ .join(', ');
200
+ sql += ` TBLPROPERTIES (${props})`;
201
+ }
202
+ return sql;
203
+ }
204
+ /**
205
+ * Create a table using Delta/Spark grammar. Delegates SQL generation to
206
+ * {@link buildCreateTableSql} and executes it.
207
+ */
208
+ async createTable(tableName, columns, options) {
209
+ await this.query(this.buildCreateTableSql(tableName, columns, options));
210
+ }
211
+ /**
212
+ * Build a `CREATE TABLE ... USING <format> AS SELECT ...` (CTAS) statement.
213
+ * The column list and types are inferred from the SELECT, so only the format
214
+ * and (optionally) partitioning/location apply.
215
+ */
216
+ buildCreateTableAsSelect(tableName, selectQuery, options) {
217
+ let sql = 'CREATE TABLE';
218
+ if (options?.ifNotExists) {
219
+ sql += ' IF NOT EXISTS';
220
+ }
221
+ sql += ` ${this.escapeId(tableName)}`;
222
+ sql += ` USING ${options?.using || 'DELTA'}`;
223
+ if (options?.partitionedBy && options.partitionedBy.length > 0) {
224
+ sql += ` PARTITIONED BY (${options.partitionedBy.map((c) => this.escapeId(c)).join(', ')})`;
225
+ }
226
+ if (options?.location) {
227
+ sql += ` LOCATION ${this.escape(options.location)}`;
228
+ }
229
+ if (options?.comment) {
230
+ sql += ` COMMENT ${this.escape(options.comment)}`;
231
+ }
232
+ if (options?.tblproperties && Object.keys(options.tblproperties).length > 0) {
233
+ const props = Object.entries(options.tblproperties)
234
+ .map(([k, v]) => `'${k}'=${this.escape(v)}`)
235
+ .join(', ');
236
+ sql += ` TBLPROPERTIES (${props})`;
237
+ }
238
+ sql += ` AS ${selectQuery.trim().replace(/;\s*$/, '')}`;
239
+ return sql;
240
+ }
241
+ /**
242
+ * Build a Delta Lake `MERGE INTO` upsert. Delta has no MySQL-style
243
+ * `ON DUPLICATE KEY UPDATE`; instead the row(s) to upsert are supplied as an
244
+ * inline `source` relation and matched against the target on the conflict
245
+ * (key) columns:
246
+ *
247
+ * MERGE INTO `t` AS target
248
+ * USING (SELECT ? AS `id`, ? AS `name`) AS source
249
+ * ON target.`id` = source.`id`
250
+ * WHEN MATCHED THEN UPDATE SET target.`name` = source.`name`
251
+ * WHEN NOT MATCHED THEN INSERT (`id`, `name`) VALUES (source.`id`, source.`name`)
252
+ *
253
+ * @param tableName - Target table.
254
+ * @param values - Column/value pairs for the row to upsert.
255
+ * @param options - `conflictFields` picks the ON/match key columns (defaults
256
+ * to all columns); `updateOnDuplicate` restricts which columns the
257
+ * WHEN MATCHED branch updates (defaults to all non-key columns).
258
+ */
259
+ buildUpsertQuery(tableName, values, options) {
260
+ if (options?.returning) {
261
+ // Delta MERGE does not support a RETURNING clause; re-select instead.
262
+ throw new Error('Databricks (Delta MERGE) does not support the RETURNING clause. Re-fetch the row after the upsert instead.');
263
+ }
264
+ const columns = Object.keys(values);
265
+ if (columns.length === 0) {
266
+ throw new Error('buildUpsertQuery requires at least one column to upsert.');
267
+ }
268
+ const processedValues = [];
269
+ // Build the inline source relation: SELECT ? AS `col`, ...
270
+ const sourceSelect = columns
271
+ .map((col) => {
272
+ const value = values[col];
273
+ if (value instanceof prorm_1.Literal) {
274
+ return `${value.val} AS ${this.escapeId(col)}`;
275
+ }
276
+ processedValues.push(value);
277
+ return `? AS ${this.escapeId(col)}`;
278
+ })
279
+ .join(', ');
280
+ const conflictFields = options?.conflictFields && options.conflictFields.length > 0
281
+ ? options.conflictFields
282
+ : columns;
283
+ const onClause = conflictFields
284
+ .map((c) => `target.${this.escapeId(c)} = source.${this.escapeId(c)}`)
285
+ .join(' AND ');
286
+ // Columns to update when matched: explicit list, or everything that isn't
287
+ // part of the match key.
288
+ const updateFields = options?.updateOnDuplicate && options.updateOnDuplicate.length > 0
289
+ ? options.updateOnDuplicate
290
+ : columns.filter((c) => !conflictFields.includes(c));
291
+ const target = this.escapeId(tableName);
292
+ let sql = `MERGE INTO ${target} AS target USING (SELECT ${sourceSelect}) AS source ON ${onClause}`;
293
+ if (updateFields.length > 0) {
294
+ const setClause = updateFields
295
+ .map((c) => `target.${this.escapeId(c)} = source.${this.escapeId(c)}`)
296
+ .join(', ');
297
+ sql += ` WHEN MATCHED THEN UPDATE SET ${setClause}`;
298
+ }
299
+ const insertCols = columns.map((c) => this.escapeId(c)).join(', ');
300
+ const insertVals = columns.map((c) => `source.${this.escapeId(c)}`).join(', ');
301
+ sql += ` WHEN NOT MATCHED THEN INSERT (${insertCols}) VALUES (${insertVals})`;
302
+ return { sql, values: processedValues };
303
+ }
304
+ // ---------------------------------------------------------------------------
305
+ // CRUD overrides — Spark SQL / Delta diverges from MySQL here.
306
+ // ---------------------------------------------------------------------------
307
+ /**
308
+ * Build a `LIMIT`/`OFFSET` tail. Spark SQL supports `LIMIT n` and, since
309
+ * Spark 3.4 / Databricks Runtime 11+, a standalone `OFFSET n` (with or
310
+ * without a preceding `LIMIT`). Unlike MySQL there is NO need for the
311
+ * `LIMIT 18446744073709551615 OFFSET n` sentinel trick — Spark accepts
312
+ * `OFFSET` on its own — so this override drops that MySQL-only hack.
313
+ *
314
+ * NOTE: `OFFSET` is only valid on the outermost query and requires a
315
+ * recent Spark/DBR; on older runtimes it raises a parser error. For deep
316
+ * pagination prefer a keyset/`WHERE` predicate over large offsets.
317
+ */
318
+ buildLimitOffset(limit, offset) {
319
+ let sql = '';
320
+ if (limit !== undefined) {
321
+ sql += ` LIMIT ${Number(limit)}`;
322
+ }
323
+ if (offset !== undefined) {
324
+ sql += ` OFFSET ${Number(offset)}`;
325
+ }
326
+ return sql;
327
+ }
328
+ /**
329
+ * Build an INSERT. A plain insert (`INSERT INTO t (cols) VALUES (...)`) is
330
+ * valid Spark SQL and reuses the inherited MySQL builder verbatim. When the
331
+ * caller sets `upsert`, MySQL would emit `... ON DUPLICATE KEY UPDATE`, which
332
+ * Spark/Delta rejects — so route to a Delta `MERGE INTO` instead.
333
+ */
334
+ buildInsertQuery(tableName, values, options) {
335
+ if (options?.upsert) {
336
+ return this.buildUpsertQuery(tableName, values, {
337
+ conflictFields: options.conflictFields,
338
+ updateOnDuplicate: options.updateOnDuplicate,
339
+ });
340
+ }
341
+ return super.buildInsertQuery(tableName, values);
342
+ }
343
+ /**
344
+ * Build an UPDATE. Delta Lake supports `UPDATE t SET ... WHERE ...`, but
345
+ * (unlike MySQL) it does NOT support a trailing `LIMIT` on UPDATE, nor a
346
+ * `RETURNING` clause. Strip `LIMIT` and reject `RETURNING` rather than emit
347
+ * SQL Spark would reject.
348
+ */
349
+ buildUpdateQuery(tableName, values, where, options) {
350
+ if (options?.returning) {
351
+ throw new Error('Databricks (Delta) does not support RETURNING on UPDATE. Re-fetch the rows after the update instead.');
352
+ }
353
+ // Reuse the inherited builder but never emit LIMIT (Delta UPDATE has none).
354
+ return super.buildUpdateQuery(tableName, values, where, { ...options, limit: undefined });
355
+ }
356
+ /**
357
+ * Build a DELETE. Delta Lake supports `DELETE FROM t WHERE ...`, but not a
358
+ * trailing `LIMIT` or `RETURNING`. Strip `LIMIT` and reject `RETURNING`.
359
+ */
360
+ buildDeleteQuery(tableName, where, options) {
361
+ if (options?.returning) {
362
+ throw new Error('Databricks (Delta) does not support RETURNING on DELETE. Re-fetch/track the rows before deleting instead.');
363
+ }
364
+ return super.buildDeleteQuery(tableName, where, { ...options, limit: undefined });
365
+ }
366
+ // ---------------------------------------------------------------------------
367
+ // DDL overrides — Spark ALTER TABLE grammar differs from MySQL.
368
+ // ---------------------------------------------------------------------------
369
+ /**
370
+ * Column spec for `ALTER TABLE ... ADD COLUMNS`. Spark only accepts
371
+ * `name type [COMMENT '...']` (optionally `FIRST`/`AFTER col`) here — it does
372
+ * NOT accept `NOT NULL`, `DEFAULT`, `PRIMARY KEY`, or identity clauses on an
373
+ * added column, so those are intentionally omitted (unlike the full CREATE
374
+ * TABLE column definition).
375
+ */
376
+ buildAddColumnSpecSql(columnName, definition) {
377
+ let sql = `${this.escapeId(columnName)} ${this.getDataTypeSql(definition.type)}`;
378
+ if (definition.comment) {
379
+ sql += ` COMMENT ${this.escape(definition.comment)}`;
380
+ }
381
+ return sql;
382
+ }
383
+ /**
384
+ * Build `ALTER TABLE t ADD COLUMNS (col type ...)`. Spark uses the plural
385
+ * `ADD COLUMNS (...)` with a parenthesised list — NOT MySQL's singular
386
+ * `ADD COLUMN col ...`.
387
+ */
388
+ buildAddColumnSql(tableName, columnName, definition) {
389
+ return `ALTER TABLE ${this.escapeId(tableName)} ADD COLUMNS (${this.buildAddColumnSpecSql(columnName, definition)})`;
390
+ }
391
+ async addColumn(tableName, columnName, definition) {
392
+ await this.query(this.buildAddColumnSql(tableName, columnName, definition));
393
+ }
394
+ /**
395
+ * Build `ALTER TABLE t DROP COLUMN col`. Valid Delta grammar (requires Delta
396
+ * column-mapping mode to be enabled on the table); identical in shape to
397
+ * MySQL, so behaviourally inherited but surfaced as a sync builder for tests.
398
+ */
399
+ buildDropColumnSql(tableName, columnName) {
400
+ return `ALTER TABLE ${this.escapeId(tableName)} DROP COLUMN ${this.escapeId(columnName)}`;
401
+ }
402
+ async removeColumn(tableName, columnName) {
403
+ await this.query(this.buildDropColumnSql(tableName, columnName));
404
+ }
405
+ /**
406
+ * Build `ALTER TABLE t RENAME COLUMN old TO new`. Spark/Delta uses
407
+ * `RENAME COLUMN`; MySQL uses `CHANGE old new <type>` (which also requires
408
+ * re-stating the type). This override needs no `DESCRIBE` round-trip.
409
+ */
410
+ buildRenameColumnSql(tableName, oldColumnName, newColumnName) {
411
+ return `ALTER TABLE ${this.escapeId(tableName)} RENAME COLUMN ${this.escapeId(oldColumnName)} TO ${this.escapeId(newColumnName)}`;
412
+ }
413
+ async renameColumn(tableName, oldColumnName, newColumnName) {
414
+ await this.query(this.buildRenameColumnSql(tableName, oldColumnName, newColumnName));
415
+ }
416
+ /**
417
+ * Delta only supports a narrow set of in-place column alterations
418
+ * (comment, nullability, ordering — and, on recent runtimes, limited type
419
+ * widening). MySQL's `CHANGE col <full-def>` is not valid Spark SQL, so
420
+ * rather than emit something a cluster would reject, expose the two
421
+ * supported primitives explicitly and fail fast on the generic path.
422
+ */
423
+ async changeColumn(_tableName, _columnName, _definition) {
424
+ throw new Error('Databricks (Delta) does not support MySQL-style CHANGE COLUMN. Use renameColumn(), ' +
425
+ 'setColumnComment(), or setColumnNullability() for the supported in-place alterations; ' +
426
+ 'arbitrary type changes require rewriting the table.');
427
+ }
428
+ /** Build `ALTER TABLE t ALTER COLUMN col COMMENT '...'` (Delta-supported). */
429
+ buildSetColumnCommentSql(tableName, columnName, comment) {
430
+ return `ALTER TABLE ${this.escapeId(tableName)} ALTER COLUMN ${this.escapeId(columnName)} COMMENT ${this.escape(comment)}`;
431
+ }
432
+ async setColumnComment(tableName, columnName, comment) {
433
+ await this.query(this.buildSetColumnCommentSql(tableName, columnName, comment));
434
+ }
435
+ /**
436
+ * Build `ALTER TABLE t ALTER COLUMN col SET|DROP NOT NULL` (Delta-supported).
437
+ */
438
+ buildSetColumnNullabilitySql(tableName, columnName, notNull) {
439
+ const action = notNull ? 'SET NOT NULL' : 'DROP NOT NULL';
440
+ return `ALTER TABLE ${this.escapeId(tableName)} ALTER COLUMN ${this.escapeId(columnName)} ${action}`;
441
+ }
442
+ async setColumnNullability(tableName, columnName, notNull) {
443
+ await this.query(this.buildSetColumnNullabilitySql(tableName, columnName, notNull));
444
+ }
445
+ /**
446
+ * Build `DROP TABLE [IF EXISTS] t`. Spark has no `CASCADE` on `DROP TABLE`
447
+ * (that's a MySQL/Postgres construct), so the inherited CASCADE handling is
448
+ * overridden away.
449
+ */
450
+ buildDropTableSql(tableName, options) {
451
+ let sql = 'DROP TABLE';
452
+ if (options?.ifExists) {
453
+ sql += ' IF EXISTS';
454
+ }
455
+ sql += ` ${this.escapeId(tableName)}`;
456
+ return sql;
457
+ }
458
+ async dropTable(tableName, options) {
459
+ await this.query(this.buildDropTableSql(tableName, options));
460
+ }
461
+ /**
462
+ * Build `ALTER TABLE t SET TBLPROPERTIES ('k'='v', ...)` — the Delta/Spark
463
+ * way to change table-level options after creation.
464
+ */
465
+ buildSetTablePropertiesSql(tableName, properties) {
466
+ const props = Object.entries(properties)
467
+ .map(([k, v]) => `'${k}'=${this.escape(v)}`)
468
+ .join(', ');
469
+ return `ALTER TABLE ${this.escapeId(tableName)} SET TBLPROPERTIES (${props})`;
470
+ }
471
+ async setTableProperties(tableName, properties) {
472
+ await this.query(this.buildSetTablePropertiesSql(tableName, properties));
473
+ }
474
+ /** Build `ALTER TABLE t UNSET TBLPROPERTIES [IF EXISTS] ('k', ...)`. */
475
+ buildUnsetTablePropertiesSql(tableName, keys, ifExists = false) {
476
+ const list = keys.map((k) => `'${k}'`).join(', ');
477
+ return `ALTER TABLE ${this.escapeId(tableName)} UNSET TBLPROPERTIES ${ifExists ? 'IF EXISTS ' : ''}(${list})`;
478
+ }
479
+ async unsetTableProperties(tableName, keys, ifExists = false) {
480
+ await this.query(this.buildUnsetTablePropertiesSql(tableName, keys, ifExists));
481
+ }
482
+ async addIndex(_tableName, _indexName, _fields, _options) {
483
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
484
+ }
485
+ async createIndex(_tableName, _indexDef) {
486
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
487
+ }
488
+ async removeIndex(_tableName, _indexName) {
489
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
490
+ }
491
+ async dropIndex(_tableName, _indexName) {
492
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
493
+ }
494
+ async createFulltextIndex() {
495
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
496
+ }
497
+ async createSpatialIndex() {
498
+ throw new Error(DatabricksDialect.INDEX_UNSUPPORTED);
499
+ }
500
+ }
501
+ exports.DatabricksDialect = DatabricksDialect;
502
+ // ---------------------------------------------------------------------------
503
+ // Secondary indexes — unsupported by Spark SQL / Delta.
504
+ // ---------------------------------------------------------------------------
505
+ // Spark SQL has no generic `CREATE INDEX`. Databricks offers only specialized
506
+ // constructs (e.g. Bloom-filter indexes, Z-ORDER / liquid clustering) that
507
+ // don't map to the ORM's index API. Fail fast instead of emitting the
508
+ // inherited MySQL `CREATE INDEX ... ON ...`, which a cluster would reject.
509
+ DatabricksDialect.INDEX_UNSUPPORTED = 'Databricks (Spark SQL / Delta) does not support generic secondary indexes ' +
510
+ '(CREATE INDEX). Use liquid clustering / Z-ORDER (OPTIMIZE ... ZORDER BY), ' +
511
+ 'partitioning, or a Bloom-filter index instead.';
512
+ /**
513
+ * Convenience factory mirroring the other dialects' `create*Dialect` helpers.
514
+ */
515
+ function createDatabricksDialect(options) {
516
+ return new DatabricksDialect(options || {});
517
+ }