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,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* YugabyteDB dialect implementation for the TypeScript ORM
|
|
4
|
+
*
|
|
5
|
+
* YugabyteDB's YSQL API reuses the PostgreSQL query layer (it is literally
|
|
6
|
+
* forked from the PostgreSQL source), so it speaks the PostgreSQL wire
|
|
7
|
+
* protocol and is largely SQL-compatible with PostgreSQL. This dialect
|
|
8
|
+
* therefore `extends PostgresDialect` and reuses the same `pg` driver
|
|
9
|
+
* (`library === 'pg'`). Notable differences from the Postgres dialect that
|
|
10
|
+
* this class layers on top:
|
|
11
|
+
*
|
|
12
|
+
* - Default port is 5433 (not Postgres's 5432). YugabyteDB's YSQL server
|
|
13
|
+
* listens on 5433 by default; 5432 is used by other services in some
|
|
14
|
+
* deployments.
|
|
15
|
+
* - `SPLIT INTO n TABLETS` / `SPLIT AT VALUES (...)`: because YugabyteDB
|
|
16
|
+
* shards ("tablets") tables across nodes, `CREATE TABLE`/`CREATE INDEX`
|
|
17
|
+
* accepts pre-splitting clauses to control the initial tablet layout.
|
|
18
|
+
* `SPLIT INTO n TABLETS` presplits a hash-sharded table/index into `n`
|
|
19
|
+
* tablets; `SPLIT AT VALUES ((a), (b), ...)` presplits a range-sharded
|
|
20
|
+
* table/index at the given range boundaries. See
|
|
21
|
+
* https://docs.yugabyte.com/preview/api/ysql/the-sql-language/statements/ddl_create_table/#split-into
|
|
22
|
+
* - Colocated tables: small tables can be co-located onto a single tablet
|
|
23
|
+
* with `WITH (colocated = true)` (older syntax) / `WITH (colocation = true)`
|
|
24
|
+
* to avoid the overhead of a tablet-per-table. See
|
|
25
|
+
* https://docs.yugabyte.com/preview/architecture/docdb-sharding/colocated-tables/
|
|
26
|
+
* - Primary-key column ordering: unlike Postgres, a YugabyteDB primary key
|
|
27
|
+
* column carries a sharding/sort directive — `HASH` (hash-sharded, the
|
|
28
|
+
* default for the first PK column) or `ASC`/`DESC` (range-sharded). This is
|
|
29
|
+
* emitted as `PRIMARY KEY (id HASH, created_at DESC)`. See
|
|
30
|
+
* https://docs.yugabyte.com/preview/architecture/docdb-sharding/sharding/
|
|
31
|
+
* - `CREATE TABLEGROUP`: YugabyteDB groups tables that should share tablets
|
|
32
|
+
* into a tablegroup; `createTableGroup()` is a small helper that emits the
|
|
33
|
+
* DDL and `buildCreateTableGroupSQL()` builds it synchronously.
|
|
34
|
+
*
|
|
35
|
+
* Behavioral notes shared with PostgreSQL (inherited, called out here so
|
|
36
|
+
* callers know the caveats):
|
|
37
|
+
* - Because YSQL is the PostgreSQL wire protocol, connection handling,
|
|
38
|
+
* parameter binding, transactions, and most query building are inherited
|
|
39
|
+
* unchanged from {@link PostgresDialect}.
|
|
40
|
+
* - `CREATE INDEX ... CONCURRENTLY` behaves differently: in YugabyteDB online
|
|
41
|
+
* index backfill is the default mechanism and `CONCURRENTLY` has its own
|
|
42
|
+
* semantics/restrictions (and cannot run inside a transaction block), so it
|
|
43
|
+
* should not be assumed to behave identically to vanilla PostgreSQL.
|
|
44
|
+
* - Some PostgreSQL system-catalog (`pg_catalog`) internals differ: YugabyteDB
|
|
45
|
+
* emulates the catalogs for compatibility but a handful of columns/values
|
|
46
|
+
* reflect its distributed storage rather than a single-node heap.
|
|
47
|
+
*/
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.YugabyteDBDialect = void 0;
|
|
50
|
+
exports.createYugabyteDBDialect = createYugabyteDBDialect;
|
|
51
|
+
const index_1 = require("../postgres/index");
|
|
52
|
+
/**
|
|
53
|
+
* YugabyteDB dialect. Postgres-wire-compatible: reuses the `pg` driver and the
|
|
54
|
+
* PostgreSQL query-building layer, layering on YugabyteDB's distributed-table
|
|
55
|
+
* DDL (tablet splitting, colocation, hash/range primary keys, tablegroups).
|
|
56
|
+
*/
|
|
57
|
+
class YugabyteDBDialect extends index_1.PostgresDialect {
|
|
58
|
+
constructor(config) {
|
|
59
|
+
// YugabyteDB's YSQL server defaults to port 5433 (not Postgres's 5432).
|
|
60
|
+
// An explicit `config.port` still wins because it's spread last.
|
|
61
|
+
super({ port: 5433, ...config });
|
|
62
|
+
// Override the inherited `readonly name = 'postgres'`. YugabyteDB reuses the
|
|
63
|
+
// pg driver, so `library` ('pg') is inherited unchanged.
|
|
64
|
+
this.name = 'yugabytedb';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Quote a `SPLIT AT VALUES` / `PRIMARY KEY` scalar for inlining into DDL:
|
|
68
|
+
* numbers pass through, everything else is single-quoted and escaped.
|
|
69
|
+
*/
|
|
70
|
+
quoteSplitValue(value) {
|
|
71
|
+
if (typeof value === 'number') {
|
|
72
|
+
return String(value);
|
|
73
|
+
}
|
|
74
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the trailing YugabyteDB-specific clauses for a `CREATE TABLE`
|
|
78
|
+
* statement (colocation, tablegroup, tablet splitting), in the order
|
|
79
|
+
* YugabyteDB expects them. Returns an empty string when none apply.
|
|
80
|
+
*/
|
|
81
|
+
buildYugabyteTableClauses(options) {
|
|
82
|
+
if (!options) {
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
const parts = [];
|
|
86
|
+
// Colocation: `WITH (colocated = true)` / `WITH (colocation = true)`.
|
|
87
|
+
if (options.colocation !== undefined) {
|
|
88
|
+
parts.push(`WITH (colocation = ${options.colocation ? 'true' : 'false'})`);
|
|
89
|
+
}
|
|
90
|
+
else if (options.colocated !== undefined) {
|
|
91
|
+
parts.push(`WITH (colocated = ${options.colocated ? 'true' : 'false'})`);
|
|
92
|
+
}
|
|
93
|
+
// Tablegroup placement.
|
|
94
|
+
if (options.tablegroup) {
|
|
95
|
+
parts.push(`TABLEGROUP ${this.escapeId(options.tablegroup)}`);
|
|
96
|
+
}
|
|
97
|
+
// Presplit a hash-sharded table into N tablets.
|
|
98
|
+
if (options.splitIntoTablets !== undefined) {
|
|
99
|
+
parts.push(`SPLIT INTO ${options.splitIntoTablets} TABLETS`);
|
|
100
|
+
}
|
|
101
|
+
// Presplit a range-sharded table at explicit boundaries.
|
|
102
|
+
if (options.splitAtValues && options.splitAtValues.length > 0) {
|
|
103
|
+
const points = options.splitAtValues
|
|
104
|
+
.map((row) => `(${row.map((v) => this.quoteSplitValue(v)).join(', ')})`)
|
|
105
|
+
.join(', ');
|
|
106
|
+
parts.push(`SPLIT AT VALUES (${points})`);
|
|
107
|
+
}
|
|
108
|
+
return parts.length > 0 ? ` ${parts.join(' ')}` : '';
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Format a column `DEFAULT` value for inlining into DDL. Mirrors the base
|
|
112
|
+
* PostgreSQL dialect's behavior (which lives in a private helper we cannot
|
|
113
|
+
* call from here): numbers/booleans pass through; strings that look like a
|
|
114
|
+
* SQL function call (`gen_random_uuid()`), a `CURRENT_*` keyword, or `NULL`
|
|
115
|
+
* are emitted raw rather than quoted; `DataType` instances that expose
|
|
116
|
+
* `toDefaultValue()` (e.g. `DataTypes.NOW`) delegate to it; everything else
|
|
117
|
+
* is single-quoted and escaped.
|
|
118
|
+
*/
|
|
119
|
+
formatDefaultValue(value) {
|
|
120
|
+
if (value === null) {
|
|
121
|
+
return 'NULL';
|
|
122
|
+
}
|
|
123
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
124
|
+
return String(value);
|
|
125
|
+
}
|
|
126
|
+
if (typeof value === 'string') {
|
|
127
|
+
if (value.toUpperCase().includes('CURRENT_') ||
|
|
128
|
+
value.toUpperCase() === 'NULL' ||
|
|
129
|
+
/^[a-zA-Z_][a-zA-Z0-9_.]*\([^)]*\)$/.test(value.trim())) {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
133
|
+
}
|
|
134
|
+
if (typeof value === 'object' &&
|
|
135
|
+
value !== null &&
|
|
136
|
+
typeof value.toDefaultValue === 'function') {
|
|
137
|
+
return value.toDefaultValue();
|
|
138
|
+
}
|
|
139
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Emit a column-level `REFERENCES` (foreign key) clause, if the column
|
|
143
|
+
* carries one. Handles composite reference targets.
|
|
144
|
+
*/
|
|
145
|
+
buildColumnReferencesSql(definition) {
|
|
146
|
+
if (!definition.references) {
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
const refField = definition.references.field;
|
|
150
|
+
const refFieldSql = Array.isArray(refField)
|
|
151
|
+
? `(${refField.map((f) => this.escapeId(f)).join(', ')})`
|
|
152
|
+
: `(${this.escapeId(refField)})`;
|
|
153
|
+
let sql = ` REFERENCES ${this.escapeId(definition.references.table)}${refFieldSql}`;
|
|
154
|
+
if (definition.references.onDelete) {
|
|
155
|
+
sql += ` ON DELETE ${definition.references.onDelete}`;
|
|
156
|
+
}
|
|
157
|
+
if (definition.references.onUpdate) {
|
|
158
|
+
sql += ` ON UPDATE ${definition.references.onUpdate}`;
|
|
159
|
+
}
|
|
160
|
+
return sql;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Build a single column definition for a `CREATE TABLE` statement. Kept
|
|
164
|
+
* self-contained (rather than reusing the base class's private helper) so
|
|
165
|
+
* this dialect can synchronously assemble DDL. Column-level `primaryKey` is
|
|
166
|
+
* intentionally NOT emitted here — YugabyteDB primary keys are emitted as a
|
|
167
|
+
* table-level `PRIMARY KEY (...)` (see {@link buildPrimaryKeyClause}) so the
|
|
168
|
+
* per-column `HASH`/`ASC`/`DESC` directive can be attached.
|
|
169
|
+
*/
|
|
170
|
+
buildColumnDefinitionSql(columnName, definition) {
|
|
171
|
+
const dt = definition.type;
|
|
172
|
+
const isSerial = definition.autoIncrement && (dt.key === 'INTEGER' || !dt.key);
|
|
173
|
+
let sql = `${this.escapeId(columnName)} ${isSerial ? 'SERIAL' : this.getDataTypeSql(definition.type)}`;
|
|
174
|
+
if (definition.allowNull === false) {
|
|
175
|
+
sql += ' NOT NULL';
|
|
176
|
+
}
|
|
177
|
+
if (definition.defaultValue !== undefined) {
|
|
178
|
+
sql += ` DEFAULT ${this.formatDefaultValue(definition.defaultValue)}`;
|
|
179
|
+
}
|
|
180
|
+
if (definition.unique) {
|
|
181
|
+
sql += ' UNIQUE';
|
|
182
|
+
}
|
|
183
|
+
sql += this.buildColumnReferencesSql(definition);
|
|
184
|
+
return sql;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build a table-level constraint clause (`PRIMARY KEY`/`UNIQUE`/
|
|
188
|
+
* `FOREIGN KEY`/`CHECK`) for inlining into a `CREATE TABLE` statement.
|
|
189
|
+
* Mirrors the base PostgreSQL dialect's private helper (which we cannot call
|
|
190
|
+
* from here). Returns null for an unrecognized/empty constraint.
|
|
191
|
+
*/
|
|
192
|
+
buildYbConstraintSql(constraint) {
|
|
193
|
+
const name = constraint.name ? `${this.escapeId(constraint.name)} ` : '';
|
|
194
|
+
const fields = constraint.fields?.map((f) => this.escapeId(f)).join(', ') || '';
|
|
195
|
+
switch (constraint.type) {
|
|
196
|
+
case 'PRIMARY KEY':
|
|
197
|
+
return `${name}PRIMARY KEY (${fields})`;
|
|
198
|
+
case 'UNIQUE':
|
|
199
|
+
return `${name}UNIQUE (${fields})`;
|
|
200
|
+
case 'FOREIGN KEY': {
|
|
201
|
+
if (!constraint.references)
|
|
202
|
+
return null;
|
|
203
|
+
const refField = constraint.references.field;
|
|
204
|
+
const refFieldSql = Array.isArray(refField)
|
|
205
|
+
? `(${refField.map((f) => this.escapeId(f)).join(', ')})`
|
|
206
|
+
: `(${this.escapeId(refField)})`;
|
|
207
|
+
let fkSql = `${name}FOREIGN KEY (${fields}) REFERENCES ${this.escapeId(constraint.references.table)}${refFieldSql}`;
|
|
208
|
+
if (constraint.references.onDelete) {
|
|
209
|
+
fkSql += ` ON DELETE ${constraint.references.onDelete}`;
|
|
210
|
+
}
|
|
211
|
+
if (constraint.references.onUpdate) {
|
|
212
|
+
fkSql += ` ON UPDATE ${constraint.references.onUpdate}`;
|
|
213
|
+
}
|
|
214
|
+
return fkSql;
|
|
215
|
+
}
|
|
216
|
+
case 'CHECK':
|
|
217
|
+
if (!constraint.check)
|
|
218
|
+
return null;
|
|
219
|
+
return `${name}CHECK (${constraint.check})`;
|
|
220
|
+
default:
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Build the table-level `PRIMARY KEY (col HASH, col2 ASC, ...)` clause from
|
|
226
|
+
* either the explicit {@link YugabyteTableOptions.primaryKey} directive list
|
|
227
|
+
* or, failing that, any columns flagged with column-level `primaryKey: true`
|
|
228
|
+
* (which get no explicit sharding directive). Returns null when there is no
|
|
229
|
+
* primary key to emit.
|
|
230
|
+
*/
|
|
231
|
+
buildPrimaryKeyClause(columns, options) {
|
|
232
|
+
if (options?.primaryKey && options.primaryKey.length > 0) {
|
|
233
|
+
const cols = options.primaryKey
|
|
234
|
+
.map((pk) => `${this.escapeId(pk.name)}${pk.order ? ` ${pk.order}` : ''}`)
|
|
235
|
+
.join(', ');
|
|
236
|
+
return `PRIMARY KEY (${cols})`;
|
|
237
|
+
}
|
|
238
|
+
const pkColumns = Object.entries(columns)
|
|
239
|
+
.filter(([, def]) => def.primaryKey)
|
|
240
|
+
.map(([name]) => this.escapeId(name));
|
|
241
|
+
if (pkColumns.length > 0) {
|
|
242
|
+
return `PRIMARY KEY (${pkColumns.join(', ')})`;
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Synchronously build a YugabyteDB `CREATE TABLE` statement, including the
|
|
248
|
+
* distributed-table clauses (hash/range primary key, colocation,
|
|
249
|
+
* tablegroup, tablet splitting). Used by {@link createTable} and directly
|
|
250
|
+
* testable without a live connection.
|
|
251
|
+
*/
|
|
252
|
+
buildCreateTableSQL(tableName, columns, options) {
|
|
253
|
+
const defs = [];
|
|
254
|
+
const hasTablePk = !!(options?.primaryKey && options.primaryKey.length > 0);
|
|
255
|
+
for (const [columnName, definition] of Object.entries(columns)) {
|
|
256
|
+
// When a table-level PK directive is supplied, strip any column-level
|
|
257
|
+
// primaryKey flag so we don't emit two PRIMARY KEY clauses.
|
|
258
|
+
const def = hasTablePk ? { ...definition, primaryKey: false } : definition;
|
|
259
|
+
defs.push(this.buildColumnDefinitionSql(columnName, def));
|
|
260
|
+
}
|
|
261
|
+
const pkClause = this.buildPrimaryKeyClause(columns, options);
|
|
262
|
+
if (pkClause) {
|
|
263
|
+
defs.push(pkClause);
|
|
264
|
+
}
|
|
265
|
+
// Table-level constraints (FOREIGN KEY / UNIQUE / CHECK / PRIMARY KEY).
|
|
266
|
+
// A PRIMARY KEY passed here is skipped when a YugabyteDB PK directive
|
|
267
|
+
// (column-level or `options.primaryKey`) already produced a PK clause, to
|
|
268
|
+
// avoid emitting two PRIMARY KEY definitions.
|
|
269
|
+
if (options?.constraints) {
|
|
270
|
+
for (const constraint of options.constraints) {
|
|
271
|
+
if (constraint.type === 'PRIMARY KEY' && pkClause) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const constraintSql = this.buildYbConstraintSql(constraint);
|
|
275
|
+
if (constraintSql) {
|
|
276
|
+
defs.push(constraintSql);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
let sql = 'CREATE TABLE';
|
|
281
|
+
if (options?.ifNotExists) {
|
|
282
|
+
sql += ' IF NOT EXISTS';
|
|
283
|
+
}
|
|
284
|
+
sql += ` ${this.escapeId(tableName)} (${defs.join(', ')})`;
|
|
285
|
+
sql += this.buildYugabyteTableClauses(options);
|
|
286
|
+
return sql;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Create a new table. Overrides {@link PostgresDialect.createTable} so the
|
|
290
|
+
* YugabyteDB-specific clauses (tablet splitting, colocation, hash/range
|
|
291
|
+
* primary keys, tablegroup) are emitted. Falls back to the inherited
|
|
292
|
+
* Postgres implementation when no YugabyteDB-specific option is present, so
|
|
293
|
+
* indexes/comments/uniqueKeys handling is preserved for the common case.
|
|
294
|
+
*/
|
|
295
|
+
async createTable(tableName, columns, options) {
|
|
296
|
+
const usesYugabyteFeatures = !!options &&
|
|
297
|
+
(options.splitIntoTablets !== undefined ||
|
|
298
|
+
(options.splitAtValues && options.splitAtValues.length > 0) ||
|
|
299
|
+
options.colocated !== undefined ||
|
|
300
|
+
options.colocation !== undefined ||
|
|
301
|
+
options.tablegroup !== undefined ||
|
|
302
|
+
(options.primaryKey && options.primaryKey.length > 0));
|
|
303
|
+
if (!usesYugabyteFeatures) {
|
|
304
|
+
return super.createTable(tableName, columns, options);
|
|
305
|
+
}
|
|
306
|
+
await this.query(this.buildCreateTableSQL(tableName, columns, options));
|
|
307
|
+
// Post-creation steps. These mirror PostgresDialect.createTable so that
|
|
308
|
+
// uniqueKeys/comment/initialAutoIncrement/indexes are still honored when a
|
|
309
|
+
// YugabyteDB-specific clause forced us down the custom DDL path (they are
|
|
310
|
+
// emitted as separate statements, exactly as the base dialect does).
|
|
311
|
+
if (options) {
|
|
312
|
+
await this.applyPostCreateTableSteps(tableName, columns, options);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Emit the follow-up statements PostgresDialect runs after `CREATE TABLE`
|
|
317
|
+
* (unique keys, table comment, sequence start value, secondary indexes).
|
|
318
|
+
* Kept here because the base dialect performs them inline in its own
|
|
319
|
+
* `createTable`, which the YugabyteDB custom-DDL path bypasses.
|
|
320
|
+
*/
|
|
321
|
+
async applyPostCreateTableSteps(tableName, columns, options) {
|
|
322
|
+
// Unique keys — supports both the array format and the legacy object map.
|
|
323
|
+
if (options.uniqueKeys) {
|
|
324
|
+
if (Array.isArray(options.uniqueKeys)) {
|
|
325
|
+
for (const uk of options.uniqueKeys) {
|
|
326
|
+
const constraintName = uk.name || `${tableName}_${uk.fields.join('_')}_key`;
|
|
327
|
+
await this.query(`ALTER TABLE ${this.escapeId(tableName)} ADD CONSTRAINT ${this.escapeId(constraintName)} UNIQUE (${uk.fields.map((f) => this.escapeId(f)).join(', ')})`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
for (const [keyName, fields] of Object.entries(options.uniqueKeys)) {
|
|
332
|
+
const constraintName = keyName || `${tableName}_${fields.join('_')}_key`;
|
|
333
|
+
await this.query(`ALTER TABLE ${this.escapeId(tableName)} ADD CONSTRAINT ${this.escapeId(constraintName)} UNIQUE (${fields.map((f) => this.escapeId(f)).join(', ')})`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Table comment.
|
|
338
|
+
if (options.comment) {
|
|
339
|
+
await this.query(`COMMENT ON TABLE ${this.escapeId(tableName)} IS '${options.comment.replace(/'/g, "''")}'`);
|
|
340
|
+
}
|
|
341
|
+
// Sequence start value for the auto-increment (SERIAL) column.
|
|
342
|
+
if (options.initialAutoIncrement) {
|
|
343
|
+
for (const [columnName, definition] of Object.entries(columns)) {
|
|
344
|
+
if (definition.autoIncrement) {
|
|
345
|
+
const sequenceName = `${tableName}_${columnName}_seq`;
|
|
346
|
+
await this.query(`ALTER SEQUENCE ${this.escapeId(sequenceName)} START WITH ${options.initialAutoIncrement}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Secondary indexes.
|
|
351
|
+
if (options.indexes) {
|
|
352
|
+
for (const index of options.indexes) {
|
|
353
|
+
await this.addIndex(tableName, index.name || `idx_${tableName}_${index.fields.join('_')}`, index.fields, {
|
|
354
|
+
unique: index.unique,
|
|
355
|
+
type: index.type,
|
|
356
|
+
using: index.using,
|
|
357
|
+
where: index.where,
|
|
358
|
+
expression: index.expression,
|
|
359
|
+
include: index.include,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Add an index to a table.
|
|
366
|
+
*
|
|
367
|
+
* Overrides {@link PostgresDialect.addIndex} only to account for
|
|
368
|
+
* YugabyteDB's `CREATE INDEX ... CONCURRENTLY` divergence: in YugabyteDB
|
|
369
|
+
* index backfill is already online by default, and `CONCURRENTLY` carries
|
|
370
|
+
* different semantics/restrictions (notably it cannot run inside a
|
|
371
|
+
* transaction block). Like the CockroachDB dialect, a requested
|
|
372
|
+
* `concurrently` flag is ignored (with a warning) rather than emitted, so
|
|
373
|
+
* the generated SQL stays safe to run in the common (transactional) case.
|
|
374
|
+
* All other index-building behavior is inherited unchanged.
|
|
375
|
+
*/
|
|
376
|
+
async addIndex(tableName, indexName, fields = [], options) {
|
|
377
|
+
if (options?.concurrently) {
|
|
378
|
+
console.warn('YugabyteDB: CREATE INDEX CONCURRENTLY is online by default and has ' +
|
|
379
|
+
'distinct semantics (it cannot run inside a transaction block). The ' +
|
|
380
|
+
'`concurrently` option will be ignored.');
|
|
381
|
+
}
|
|
382
|
+
return super.addIndex(tableName, indexName, fields, options);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Build a `CREATE TABLEGROUP` statement synchronously.
|
|
386
|
+
*/
|
|
387
|
+
buildCreateTableGroupSQL(name, options) {
|
|
388
|
+
let sql = 'CREATE TABLEGROUP';
|
|
389
|
+
if (options?.ifNotExists) {
|
|
390
|
+
sql += ' IF NOT EXISTS';
|
|
391
|
+
}
|
|
392
|
+
sql += ` ${this.escapeId(name)}`;
|
|
393
|
+
if (options?.owner) {
|
|
394
|
+
sql += ` OWNER ${this.escapeId(options.owner)}`;
|
|
395
|
+
}
|
|
396
|
+
return sql;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Create a tablegroup (`CREATE TABLEGROUP name`). Tables created with the
|
|
400
|
+
* `tablegroup` option share the tablegroup's tablets.
|
|
401
|
+
*/
|
|
402
|
+
async createTableGroup(name, options) {
|
|
403
|
+
await this.query(this.buildCreateTableGroupSQL(name, options));
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Drop a tablegroup (`DROP TABLEGROUP [IF EXISTS] name`).
|
|
407
|
+
*/
|
|
408
|
+
async dropTableGroup(name, options) {
|
|
409
|
+
let sql = 'DROP TABLEGROUP';
|
|
410
|
+
if (options?.ifExists) {
|
|
411
|
+
sql += ' IF EXISTS';
|
|
412
|
+
}
|
|
413
|
+
sql += ` ${this.escapeId(name)}`;
|
|
414
|
+
await this.query(sql);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
exports.YugabyteDBDialect = YugabyteDBDialect;
|
|
418
|
+
/**
|
|
419
|
+
* Create a new YugabyteDB dialect instance.
|
|
420
|
+
*/
|
|
421
|
+
function createYugabyteDBDialect(options) {
|
|
422
|
+
return new YugabyteDBDialect(options || {});
|
|
423
|
+
}
|
|
424
|
+
exports.default = YugabyteDBDialect;
|