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.
- package/CHANGELOG.md +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- package/package.json +190 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Exasol dialect implementation for the TypeScript ORM.
|
|
4
|
+
*
|
|
5
|
+
* Exasol is an in-memory, column-oriented, massively-parallel (MPP) analytic
|
|
6
|
+
* database. Its SQL grammar and wire behavior are close enough to PostgreSQL
|
|
7
|
+
* that this dialect extends {@link PostgresDialect} and reuses the pg-style
|
|
8
|
+
* grammar (double-quoted identifiers, `$1` placeholders, `ON CONFLICT`-free
|
|
9
|
+
* INSERTs, etc.) as its base, overriding only the places where Exasol really
|
|
10
|
+
* differs. Notable differences from PostgreSQL captured here:
|
|
11
|
+
*
|
|
12
|
+
* - Default SQL port is 8563 (not 5432).
|
|
13
|
+
* - CREATE TABLE supports MPP distribution/partitioning clauses:
|
|
14
|
+
* `... DISTRIBUTE BY col1, col2` controls how rows are hash-distributed
|
|
15
|
+
* across cluster nodes, and `... PARTITION BY col` controls on-disk
|
|
16
|
+
* partitioning within a node. Both are surfaced via table options and
|
|
17
|
+
* emitted as trailing clauses.
|
|
18
|
+
* - No SERIAL / BIGSERIAL. Auto-increment columns use an `IDENTITY` column
|
|
19
|
+
* constraint on a numeric (DECIMAL) column instead.
|
|
20
|
+
* - Type mapping differs: TEXT maps to `VARCHAR(2000000)` (Exasol's max
|
|
21
|
+
* VARCHAR width), STRING to `VARCHAR(n)`, integers to `DECIMAL(18,0)`
|
|
22
|
+
* (Exasol has no native narrow integer types — everything numeric is a
|
|
23
|
+
* DECIMAL), and DECIMAL(p,s)/BOOLEAN/TIMESTAMP map straight through.
|
|
24
|
+
* - Bulk load/unload uses Exasol's `IMPORT` / `EXPORT` statements against a
|
|
25
|
+
* file/connection endpoint rather than PostgreSQL's `COPY`.
|
|
26
|
+
* - Exasol upper-cases unquoted identifiers (like Oracle). This dialect quotes
|
|
27
|
+
* identifiers with double quotes (inherited from PostgresDialect), so the
|
|
28
|
+
* ORM's mixed-case names are preserved exactly rather than being folded to
|
|
29
|
+
* upper case.
|
|
30
|
+
* - Exasol has **no `RETURNING` clause** on INSERT/UPDATE/DELETE and **no
|
|
31
|
+
* `ON CONFLICT`**. So the write builders inherited from PostgresDialect
|
|
32
|
+
* (`buildInsertQuery`, `buildUpdateQuery`, `buildDeleteQuery`,
|
|
33
|
+
* `buildUpsertQuery`) are overridden here to strip `RETURNING` and to express
|
|
34
|
+
* upserts as a `MERGE INTO ... USING (SELECT ...) ON (...) WHEN MATCHED /
|
|
35
|
+
* WHEN NOT MATCHED` statement instead.
|
|
36
|
+
* - Plain SELECT (WHERE, ORDER BY, GROUP BY / HAVING, JOIN, `LIMIT ... OFFSET`)
|
|
37
|
+
* and `buildLimitOffset` are inherited unchanged: Exasol's SELECT grammar
|
|
38
|
+
* matches the PostgreSQL forms the base emits, including `LIMIT n OFFSET m`.
|
|
39
|
+
*
|
|
40
|
+
* Placeholders: this dialect keeps the PostgreSQL `$n` positional style so it
|
|
41
|
+
* composes with the rest of the ORM's parameter handling. Exasol's own JDBC/
|
|
42
|
+
* WebSocket drivers use `?`; a live driver binding would translate accordingly.
|
|
43
|
+
*/
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.ExasolDialect = void 0;
|
|
46
|
+
exports.createExasolDialect = createExasolDialect;
|
|
47
|
+
const postgres_1 = require("../postgres");
|
|
48
|
+
const prorm_1 = require("../../prorm");
|
|
49
|
+
/**
|
|
50
|
+
* Exasol dialect. Extends {@link PostgresDialect}; see the file header for the
|
|
51
|
+
* list of Exasol-specific behaviors.
|
|
52
|
+
*/
|
|
53
|
+
class ExasolDialect extends postgres_1.PostgresDialect {
|
|
54
|
+
constructor(config) {
|
|
55
|
+
// Exasol's default SQL port is 8563 (not Postgres's 5432). Caller-supplied
|
|
56
|
+
// config still wins over this default.
|
|
57
|
+
super({ port: 8563, ...config });
|
|
58
|
+
this.name = 'exasol';
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Map an ORM data type to its Exasol SQL type. Overrides the Postgres
|
|
62
|
+
* mapping for the types that differ on Exasol:
|
|
63
|
+
* - TEXT -> VARCHAR(2000000) (Exasol's max VARCHAR width; no TEXT type)
|
|
64
|
+
* - STRING -> VARCHAR(n)
|
|
65
|
+
* - INTEGER -> DECIMAL(18,0) (no SERIAL; IDENTITY is applied separately)
|
|
66
|
+
* - BIGINT -> DECIMAL(36,0)
|
|
67
|
+
* - DECIMAL -> DECIMAL(p,s)
|
|
68
|
+
* - BOOLEAN -> BOOLEAN
|
|
69
|
+
* - DATE -> TIMESTAMP
|
|
70
|
+
* Everything else delegates to the PostgreSQL mapping.
|
|
71
|
+
*/
|
|
72
|
+
getDataTypeSql(dataType) {
|
|
73
|
+
if (typeof dataType === 'string') {
|
|
74
|
+
// Normalize the cross-dialect DATETIME pseudo-type to TIMESTAMP, matching
|
|
75
|
+
// the Postgres base behavior.
|
|
76
|
+
if (/^DATETIME(\(\d+\))?$/i.test(dataType)) {
|
|
77
|
+
return dataType.replace(/^DATETIME/i, 'TIMESTAMP');
|
|
78
|
+
}
|
|
79
|
+
return dataType;
|
|
80
|
+
}
|
|
81
|
+
if (!dataType || typeof dataType !== 'object') {
|
|
82
|
+
return super.getDataTypeSql(dataType);
|
|
83
|
+
}
|
|
84
|
+
const dt = dataType;
|
|
85
|
+
switch (dt.key) {
|
|
86
|
+
case 'TEXT':
|
|
87
|
+
// Exasol has no TEXT type; use its maximum-width VARCHAR.
|
|
88
|
+
return 'VARCHAR(2000000)';
|
|
89
|
+
case 'STRING':
|
|
90
|
+
return `VARCHAR(${dt.length || 255})`;
|
|
91
|
+
case 'CHAR':
|
|
92
|
+
return `CHAR(${dt.length || 1})`;
|
|
93
|
+
case 'INTEGER':
|
|
94
|
+
// No SERIAL on Exasol - auto-increment is handled via IDENTITY in the
|
|
95
|
+
// column definition, so the base type is a plain numeric DECIMAL.
|
|
96
|
+
return 'DECIMAL(18,0)';
|
|
97
|
+
case 'BIGINT':
|
|
98
|
+
return 'DECIMAL(36,0)';
|
|
99
|
+
case 'DECIMAL':
|
|
100
|
+
return `DECIMAL(${dt.precision || 18},${dt.scale || 0})`;
|
|
101
|
+
case 'BOOLEAN':
|
|
102
|
+
return 'BOOLEAN';
|
|
103
|
+
case 'DATE':
|
|
104
|
+
return dt.precision ? `TIMESTAMP(${dt.precision})` : 'TIMESTAMP';
|
|
105
|
+
case 'DATEONLY':
|
|
106
|
+
return 'DATE';
|
|
107
|
+
default:
|
|
108
|
+
return super.getDataTypeSql(dataType);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format a single column's definition for CREATE TABLE. Emits `IDENTITY`
|
|
113
|
+
* (rather than SERIAL) for auto-increment columns.
|
|
114
|
+
*/
|
|
115
|
+
buildColumnSql(columnName, definition) {
|
|
116
|
+
let sql = `${this.escapeId(columnName)} ${this.getDataTypeSql(definition.type)}`;
|
|
117
|
+
if (definition.autoIncrement) {
|
|
118
|
+
// Exasol auto-increment: numeric column with an IDENTITY constraint.
|
|
119
|
+
sql += ' IDENTITY';
|
|
120
|
+
}
|
|
121
|
+
if (definition.allowNull === false) {
|
|
122
|
+
sql += ' NOT NULL';
|
|
123
|
+
}
|
|
124
|
+
if (definition.defaultValue !== undefined && !definition.autoIncrement) {
|
|
125
|
+
sql += ` DEFAULT ${this.formatDefault(definition.defaultValue)}`;
|
|
126
|
+
}
|
|
127
|
+
if (definition.primaryKey) {
|
|
128
|
+
sql += ' PRIMARY KEY';
|
|
129
|
+
}
|
|
130
|
+
if (definition.unique) {
|
|
131
|
+
// Exasol accepts a column-level UNIQUE constraint (it is tracked but not
|
|
132
|
+
// enforced by default, like foreign keys).
|
|
133
|
+
sql += ' UNIQUE';
|
|
134
|
+
}
|
|
135
|
+
if (definition.references) {
|
|
136
|
+
const refField = definition.references.field;
|
|
137
|
+
const refFieldSql = Array.isArray(refField)
|
|
138
|
+
? `(${refField.map((f) => this.escapeId(f)).join(', ')})`
|
|
139
|
+
: `(${this.escapeId(refField)})`;
|
|
140
|
+
sql += ` REFERENCES ${this.escapeId(definition.references.table)}${refFieldSql}`;
|
|
141
|
+
}
|
|
142
|
+
return sql;
|
|
143
|
+
}
|
|
144
|
+
/** Format a DEFAULT value literal for a column definition. */
|
|
145
|
+
formatDefault(value) {
|
|
146
|
+
if (value === null) {
|
|
147
|
+
return 'NULL';
|
|
148
|
+
}
|
|
149
|
+
if (typeof value === 'string') {
|
|
150
|
+
if (value.toUpperCase().includes('CURRENT_') || value.toUpperCase() === 'NULL') {
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
154
|
+
}
|
|
155
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
156
|
+
return String(value);
|
|
157
|
+
}
|
|
158
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
159
|
+
}
|
|
160
|
+
/** Render a `DISTRIBUTE BY` / `PARTITION BY` column list. */
|
|
161
|
+
columnList(cols) {
|
|
162
|
+
const arr = Array.isArray(cols) ? cols : [cols];
|
|
163
|
+
return arr.map((c) => this.escapeId(c)).join(', ');
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Build a `CREATE TABLE` statement, including Exasol's MPP `DISTRIBUTE BY`
|
|
167
|
+
* and `PARTITION BY` clauses. Exposed synchronously so the emitted SQL can be
|
|
168
|
+
* built (and tested) without a live connection.
|
|
169
|
+
*/
|
|
170
|
+
buildCreateTableSQL(tableName, columns, options) {
|
|
171
|
+
const columnDefs = Object.entries(columns).map(([name, def]) => this.buildColumnSql(name, def));
|
|
172
|
+
let sql = 'CREATE TABLE';
|
|
173
|
+
if (options?.ifNotExists) {
|
|
174
|
+
sql += ' IF NOT EXISTS';
|
|
175
|
+
}
|
|
176
|
+
sql += ` ${this.escapeId(tableName)} (${columnDefs.join(', ')})`;
|
|
177
|
+
// MPP distribution across cluster nodes.
|
|
178
|
+
if (options?.distributeBy) {
|
|
179
|
+
sql += ` DISTRIBUTE BY ${this.columnList(options.distributeBy)}`;
|
|
180
|
+
}
|
|
181
|
+
// On-disk partitioning within a node.
|
|
182
|
+
if (options?.partitionBy) {
|
|
183
|
+
sql += ` PARTITION BY ${this.columnList(options.partitionBy)}`;
|
|
184
|
+
}
|
|
185
|
+
return sql;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create a table. Overrides the Postgres implementation to emit Exasol's
|
|
189
|
+
* IDENTITY columns and `DISTRIBUTE BY` / `PARTITION BY` clauses.
|
|
190
|
+
*/
|
|
191
|
+
async createTable(tableName, columns, options) {
|
|
192
|
+
await this.query(this.buildCreateTableSQL(tableName, columns, options));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Add a column. Overrides the Postgres implementation, which would emit a
|
|
196
|
+
* `SERIAL` for auto-increment columns; Exasol uses `IDENTITY` instead (see
|
|
197
|
+
* {@link buildColumnSql}). Exasol accepts the optional `COLUMN` keyword.
|
|
198
|
+
*/
|
|
199
|
+
async addColumn(tableName, columnName, definition) {
|
|
200
|
+
const sql = `ALTER TABLE ${this.escapeId(tableName)} ADD COLUMN ${this.buildColumnSql(columnName, definition)}`;
|
|
201
|
+
await this.query(sql);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Change a column's type. Exasol uses `ALTER TABLE ... MODIFY COLUMN col type`
|
|
205
|
+
* rather than PostgreSQL's `ALTER COLUMN col TYPE type`.
|
|
206
|
+
*/
|
|
207
|
+
async changeColumn(tableName, columnName, definition) {
|
|
208
|
+
let sql = `ALTER TABLE ${this.escapeId(tableName)} MODIFY COLUMN ${this.escapeId(columnName)} ${this.getDataTypeSql(definition.type)}`;
|
|
209
|
+
if (definition.allowNull === false) {
|
|
210
|
+
sql += ' NOT NULL';
|
|
211
|
+
}
|
|
212
|
+
if (definition.defaultValue !== undefined) {
|
|
213
|
+
sql += ` DEFAULT ${this.formatDefault(definition.defaultValue)}`;
|
|
214
|
+
}
|
|
215
|
+
await this.query(sql);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Build an INSERT. Same as the PostgreSQL base but Exasol has no `RETURNING`
|
|
219
|
+
* clause, and upserts are expressed as a `MERGE` (Exasol has no
|
|
220
|
+
* `ON CONFLICT`). When `options.upsert` is set this delegates to
|
|
221
|
+
* {@link buildMergeSQL}; the `returning` option is ignored.
|
|
222
|
+
*/
|
|
223
|
+
buildInsertQuery(tableName, values, options) {
|
|
224
|
+
if (options?.upsert) {
|
|
225
|
+
return this.buildMergeSQL(tableName, values, {
|
|
226
|
+
conflictFields: options.conflictFields,
|
|
227
|
+
updateOnDuplicate: options.updateOnDuplicate,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const columns = Object.keys(values);
|
|
231
|
+
const processedValues = [];
|
|
232
|
+
const placeholders = [];
|
|
233
|
+
let paramIndex = 1;
|
|
234
|
+
for (const value of Object.values(values)) {
|
|
235
|
+
if (value instanceof prorm_1.Literal) {
|
|
236
|
+
placeholders.push(value.val);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
placeholders.push(`$${paramIndex}`);
|
|
240
|
+
processedValues.push(value);
|
|
241
|
+
paramIndex++;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// No RETURNING on Exasol - deliberately omitted even if requested.
|
|
245
|
+
const sql = `INSERT INTO ${this.escapeId(tableName)} (${columns
|
|
246
|
+
.map((c) => this.escapeId(c))
|
|
247
|
+
.join(', ')}) VALUES (${placeholders.join(', ')})`;
|
|
248
|
+
return { sql, values: processedValues };
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Build an UPSERT as an Exasol `MERGE` statement. Exasol has no
|
|
252
|
+
* `INSERT ... ON CONFLICT`.
|
|
253
|
+
*/
|
|
254
|
+
buildUpsertQuery(tableName, values, options) {
|
|
255
|
+
return this.buildMergeSQL(tableName, values, {
|
|
256
|
+
conflictFields: options?.conflictFields,
|
|
257
|
+
updateOnDuplicate: options?.updateOnDuplicate,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Build the Exasol `MERGE INTO ... USING (SELECT ...) ON (...)` statement that
|
|
262
|
+
* implements an upsert for a single row of `values`.
|
|
263
|
+
*
|
|
264
|
+
* The row is presented as a one-row derived source via a FROM-less
|
|
265
|
+
* `SELECT $1 AS "col", ...` (Exasol permits SELECT without FROM). Rows are
|
|
266
|
+
* matched on `conflictFields`; matched rows are updated (excluding the
|
|
267
|
+
* conflict columns, which Exasol forbids updating because they appear in the
|
|
268
|
+
* `ON` condition) and unmatched rows are inserted.
|
|
269
|
+
*/
|
|
270
|
+
buildMergeSQL(tableName, values, options) {
|
|
271
|
+
const conflictFields = options?.conflictFields;
|
|
272
|
+
if (!conflictFields || conflictFields.length === 0) {
|
|
273
|
+
throw new Error('buildMergeSQL: options.conflictFields is required - Exasol MERGE needs the ' +
|
|
274
|
+
'key column(s) to match existing rows on, so it cannot be inferred from the ' +
|
|
275
|
+
'inserted columns.');
|
|
276
|
+
}
|
|
277
|
+
const columns = Object.keys(values);
|
|
278
|
+
const processedValues = [];
|
|
279
|
+
let paramIndex = 1;
|
|
280
|
+
// FROM-less source select: one aliased expression per column.
|
|
281
|
+
const sourceExprs = columns.map((col) => {
|
|
282
|
+
const value = values[col];
|
|
283
|
+
if (value instanceof prorm_1.Literal) {
|
|
284
|
+
return `${value.val} AS ${this.escapeId(col)}`;
|
|
285
|
+
}
|
|
286
|
+
const placeholder = `$${paramIndex++}`;
|
|
287
|
+
processedValues.push(value);
|
|
288
|
+
return `${placeholder} AS ${this.escapeId(col)}`;
|
|
289
|
+
});
|
|
290
|
+
const onCondition = conflictFields
|
|
291
|
+
.map((c) => `dst.${this.escapeId(c)} = src.${this.escapeId(c)}`)
|
|
292
|
+
.join(' AND ');
|
|
293
|
+
// Columns to update on match: explicit list if given, otherwise every
|
|
294
|
+
// non-conflict column. Exasol forbids updating the ON-condition columns.
|
|
295
|
+
const conflictSet = new Set(conflictFields);
|
|
296
|
+
const updateFields = (options?.updateOnDuplicate && options.updateOnDuplicate.length > 0
|
|
297
|
+
? options.updateOnDuplicate
|
|
298
|
+
: columns).filter((c) => !conflictSet.has(c));
|
|
299
|
+
let sql = `MERGE INTO ${this.escapeId(tableName)} dst` +
|
|
300
|
+
` USING (SELECT ${sourceExprs.join(', ')}) src` +
|
|
301
|
+
` ON (${onCondition})`;
|
|
302
|
+
if (updateFields.length > 0) {
|
|
303
|
+
const updateClauses = updateFields
|
|
304
|
+
.map((c) => `dst.${this.escapeId(c)} = src.${this.escapeId(c)}`)
|
|
305
|
+
.join(', ');
|
|
306
|
+
sql += ` WHEN MATCHED THEN UPDATE SET ${updateClauses}`;
|
|
307
|
+
}
|
|
308
|
+
const insertCols = columns.map((c) => this.escapeId(c)).join(', ');
|
|
309
|
+
const insertVals = columns.map((c) => `src.${this.escapeId(c)}`).join(', ');
|
|
310
|
+
sql += ` WHEN NOT MATCHED THEN INSERT (${insertCols}) VALUES (${insertVals})`;
|
|
311
|
+
return { sql, values: processedValues };
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Build an UPDATE. Same as the PostgreSQL base, but Exasol supports neither a
|
|
315
|
+
* `RETURNING` clause nor a `LIMIT` on UPDATE, so both are stripped from the
|
|
316
|
+
* options before delegating.
|
|
317
|
+
*/
|
|
318
|
+
buildUpdateQuery(tableName, values, where, options) {
|
|
319
|
+
const { returning: _returning, limit: _limit, ...rest } = options || {};
|
|
320
|
+
return super.buildUpdateQuery(tableName, values, where, rest);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Build a DELETE. Exasol has no `RETURNING` and no `LIMIT` on DELETE, so both
|
|
324
|
+
* are stripped; `truncate` (which maps to `TRUNCATE TABLE`) is preserved.
|
|
325
|
+
*/
|
|
326
|
+
buildDeleteQuery(tableName, where, options) {
|
|
327
|
+
const { returning: _returning, limit: _limit, ...rest } = options || {};
|
|
328
|
+
return super.buildDeleteQuery(tableName, where, rest);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Build an Exasol `IMPORT INTO <table> FROM <format> AT '<endpoint>' FILE '<path>'`
|
|
332
|
+
* statement for bulk-loading data. `schema` on the options, if any, is not
|
|
333
|
+
* used here; qualify the table name yourself if needed.
|
|
334
|
+
*/
|
|
335
|
+
buildImportSQL(tableName, options) {
|
|
336
|
+
const format = options.format || 'CSV';
|
|
337
|
+
return (`IMPORT INTO ${this.escapeId(tableName)} FROM ${format}` +
|
|
338
|
+
` AT '${options.at.replace(/'/g, "''")}' FILE '${options.file.replace(/'/g, "''")}'`);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Build an Exasol `EXPORT <table> INTO <format> AT '<endpoint>' FILE '<path>'`
|
|
342
|
+
* statement for bulk-unloading data.
|
|
343
|
+
*/
|
|
344
|
+
buildExportSQL(tableName, options) {
|
|
345
|
+
const format = options.format || 'CSV';
|
|
346
|
+
return (`EXPORT ${this.escapeId(tableName)} INTO ${format}` +
|
|
347
|
+
` AT '${options.at.replace(/'/g, "''")}' FILE '${options.file.replace(/'/g, "''")}'`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
exports.ExasolDialect = ExasolDialect;
|
|
351
|
+
/**
|
|
352
|
+
* Create a new Exasol dialect instance.
|
|
353
|
+
*/
|
|
354
|
+
function createExasolDialect(options) {
|
|
355
|
+
return new ExasolDialect(options || {});
|
|
356
|
+
}
|
|
357
|
+
exports.default = ExasolDialect;
|