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,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Trino (formerly PrestoSQL) dialect implementation for the TypeScript ORM.
|
|
4
|
+
*
|
|
5
|
+
* Trino is a distributed, federated SQL query engine. It is *not* a storage
|
|
6
|
+
* engine of its own: it runs ANSI SQL over pluggable connectors (Hive, Iceberg,
|
|
7
|
+
* MySQL, PostgreSQL, Kafka, ...). Because its SQL surface is ANSI-flavored and
|
|
8
|
+
* it quotes identifiers with double quotes (like PostgreSQL), this dialect
|
|
9
|
+
* extends {@link PostgresDialect} and overrides only where Trino differs.
|
|
10
|
+
*
|
|
11
|
+
* Key differences from PostgreSQL that this dialect implements:
|
|
12
|
+
*
|
|
13
|
+
* - **Default port 8080.** Trino's HTTP/query port is 8080, not 5432.
|
|
14
|
+
* The constructor injects it via `super({ port: 8080, ...config })`.
|
|
15
|
+
*
|
|
16
|
+
* - **Three-part table names: `catalog.schema.table`.** A Trino table lives in
|
|
17
|
+
* a connector *catalog* and a *schema*. When a `catalog` is configured (and,
|
|
18
|
+
* optionally, a default `schema`), {@link TrinoDialect.quoteTable} emits the
|
|
19
|
+
* fully-qualified `"catalog"."schema"."table"` form. Without a catalog it
|
|
20
|
+
* falls back to the PostgreSQL `schema.table` behavior.
|
|
21
|
+
*
|
|
22
|
+
* - **Connector table properties via `WITH (...)`.** `CREATE TABLE ... WITH
|
|
23
|
+
* (format = 'ORC', partitioning = ARRAY['col'])` configures the underlying
|
|
24
|
+
* connector (file format, partitioning, bucketing, ...). Exposed through
|
|
25
|
+
* {@link TrinoTableOptions} (`format`, `partitioning`, `tableProperties`).
|
|
26
|
+
*
|
|
27
|
+
* - **`CREATE TABLE AS SELECT` (CTAS).** Trino's primary way to materialize a
|
|
28
|
+
* table from a query. Exposed via {@link TrinoDialect.buildCreateTableAsSelectSQL}
|
|
29
|
+
* (sync SQL builder) and {@link TrinoDialect.createTableAsSelect} (executes it).
|
|
30
|
+
*
|
|
31
|
+
* - **No PRIMARY KEY / FOREIGN KEY / UNIQUE enforcement.** Trino does not
|
|
32
|
+
* support (or enforce) key constraints — `CREATE TABLE` here omits any
|
|
33
|
+
* `PRIMARY KEY`, `FOREIGN KEY`, or `UNIQUE` clause entirely. Constraint
|
|
34
|
+
* metadata on columns/tables is ignored for DDL purposes.
|
|
35
|
+
*
|
|
36
|
+
* - **No AUTO_INCREMENT / identity / sequences.** Trino has no
|
|
37
|
+
* SERIAL/BIGSERIAL/IDENTITY. Surrogate keys are *not* auto-generated;
|
|
38
|
+
* application code (or the source connector) must supply key values. The
|
|
39
|
+
* `autoIncrement` column flag is ignored.
|
|
40
|
+
*
|
|
41
|
+
* - **Type mapping.** Trino uses unbounded `VARCHAR` (no length required),
|
|
42
|
+
* `DOUBLE` (not `DOUBLE PRECISION`), `BOOLEAN`, and `TIMESTAMP`. See
|
|
43
|
+
* {@link TrinoDialect.getDataTypeSql}.
|
|
44
|
+
*/
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.TrinoDialect = void 0;
|
|
47
|
+
exports.createTrinoDialect = createTrinoDialect;
|
|
48
|
+
const index_1 = require("../postgres/index");
|
|
49
|
+
const prorm_1 = require("../../prorm");
|
|
50
|
+
/**
|
|
51
|
+
* Trino / PrestoSQL federated query engine dialect. Extends {@link PostgresDialect}
|
|
52
|
+
* (ANSI SQL, double-quoted identifiers) and overrides Trino-specific behavior.
|
|
53
|
+
*/
|
|
54
|
+
class TrinoDialect extends index_1.PostgresDialect {
|
|
55
|
+
constructor(config) {
|
|
56
|
+
// Trino's default query port is 8080 (not PostgreSQL's 5432).
|
|
57
|
+
super({ port: 8080, ...config });
|
|
58
|
+
this.name = 'trino';
|
|
59
|
+
this.trinoCatalog = config.catalog;
|
|
60
|
+
this.trinoSchema = config.schema;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Quote a table name. When a connector catalog is configured, emit the Trino
|
|
64
|
+
* three-part `"catalog"."schema"."table"` form; otherwise defer to the
|
|
65
|
+
* PostgreSQL `schema.table` behavior.
|
|
66
|
+
*/
|
|
67
|
+
quoteTable(tableName, schema) {
|
|
68
|
+
if (this.trinoCatalog) {
|
|
69
|
+
const effectiveSchema = schema ?? this.trinoSchema;
|
|
70
|
+
const parts = [this.escapeId(this.trinoCatalog)];
|
|
71
|
+
if (effectiveSchema) {
|
|
72
|
+
parts.push(this.escapeId(effectiveSchema));
|
|
73
|
+
}
|
|
74
|
+
parts.push(this.escapeId(tableName));
|
|
75
|
+
return parts.join('.');
|
|
76
|
+
}
|
|
77
|
+
return super.quoteTable(tableName, schema);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Map a data type to Trino SQL. Trino uses unbounded `VARCHAR`, `DOUBLE`,
|
|
81
|
+
* `BOOLEAN`, and `TIMESTAMP`, and has no SERIAL/identity types.
|
|
82
|
+
*/
|
|
83
|
+
getDataTypeSql(dataType) {
|
|
84
|
+
if (typeof dataType === 'string') {
|
|
85
|
+
// The shared model-sync layer emits the cross-dialect 'DATETIME'
|
|
86
|
+
// pseudo-type for timestamp columns; Trino spells it TIMESTAMP.
|
|
87
|
+
if (/^DATETIME(\(\d+\))?$/i.test(dataType)) {
|
|
88
|
+
return dataType.replace(/^DATETIME/i, 'TIMESTAMP');
|
|
89
|
+
}
|
|
90
|
+
return dataType;
|
|
91
|
+
}
|
|
92
|
+
if (!dataType || typeof dataType !== 'object') {
|
|
93
|
+
return 'VARCHAR';
|
|
94
|
+
}
|
|
95
|
+
const dt = dataType;
|
|
96
|
+
switch (dt.key) {
|
|
97
|
+
case 'STRING':
|
|
98
|
+
case 'TEXT':
|
|
99
|
+
// Trino VARCHAR is unbounded by default — no length needed.
|
|
100
|
+
return 'VARCHAR';
|
|
101
|
+
case 'CHAR':
|
|
102
|
+
return dt.length ? `CHAR(${dt.length})` : 'CHAR';
|
|
103
|
+
case 'INTEGER':
|
|
104
|
+
// No SERIAL in Trino; auto-increment is not honored.
|
|
105
|
+
return 'INTEGER';
|
|
106
|
+
case 'BIGINT':
|
|
107
|
+
return 'BIGINT';
|
|
108
|
+
case 'FLOAT':
|
|
109
|
+
return 'REAL';
|
|
110
|
+
case 'DOUBLE':
|
|
111
|
+
return 'DOUBLE';
|
|
112
|
+
case 'DECIMAL':
|
|
113
|
+
return `DECIMAL(${dt.precision || 10}, ${dt.scale || 0})`;
|
|
114
|
+
case 'BOOLEAN':
|
|
115
|
+
return 'BOOLEAN';
|
|
116
|
+
case 'DATE':
|
|
117
|
+
return 'TIMESTAMP';
|
|
118
|
+
case 'DATEONLY':
|
|
119
|
+
return 'DATE';
|
|
120
|
+
case 'TIME':
|
|
121
|
+
return 'TIME';
|
|
122
|
+
case 'BLOB':
|
|
123
|
+
return 'VARBINARY';
|
|
124
|
+
case 'JSON':
|
|
125
|
+
case 'JSONB':
|
|
126
|
+
return 'JSON';
|
|
127
|
+
case 'UUID':
|
|
128
|
+
return 'UUID';
|
|
129
|
+
case 'ARRAY': {
|
|
130
|
+
const arrayType = dt.type || dt.subtype;
|
|
131
|
+
if (arrayType) {
|
|
132
|
+
return `ARRAY(${this.getDataTypeSql(arrayType)})`;
|
|
133
|
+
}
|
|
134
|
+
return 'ARRAY(VARCHAR)';
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
return 'VARCHAR';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Build a column definition fragment for Trino DDL. PRIMARY KEY, UNIQUE,
|
|
142
|
+
* FOREIGN KEY (references) and auto-increment are intentionally NOT emitted —
|
|
143
|
+
* Trino neither supports nor enforces them.
|
|
144
|
+
*/
|
|
145
|
+
getTrinoColumnDefinitionSql(columnName, definition) {
|
|
146
|
+
let sql = `${this.escapeId(columnName)} ${this.getDataTypeSql(definition.type)}`;
|
|
147
|
+
if (definition.allowNull === false) {
|
|
148
|
+
sql += ' NOT NULL';
|
|
149
|
+
}
|
|
150
|
+
if (definition.comment) {
|
|
151
|
+
sql += ` COMMENT '${String(definition.comment).replace(/'/g, "''")}'`;
|
|
152
|
+
}
|
|
153
|
+
return sql;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Build the `WITH (...)` connector-properties clause (or '' when there are
|
|
157
|
+
* no properties). Handles `format`, `partitioning`, and `tableProperties`.
|
|
158
|
+
*/
|
|
159
|
+
buildTablePropertiesClause(options) {
|
|
160
|
+
if (!options)
|
|
161
|
+
return '';
|
|
162
|
+
const props = [];
|
|
163
|
+
if (options.format) {
|
|
164
|
+
props.push(`format = '${String(options.format).replace(/'/g, "''")}'`);
|
|
165
|
+
}
|
|
166
|
+
if (options.partitioning && options.partitioning.length > 0) {
|
|
167
|
+
const cols = options.partitioning.map((c) => `'${String(c).replace(/'/g, "''")}'`).join(', ');
|
|
168
|
+
props.push(`partitioning = ARRAY[${cols}]`);
|
|
169
|
+
}
|
|
170
|
+
if (options.tableProperties) {
|
|
171
|
+
for (const [key, value] of Object.entries(options.tableProperties)) {
|
|
172
|
+
if (typeof value === 'string') {
|
|
173
|
+
props.push(`${key} = '${value.replace(/'/g, "''")}'`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
props.push(`${key} = ${value}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return props.length > 0 ? `WITH (${props.join(', ')})` : '';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Build (synchronously) a Trino `CREATE TABLE` statement. Omits all key
|
|
184
|
+
* constraints (PK/FK/UNIQUE) and appends connector `WITH (...)` properties.
|
|
185
|
+
*/
|
|
186
|
+
buildCreateTableSQL(tableName, columns, options) {
|
|
187
|
+
const columnDefs = Object.entries(columns)
|
|
188
|
+
.map(([name, def]) => this.getTrinoColumnDefinitionSql(name, def))
|
|
189
|
+
.filter((s) => s.trim().length > 0);
|
|
190
|
+
let sql = 'CREATE TABLE';
|
|
191
|
+
if (options?.ifNotExists) {
|
|
192
|
+
sql += ' IF NOT EXISTS';
|
|
193
|
+
}
|
|
194
|
+
sql += ` ${this.quoteTable(tableName, options?.schema)} (${columnDefs.join(', ')})`;
|
|
195
|
+
if (options?.comment) {
|
|
196
|
+
sql += ` COMMENT '${String(options.comment).replace(/'/g, "''")}'`;
|
|
197
|
+
}
|
|
198
|
+
const props = this.buildTablePropertiesClause(options);
|
|
199
|
+
if (props) {
|
|
200
|
+
sql += ` ${props}`;
|
|
201
|
+
}
|
|
202
|
+
return sql;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Build (synchronously) a Trino `CREATE TABLE ... AS SELECT` (CTAS) statement.
|
|
206
|
+
*
|
|
207
|
+
* @param tableName - Name of the table to create.
|
|
208
|
+
* @param selectQuery - The `SELECT ...` query (raw SQL) to populate it from.
|
|
209
|
+
* @param options - Connector properties and CTAS options.
|
|
210
|
+
*/
|
|
211
|
+
buildCreateTableAsSelectSQL(tableName, selectQuery, options) {
|
|
212
|
+
let sql = 'CREATE TABLE';
|
|
213
|
+
if (options?.ifNotExists) {
|
|
214
|
+
sql += ' IF NOT EXISTS';
|
|
215
|
+
}
|
|
216
|
+
sql += ` ${this.quoteTable(tableName, options?.schema)}`;
|
|
217
|
+
if (options?.comment) {
|
|
218
|
+
sql += ` COMMENT '${String(options.comment).replace(/'/g, "''")}'`;
|
|
219
|
+
}
|
|
220
|
+
const props = this.buildTablePropertiesClause(options);
|
|
221
|
+
if (props) {
|
|
222
|
+
sql += ` ${props}`;
|
|
223
|
+
}
|
|
224
|
+
sql += ` AS ${selectQuery}`;
|
|
225
|
+
if (options?.withNoData) {
|
|
226
|
+
sql += ' WITH NO DATA';
|
|
227
|
+
}
|
|
228
|
+
return sql;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Create a table in Trino. Overrides the PostgreSQL implementation to omit
|
|
232
|
+
* key constraints and support connector `WITH (...)` properties.
|
|
233
|
+
*/
|
|
234
|
+
async createTable(tableName, columns, options) {
|
|
235
|
+
await this.query(this.buildCreateTableSQL(tableName, columns, options));
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Execute a `CREATE TABLE AS SELECT` (CTAS) statement.
|
|
239
|
+
*/
|
|
240
|
+
async createTableAsSelect(tableName, selectQuery, options) {
|
|
241
|
+
await this.query(this.buildCreateTableAsSelectSQL(tableName, selectQuery, options));
|
|
242
|
+
}
|
|
243
|
+
// ==========================================================================
|
|
244
|
+
// DDL: DROP TABLE / ADD COLUMN / DROP COLUMN
|
|
245
|
+
//
|
|
246
|
+
// These override the PostgreSQL versions so they (a) use the Trino
|
|
247
|
+
// catalog.schema.table naming from quoteTable() and (b) emit only clauses
|
|
248
|
+
// Trino actually accepts. Trino has no CASCADE on DROP TABLE, and column
|
|
249
|
+
// definitions may not carry PK / UNIQUE / FOREIGN KEY / DEFAULT / SERIAL.
|
|
250
|
+
// ==========================================================================
|
|
251
|
+
/**
|
|
252
|
+
* Drop a table. Trino's `DROP TABLE` supports `IF EXISTS` but has no
|
|
253
|
+
* `CASCADE` (there are no dependent constraints to cascade).
|
|
254
|
+
*/
|
|
255
|
+
async dropTable(tableName, options) {
|
|
256
|
+
let sql = 'DROP TABLE';
|
|
257
|
+
if (options?.ifExists) {
|
|
258
|
+
sql += ' IF EXISTS';
|
|
259
|
+
}
|
|
260
|
+
sql += ` ${this.quoteTable(tableName)}`;
|
|
261
|
+
await this.query(sql);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Add a column. Uses the Trino column-definition builder (no constraints /
|
|
265
|
+
* default / SERIAL) and the catalog-qualified table name.
|
|
266
|
+
*/
|
|
267
|
+
async addColumn(tableName, columnName, definition) {
|
|
268
|
+
const sql = `ALTER TABLE ${this.quoteTable(tableName)} ADD COLUMN ${this.getTrinoColumnDefinitionSql(columnName, definition)}`;
|
|
269
|
+
await this.query(sql);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Remove a column. `ALTER TABLE ... DROP COLUMN` with catalog-qualified name.
|
|
273
|
+
*/
|
|
274
|
+
async removeColumn(tableName, columnName) {
|
|
275
|
+
const sql = `ALTER TABLE ${this.quoteTable(tableName)} DROP COLUMN ${this.escapeId(columnName)}`;
|
|
276
|
+
await this.query(sql);
|
|
277
|
+
}
|
|
278
|
+
// ==========================================================================
|
|
279
|
+
// Pagination: Trino orders OFFSET *before* LIMIT (unlike PostgreSQL's
|
|
280
|
+
// `LIMIT n OFFSET m`), and allows a standalone OFFSET.
|
|
281
|
+
// [ ORDER BY ... ] [ OFFSET count ] [ LIMIT count ]
|
|
282
|
+
// ==========================================================================
|
|
283
|
+
buildLimitOffset(limit, offset) {
|
|
284
|
+
let sql = '';
|
|
285
|
+
if (offset !== undefined) {
|
|
286
|
+
sql += ` OFFSET ${Number(offset)}`;
|
|
287
|
+
}
|
|
288
|
+
if (limit !== undefined) {
|
|
289
|
+
sql += ` LIMIT ${Number(limit)}`;
|
|
290
|
+
}
|
|
291
|
+
return sql;
|
|
292
|
+
}
|
|
293
|
+
// ==========================================================================
|
|
294
|
+
// CRUD builders
|
|
295
|
+
//
|
|
296
|
+
// Trino accepts standard `INSERT INTO ... VALUES`, `UPDATE ... SET ... WHERE`,
|
|
297
|
+
// and `DELETE FROM ... WHERE` (UPDATE/DELETE are connector-dependent at
|
|
298
|
+
// execution time). It has NO `RETURNING`, NO `ON CONFLICT`/upsert, and NO
|
|
299
|
+
// `LIMIT` on UPDATE/DELETE — so those clauses are never emitted. Tables are
|
|
300
|
+
// catalog-qualified via quoteTable().
|
|
301
|
+
// ==========================================================================
|
|
302
|
+
/**
|
|
303
|
+
* Build an INSERT query. Trino form: `INSERT INTO t (cols) VALUES (...)`.
|
|
304
|
+
* No `RETURNING` and no `ON CONFLICT`/upsert — requesting an upsert throws.
|
|
305
|
+
*/
|
|
306
|
+
buildInsertQuery(tableName, values, options) {
|
|
307
|
+
if (options?.upsert) {
|
|
308
|
+
throw new Error('Trino does not support upsert / ON CONFLICT. Trino has no primary-key or ' +
|
|
309
|
+
'unique constraints to conflict on. Use INSERT, or MERGE (on connectors ' +
|
|
310
|
+
'that support it) issued as raw SQL.');
|
|
311
|
+
}
|
|
312
|
+
const columns = Object.keys(values);
|
|
313
|
+
const processedValues = [];
|
|
314
|
+
const placeholders = [];
|
|
315
|
+
let paramIndex = 1;
|
|
316
|
+
for (const value of Object.values(values)) {
|
|
317
|
+
if (value instanceof prorm_1.Literal) {
|
|
318
|
+
placeholders.push(value.val);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
placeholders.push(`$${paramIndex}`);
|
|
322
|
+
processedValues.push(value);
|
|
323
|
+
paramIndex++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const sql = `INSERT INTO ${this.quoteTable(tableName, options?.schema)} (${columns
|
|
327
|
+
.map((c) => this.escapeId(c))
|
|
328
|
+
.join(', ')}) VALUES (${placeholders.join(', ')})`;
|
|
329
|
+
// Trino has no RETURNING — options.returning is intentionally ignored.
|
|
330
|
+
return { sql, values: processedValues };
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Trino has no upsert. Kept explicit so callers get a clear error instead of
|
|
334
|
+
* inheriting PostgreSQL's `INSERT ... ON CONFLICT` (invalid in Trino).
|
|
335
|
+
*/
|
|
336
|
+
buildUpsertQuery(_tableName, _values, _options) {
|
|
337
|
+
throw new Error('Trino does not support upsert / ON CONFLICT. Trino has no primary-key or ' +
|
|
338
|
+
'unique constraints to conflict on. Use INSERT, or MERGE (on connectors ' +
|
|
339
|
+
'that support it) issued as raw SQL.');
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Build an UPDATE query. No `RETURNING`, no `LIMIT` (Trino supports neither
|
|
343
|
+
* on UPDATE). Actual UPDATE support is connector-dependent at run time.
|
|
344
|
+
*/
|
|
345
|
+
buildUpdateQuery(tableName, values, where, _options) {
|
|
346
|
+
const setClauses = [];
|
|
347
|
+
const queryValues = [];
|
|
348
|
+
let paramIndex = 1;
|
|
349
|
+
for (const [key, value] of Object.entries(values)) {
|
|
350
|
+
if (value instanceof prorm_1.Literal) {
|
|
351
|
+
setClauses.push(`${this.escapeId(key)} = ${value.val}`);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
setClauses.push(`${this.escapeId(key)} = $${paramIndex}`);
|
|
355
|
+
queryValues.push(value);
|
|
356
|
+
paramIndex++;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const whereClause = this.buildWhereClause(where);
|
|
360
|
+
let sql = `UPDATE ${this.quoteTable(tableName)} SET ${setClauses.join(', ')}`;
|
|
361
|
+
if (whereClause.sql) {
|
|
362
|
+
sql += ` WHERE ${whereClause.sql}`;
|
|
363
|
+
}
|
|
364
|
+
return { sql, values: [...queryValues, ...whereClause.values] };
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Build a DELETE query. No `RETURNING`, no `LIMIT`. Trino has no `TRUNCATE`,
|
|
368
|
+
* so a `truncate` request degrades to an unqualified `DELETE FROM t`. Actual
|
|
369
|
+
* DELETE support is connector-dependent at run time.
|
|
370
|
+
*/
|
|
371
|
+
buildDeleteQuery(tableName, where, options) {
|
|
372
|
+
if (options?.truncate) {
|
|
373
|
+
// Trino has no TRUNCATE statement; delete every row instead.
|
|
374
|
+
return { sql: `DELETE FROM ${this.quoteTable(tableName)}`, values: [] };
|
|
375
|
+
}
|
|
376
|
+
const whereClause = this.buildWhereClause(where);
|
|
377
|
+
let sql = `DELETE FROM ${this.quoteTable(tableName)}`;
|
|
378
|
+
if (whereClause.sql) {
|
|
379
|
+
sql += ` WHERE ${whereClause.sql}`;
|
|
380
|
+
}
|
|
381
|
+
return { sql, values: whereClause.values };
|
|
382
|
+
}
|
|
383
|
+
// ==========================================================================
|
|
384
|
+
// Indexes: Trino has NO indexes. Query performance comes from the underlying
|
|
385
|
+
// connector's storage layout (partitioning / bucketing / sorting), which is
|
|
386
|
+
// configured through table `WITH (...)` properties, not `CREATE INDEX`.
|
|
387
|
+
// Every index entry point throws a clear, actionable error.
|
|
388
|
+
// ==========================================================================
|
|
389
|
+
noIndexes(method) {
|
|
390
|
+
throw new Error(`Trino does not support indexes (${method} is unavailable). Control data layout ` +
|
|
391
|
+
`and query performance with connector table properties instead — e.g. ` +
|
|
392
|
+
`CREATE TABLE ... WITH (partitioning = ARRAY[...], bucketed_by = ARRAY[...]).`);
|
|
393
|
+
}
|
|
394
|
+
async addIndex(_tableName, _indexName, _fields, _options) {
|
|
395
|
+
this.noIndexes('addIndex');
|
|
396
|
+
}
|
|
397
|
+
async createIndex(_tableName, _indexDef) {
|
|
398
|
+
this.noIndexes('createIndex');
|
|
399
|
+
}
|
|
400
|
+
async removeIndex(_tableName, _indexName) {
|
|
401
|
+
this.noIndexes('removeIndex');
|
|
402
|
+
}
|
|
403
|
+
async dropIndex(_tableName, _indexName, _options) {
|
|
404
|
+
this.noIndexes('dropIndex');
|
|
405
|
+
}
|
|
406
|
+
async createPartialIndex(_tableName, _indexName, _fields, _where, _options) {
|
|
407
|
+
this.noIndexes('createPartialIndex');
|
|
408
|
+
}
|
|
409
|
+
async createExpressionIndex(_tableName, _indexName, _expression, _options) {
|
|
410
|
+
this.noIndexes('createExpressionIndex');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
exports.TrinoDialect = TrinoDialect;
|
|
414
|
+
/**
|
|
415
|
+
* Create a new Trino dialect instance.
|
|
416
|
+
*/
|
|
417
|
+
function createTrinoDialect(options) {
|
|
418
|
+
return new TrinoDialect(options || {});
|
|
419
|
+
}
|
|
420
|
+
exports.default = TrinoDialect;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Turso / libSQL dialect implementation.
|
|
4
|
+
*
|
|
5
|
+
* Turso is a hosted libSQL service; libSQL itself is a SQLite-compatible
|
|
6
|
+
* fork, so the SQL this dialect generates (DDL, JSON helpers, upsert
|
|
7
|
+
* syntax, LIMIT/OFFSET pagination, etc.) is identical to `SQLiteDialect`'s.
|
|
8
|
+
* Rather than duplicate ~90 pure SQL-generation methods, this class
|
|
9
|
+
* extends `SQLiteDialect` and overrides only the pieces that depend on the
|
|
10
|
+
* driver: connection lifecycle, query execution, streaming, and
|
|
11
|
+
* transactions. `SQLiteDialect` reaches those through its own `private`
|
|
12
|
+
* fields, which subclasses can't touch, so this class keeps entirely
|
|
13
|
+
* separate connection/transaction state and never touches the parent's.
|
|
14
|
+
*
|
|
15
|
+
* The `@libsql/client` driver works identically for a local embedded
|
|
16
|
+
* replica (`file:` / `:memory:` URLs) and a remote Turso database
|
|
17
|
+
* (`libsql:`/`https:` URLs with an `authToken`), unlike `better-sqlite3`
|
|
18
|
+
* which is local-only — that's the whole point of this dialect existing
|
|
19
|
+
* separately from `SQLiteDialect`.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.TursoDialect = void 0;
|
|
23
|
+
exports.createTursoDialect = createTursoDialect;
|
|
24
|
+
const client_1 = require("@libsql/client");
|
|
25
|
+
const index_1 = require("../sqlite/index");
|
|
26
|
+
const query_stream_helper_1 = require("../query-stream-helper");
|
|
27
|
+
class TursoTransaction {
|
|
28
|
+
constructor(depth, options, dialect) {
|
|
29
|
+
this.dialect = dialect;
|
|
30
|
+
this.finished = false;
|
|
31
|
+
this.parent = null;
|
|
32
|
+
this.savepoints = [];
|
|
33
|
+
this.id = `sp_${depth}_${Date.now()}`;
|
|
34
|
+
this.options = options || {};
|
|
35
|
+
}
|
|
36
|
+
async commit() {
|
|
37
|
+
if (this.finished)
|
|
38
|
+
return;
|
|
39
|
+
await this.dialect.commitTransaction(this);
|
|
40
|
+
this.finished = true;
|
|
41
|
+
}
|
|
42
|
+
async rollback() {
|
|
43
|
+
if (this.finished)
|
|
44
|
+
return;
|
|
45
|
+
await this.dialect.rollbackTransaction(this);
|
|
46
|
+
this.finished = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Turso / libSQL dialect. See the module-level doc comment for why this
|
|
51
|
+
* extends `SQLiteDialect` instead of implementing `Dialect` from scratch.
|
|
52
|
+
*/
|
|
53
|
+
class TursoDialect extends index_1.SQLiteDialect {
|
|
54
|
+
constructor(config) {
|
|
55
|
+
// SQLiteDialect's constructor only reads `storage` (defaulted below) and
|
|
56
|
+
// is otherwise inert until connect() is called — connect() is fully
|
|
57
|
+
// overridden here, so the better-sqlite3 codepath it would normally run
|
|
58
|
+
// never executes.
|
|
59
|
+
super({ storage: config.url || ':memory:', ...config });
|
|
60
|
+
this.name = 'turso';
|
|
61
|
+
this.library = '@libsql/client';
|
|
62
|
+
this.client = null;
|
|
63
|
+
this._tursoConnected = false;
|
|
64
|
+
this.tursoTransactionDepth = 0;
|
|
65
|
+
this.tursoConfig = { url: ':memory:', ...config };
|
|
66
|
+
}
|
|
67
|
+
async connect() {
|
|
68
|
+
try {
|
|
69
|
+
this.client = (0, client_1.createClient)({
|
|
70
|
+
url: this.tursoConfig.url,
|
|
71
|
+
authToken: this.tursoConfig.authToken,
|
|
72
|
+
encryptionKey: this.tursoConfig.encryptionKey,
|
|
73
|
+
syncUrl: this.tursoConfig.syncUrl,
|
|
74
|
+
syncInterval: this.tursoConfig.syncInterval,
|
|
75
|
+
});
|
|
76
|
+
// Verify the connection actually works instead of deferring the
|
|
77
|
+
// failure to the caller's first query.
|
|
78
|
+
await this.client.execute('SELECT 1');
|
|
79
|
+
await this.client.execute('PRAGMA foreign_keys = ON');
|
|
80
|
+
this._tursoConnected = true;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new Error(`Failed to connect to Turso/libSQL database: ${error}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async disconnect() {
|
|
87
|
+
if (this.client) {
|
|
88
|
+
this.client.close();
|
|
89
|
+
this.client = null;
|
|
90
|
+
this._tursoConnected = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
getConnection() {
|
|
94
|
+
return this.client;
|
|
95
|
+
}
|
|
96
|
+
isConnected() {
|
|
97
|
+
return this._tursoConnected && this.client !== null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* `SQLiteAdvanced` (the parent class's `.advanced` getter) drives
|
|
101
|
+
* better-sqlite3's synchronous `Database` API directly, which the
|
|
102
|
+
* `@libsql/client` connection this dialect wraps doesn't expose.
|
|
103
|
+
*/
|
|
104
|
+
get advanced() {
|
|
105
|
+
throw new Error('TursoDialect does not support the .advanced SQLite extension API (it depends on a synchronous better-sqlite3 connection). Use the standard Dialect methods instead.');
|
|
106
|
+
}
|
|
107
|
+
async query(sql, options) {
|
|
108
|
+
if (!this.client) {
|
|
109
|
+
throw new Error('Not connected to database');
|
|
110
|
+
}
|
|
111
|
+
const sqlUpper = sql.trim().toUpperCase();
|
|
112
|
+
const isSelect = sqlUpper.startsWith('SELECT') || sqlUpper.startsWith('PRAGMA');
|
|
113
|
+
const params = options?.replacements ?? options?.bind ?? options?.bindings;
|
|
114
|
+
try {
|
|
115
|
+
const result = await (params === undefined
|
|
116
|
+
? this.client.execute(sql)
|
|
117
|
+
: this.client.execute({ sql, args: this.toLibsqlArgs(params) }));
|
|
118
|
+
if (isSelect) {
|
|
119
|
+
const rows = result.rows.map((row) => this.rowToObject(row, result.columns));
|
|
120
|
+
return { rows, rowCount: rows.length, fields: [] };
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
rows: [],
|
|
124
|
+
rowCount: result.rowsAffected,
|
|
125
|
+
fields: [],
|
|
126
|
+
lastInsertRowid: result.lastInsertRowid !== undefined ? Number(result.lastInsertRowid) : undefined,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
throw new Error(`Query error: ${error}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* `@libsql/client` has no native server-side cursor — `execute()` always
|
|
135
|
+
* returns the full result set — so this uses the same generic
|
|
136
|
+
* LIMIT/OFFSET-paginated fallback the other non-cursor dialects use
|
|
137
|
+
* (`buildLimitOffset()` is inherited unchanged from `SQLiteDialect`,
|
|
138
|
+
* since libSQL's pagination syntax is identical to SQLite's).
|
|
139
|
+
*/
|
|
140
|
+
queryStream(sql, options) {
|
|
141
|
+
return (0, query_stream_helper_1.createPaginatedQueryStream)(this, sql, options);
|
|
142
|
+
}
|
|
143
|
+
toLibsqlArgs(params) {
|
|
144
|
+
if (Array.isArray(params)) {
|
|
145
|
+
return params;
|
|
146
|
+
}
|
|
147
|
+
return params;
|
|
148
|
+
}
|
|
149
|
+
rowToObject(row, columns) {
|
|
150
|
+
const obj = {};
|
|
151
|
+
for (let i = 0; i < columns.length; i++) {
|
|
152
|
+
obj[columns[i]] = row[i];
|
|
153
|
+
}
|
|
154
|
+
return obj;
|
|
155
|
+
}
|
|
156
|
+
async getDatabaseVersion() {
|
|
157
|
+
const result = await this.query('SELECT sqlite_version() AS version');
|
|
158
|
+
return String(result.rows[0]?.version ?? 'unknown');
|
|
159
|
+
}
|
|
160
|
+
async attachDatabase(path, alias) {
|
|
161
|
+
const aliasId = this.quoteIdentifier(alias);
|
|
162
|
+
await this.client.execute({ sql: `ATTACH DATABASE ? AS ${aliasId}`, args: [path] });
|
|
163
|
+
}
|
|
164
|
+
async detachDatabase(alias) {
|
|
165
|
+
const aliasId = this.quoteIdentifier(alias);
|
|
166
|
+
await this.client.execute(`DETACH DATABASE ${aliasId}`);
|
|
167
|
+
}
|
|
168
|
+
async startTransaction(options) {
|
|
169
|
+
if (!this.client) {
|
|
170
|
+
throw new Error('Not connected to database');
|
|
171
|
+
}
|
|
172
|
+
const transaction = new TursoTransaction(this.tursoTransactionDepth++, options, this);
|
|
173
|
+
if (this.tursoTransactionDepth === 1) {
|
|
174
|
+
await this.client.execute('BEGIN TRANSACTION');
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
await this.client.execute(`SAVEPOINT sp_${transaction.id}`);
|
|
178
|
+
}
|
|
179
|
+
return transaction;
|
|
180
|
+
}
|
|
181
|
+
async commitTransaction(transaction) {
|
|
182
|
+
if (!this.client) {
|
|
183
|
+
throw new Error('Not connected to database');
|
|
184
|
+
}
|
|
185
|
+
const tx = transaction;
|
|
186
|
+
if (this.tursoTransactionDepth === 1) {
|
|
187
|
+
await this.client.execute('COMMIT');
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
await this.client.execute(`RELEASE SAVEPOINT sp_${tx.id}`);
|
|
191
|
+
}
|
|
192
|
+
this.tursoTransactionDepth--;
|
|
193
|
+
}
|
|
194
|
+
async rollbackTransaction(transaction) {
|
|
195
|
+
if (!this.client) {
|
|
196
|
+
throw new Error('Not connected to database');
|
|
197
|
+
}
|
|
198
|
+
const tx = transaction;
|
|
199
|
+
if (this.tursoTransactionDepth === 1) {
|
|
200
|
+
await this.client.execute('ROLLBACK');
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
await this.client.execute(`ROLLBACK TO SAVEPOINT sp_${tx.id}`);
|
|
204
|
+
}
|
|
205
|
+
this.tursoTransactionDepth--;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Pull the local embedded replica up to date with its `syncUrl` remote.
|
|
209
|
+
* No-op (well, throws) if this client wasn't configured with a `syncUrl`.
|
|
210
|
+
*/
|
|
211
|
+
async sync() {
|
|
212
|
+
if (!this.client) {
|
|
213
|
+
throw new Error('Not connected to database');
|
|
214
|
+
}
|
|
215
|
+
if (!this.tursoConfig.syncUrl) {
|
|
216
|
+
throw new Error('sync() requires a syncUrl to have been configured on connect');
|
|
217
|
+
}
|
|
218
|
+
await this.client.sync();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.TursoDialect = TursoDialect;
|
|
222
|
+
/**
|
|
223
|
+
* Create a new Turso/libSQL dialect instance.
|
|
224
|
+
*/
|
|
225
|
+
function createTursoDialect(options) {
|
|
226
|
+
return new TursoDialect(options || {});
|
|
227
|
+
}
|