Comparing version
@@ -337,3 +337,3 @@ import { TypeORMError } from "../../error"; | ||
value = value | ||
.substr(1, value.length - 2) | ||
.slice(1, -1) | ||
.split(",") | ||
@@ -344,6 +344,4 @@ .map((val) => { | ||
val = val.slice(1, -1); | ||
// replace double escaped backslash to single escaped e.g. \\\\ -> \\ | ||
val = val.replace(/(\\\\)/g, "\\"); | ||
// replace escaped double quotes to non-escaped e.g. \"asd\" -> "asd" | ||
return val.replace(/(\\")/g, '"'); | ||
// replace escaped backslash and double quotes | ||
return val.replace(/\\(\\|")/g, "$1"); | ||
}); | ||
@@ -350,0 +348,0 @@ // convert to number if that exists in possible enum options |
@@ -13,3 +13,3 @@ import { MissingDriverError } from "../error/MissingDriverError"; | ||
import { PostgresDriver } from "./postgres/PostgresDriver"; | ||
import { ExpoDriver } from "./expo/ExpoDriver"; | ||
import { ExpoDriverFactory } from "./expo/ExpoDriverFactory"; | ||
import { AuroraMysqlDriver } from "./aurora-mysql/AuroraMysqlDriver"; | ||
@@ -60,3 +60,3 @@ import { AuroraPostgresDriver } from "./aurora-postgres/AuroraPostgresDriver"; | ||
case "expo": | ||
return new ExpoDriver(connection); | ||
return new ExpoDriverFactory(connection).create(); | ||
case "aurora-mysql": | ||
@@ -63,0 +63,0 @@ return new AuroraMysqlDriver(connection); |
@@ -5,18 +5,8 @@ import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver"; | ||
import { DataSource } from "../../data-source/DataSource"; | ||
import { ReplicationMode } from "../types/ReplicationMode"; | ||
export declare class ExpoDriver extends AbstractSqliteDriver { | ||
options: ExpoConnectionOptions; | ||
constructor(connection: DataSource); | ||
/** | ||
* Closes connection with database. | ||
*/ | ||
disconnect(): Promise<void>; | ||
/** | ||
* Creates a query runner used to execute database queries. | ||
*/ | ||
createQueryRunner(mode: ReplicationMode): QueryRunner; | ||
/** | ||
* Creates connection with the database. | ||
*/ | ||
protected createDatabaseConnection(): Promise<void>; | ||
createQueryRunner(): QueryRunner; | ||
protected createDatabaseConnection(): Promise<any>; | ||
} |
import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver"; | ||
import { ExpoQueryRunner } from "./ExpoQueryRunner"; | ||
export class ExpoDriver extends AbstractSqliteDriver { | ||
// ------------------------------------------------------------------------- | ||
// Constructor | ||
// ------------------------------------------------------------------------- | ||
constructor(connection) { | ||
super(connection); | ||
this.database = this.options.database; | ||
// load sqlite package | ||
this.sqlite = this.options.driver; | ||
} | ||
// ------------------------------------------------------------------------- | ||
// Public Methods | ||
// ------------------------------------------------------------------------- | ||
/** | ||
* Closes connection with database. | ||
*/ | ||
async disconnect() { | ||
return new Promise((ok, fail) => { | ||
try { | ||
this.queryRunner = undefined; | ||
this.databaseConnection._db.close(); | ||
this.databaseConnection = undefined; | ||
ok(); | ||
} | ||
catch (error) { | ||
fail(error); | ||
} | ||
}); | ||
this.queryRunner = undefined; | ||
await this.databaseConnection.closeAsync(); | ||
this.databaseConnection = undefined; | ||
} | ||
/** | ||
* Creates a query runner used to execute database queries. | ||
*/ | ||
createQueryRunner(mode) { | ||
createQueryRunner() { | ||
if (!this.queryRunner) | ||
@@ -40,30 +18,6 @@ this.queryRunner = new ExpoQueryRunner(this); | ||
} | ||
// ------------------------------------------------------------------------- | ||
// Protected Methods | ||
// ------------------------------------------------------------------------- | ||
/** | ||
* Creates connection with the database. | ||
*/ | ||
createDatabaseConnection() { | ||
return new Promise((ok, fail) => { | ||
try { | ||
const databaseConnection = this.sqlite.openDatabase(this.options.database); | ||
/* | ||
// we need to enable foreign keys in sqlite to make sure all foreign key related features | ||
// working properly. this also makes onDelete work with sqlite. | ||
*/ | ||
databaseConnection.transaction((tsx) => { | ||
tsx.executeSql(`PRAGMA foreign_keys = ON`, [], (t, result) => { | ||
ok(databaseConnection); | ||
}, (t, err) => { | ||
fail({ transaction: t, error: err }); | ||
}); | ||
}, (err) => { | ||
fail(err); | ||
}); | ||
} | ||
catch (error) { | ||
fail(error); | ||
} | ||
}); | ||
async createDatabaseConnection() { | ||
this.databaseConnection = await this.sqlite.openDatabaseAsync(this.options.database); | ||
await this.databaseConnection.runAsync("PRAGMA foreign_keys = ON"); | ||
return this.databaseConnection; | ||
} | ||
@@ -70,0 +24,0 @@ } |
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"; | ||
import { ExpoDriver } from "./ExpoDriver"; | ||
/** | ||
* Runs queries on a single sqlite database connection. | ||
*/ | ||
export declare class ExpoQueryRunner extends AbstractSqliteQueryRunner { | ||
/** | ||
* Database driver used by connection. | ||
*/ | ||
driver: ExpoDriver; | ||
/** | ||
* Database transaction object | ||
*/ | ||
private transaction?; | ||
constructor(driver: ExpoDriver); | ||
/** | ||
* Starts transaction. Within Expo, all database operations happen in a | ||
* transaction context, so issuing a `BEGIN TRANSACTION` command is | ||
* redundant and will result in the following error: | ||
* | ||
* `Error: Error code 1: cannot start a transaction within a transaction` | ||
* | ||
* Instead, we keep track of a `Transaction` object in `this.transaction` | ||
* and continue using the same object until we wish to commit the | ||
* transaction. | ||
*/ | ||
startTransaction(): Promise<void>; | ||
/** | ||
* Commits transaction. | ||
* Error will be thrown if transaction was not started. | ||
* Since Expo will automatically commit the transaction once all the | ||
* callbacks of the transaction object have been completed, "committing" a | ||
* transaction in this driver's context means that we delete the transaction | ||
* object and set the stage for the next transaction. | ||
*/ | ||
commitTransaction(): Promise<void>; | ||
/** | ||
* Rollbacks transaction. | ||
* Error will be thrown if transaction was not started. | ||
* This method's functionality is identical to `commitTransaction()` because | ||
* the transaction lifecycle is handled within the Expo transaction object. | ||
* Issuing separate statements for `COMMIT` or `ROLLBACK` aren't necessary. | ||
*/ | ||
rollbackTransaction(): Promise<void>; | ||
/** | ||
* Called before migrations are run. | ||
*/ | ||
beforeMigration(): Promise<void>; | ||
/** | ||
* Called after migrations are run. | ||
*/ | ||
afterMigration(): Promise<void>; | ||
/** | ||
* Executes a given SQL query. | ||
*/ | ||
query(query: string, parameters?: any[], useStructuredResult?: boolean): Promise<any>; | ||
} |
import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"; | ||
import { QueryFailedError } from "../../error/QueryFailedError"; | ||
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"; | ||
import { TransactionNotStartedError } from "../../error/TransactionNotStartedError"; | ||
import { Broadcaster } from "../../subscriber/Broadcaster"; | ||
import { QueryResult } from "../../query-runner/QueryResult"; | ||
import { BroadcasterResult } from "../../subscriber/BroadcasterResult"; | ||
/** | ||
* Runs queries on a single sqlite database connection. | ||
*/ | ||
export class ExpoQueryRunner extends AbstractSqliteQueryRunner { | ||
// ------------------------------------------------------------------------- | ||
// Constructor | ||
// ------------------------------------------------------------------------- | ||
constructor(driver) { | ||
@@ -21,143 +14,45 @@ super(); | ||
} | ||
/** | ||
* Starts transaction. Within Expo, all database operations happen in a | ||
* transaction context, so issuing a `BEGIN TRANSACTION` command is | ||
* redundant and will result in the following error: | ||
* | ||
* `Error: Error code 1: cannot start a transaction within a transaction` | ||
* | ||
* Instead, we keep track of a `Transaction` object in `this.transaction` | ||
* and continue using the same object until we wish to commit the | ||
* transaction. | ||
*/ | ||
async startTransaction() { | ||
this.isTransactionActive = true; | ||
try { | ||
await this.broadcaster.broadcast("BeforeTransactionStart"); | ||
} | ||
catch (err) { | ||
this.isTransactionActive = false; | ||
throw err; | ||
} | ||
this.transactionDepth += 1; | ||
await this.broadcaster.broadcast("AfterTransactionStart"); | ||
} | ||
/** | ||
* Commits transaction. | ||
* Error will be thrown if transaction was not started. | ||
* Since Expo will automatically commit the transaction once all the | ||
* callbacks of the transaction object have been completed, "committing" a | ||
* transaction in this driver's context means that we delete the transaction | ||
* object and set the stage for the next transaction. | ||
*/ | ||
async commitTransaction() { | ||
if (!this.isTransactionActive && | ||
typeof this.transaction === "undefined") | ||
throw new TransactionNotStartedError(); | ||
await this.broadcaster.broadcast("BeforeTransactionCommit"); | ||
this.transaction = undefined; | ||
this.isTransactionActive = false; | ||
this.transactionDepth -= 1; | ||
await this.broadcaster.broadcast("AfterTransactionCommit"); | ||
} | ||
/** | ||
* Rollbacks transaction. | ||
* Error will be thrown if transaction was not started. | ||
* This method's functionality is identical to `commitTransaction()` because | ||
* the transaction lifecycle is handled within the Expo transaction object. | ||
* Issuing separate statements for `COMMIT` or `ROLLBACK` aren't necessary. | ||
*/ | ||
async rollbackTransaction() { | ||
if (!this.isTransactionActive && | ||
typeof this.transaction === "undefined") | ||
throw new TransactionNotStartedError(); | ||
await this.broadcaster.broadcast("BeforeTransactionRollback"); | ||
this.transaction = undefined; | ||
this.isTransactionActive = false; | ||
this.transactionDepth -= 1; | ||
await this.broadcaster.broadcast("AfterTransactionRollback"); | ||
} | ||
/** | ||
* Called before migrations are run. | ||
*/ | ||
async beforeMigration() { | ||
const databaseConnection = await this.connect(); | ||
return new Promise((ok, fail) => { | ||
databaseConnection.exec([{ sql: "PRAGMA foreign_keys = OFF", args: [] }], false, (err) => (err ? fail(err) : ok())); | ||
}); | ||
await this.query("PRAGMA foreign_keys = OFF"); | ||
} | ||
/** | ||
* Called after migrations are run. | ||
*/ | ||
async afterMigration() { | ||
const databaseConnection = await this.connect(); | ||
return new Promise((ok, fail) => { | ||
databaseConnection.exec([{ sql: "PRAGMA foreign_keys = ON", args: [] }], false, (err) => (err ? fail(err) : ok())); | ||
}); | ||
await this.query("PRAGMA foreign_keys = ON"); | ||
} | ||
/** | ||
* Executes a given SQL query. | ||
*/ | ||
async query(query, parameters, useStructuredResult = false) { | ||
if (this.isReleased) | ||
throw new QueryRunnerAlreadyReleasedError(); | ||
return new Promise(async (ok, fail) => { | ||
const databaseConnection = await this.connect(); | ||
const broadcasterResult = new BroadcasterResult(); | ||
this.driver.connection.logger.logQuery(query, parameters, this); | ||
this.broadcaster.broadcastBeforeQueryEvent(broadcasterResult, query, parameters); | ||
const queryStartTime = +new Date(); | ||
// All Expo SQL queries are executed in a transaction context | ||
databaseConnection.transaction(async (transaction) => { | ||
if (typeof this.transaction === "undefined") { | ||
await this.startTransaction(); | ||
this.transaction = transaction; | ||
} | ||
this.transaction.executeSql(query, parameters, async (t, raw) => { | ||
// log slow queries if maxQueryExecution time is set | ||
const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime; | ||
const queryEndTime = +new Date(); | ||
const queryExecutionTime = queryEndTime - queryStartTime; | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, true, queryExecutionTime, raw, undefined); | ||
await broadcasterResult.wait(); | ||
if (maxQueryExecutionTime && | ||
queryExecutionTime > maxQueryExecutionTime) { | ||
this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this); | ||
} | ||
const result = new QueryResult(); | ||
if (raw?.hasOwnProperty("rowsAffected")) { | ||
result.affected = raw.rowsAffected; | ||
} | ||
if (raw?.hasOwnProperty("rows")) { | ||
const resultSet = []; | ||
for (let i = 0; i < raw.rows.length; i++) { | ||
resultSet.push(raw.rows.item(i)); | ||
} | ||
result.raw = resultSet; | ||
result.records = resultSet; | ||
} | ||
// return id of inserted row, if query was insert statement. | ||
if (query.startsWith("INSERT INTO")) { | ||
result.raw = raw.insertId; | ||
} | ||
if (useStructuredResult) { | ||
ok(result); | ||
} | ||
else { | ||
ok(result.raw); | ||
} | ||
}, async (t, err) => { | ||
this.driver.connection.logger.logQueryError(err, query, parameters, this); | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, false, undefined, undefined, err); | ||
await broadcasterResult.wait(); | ||
fail(new QueryFailedError(query, parameters, err)); | ||
}); | ||
}, async (err) => { | ||
await this.rollbackTransaction(); | ||
fail(err); | ||
}, () => { | ||
this.isTransactionActive = false; | ||
this.transaction = undefined; | ||
}); | ||
}); | ||
const databaseConnection = await this.connect(); | ||
const broadcasterResult = new BroadcasterResult(); | ||
this.driver.connection.logger.logQuery(query, parameters, this); | ||
this.broadcaster.broadcastBeforeQueryEvent(broadcasterResult, query, parameters); | ||
const queryStartTime = +new Date(); | ||
const statement = await databaseConnection.prepareAsync(query); | ||
try { | ||
const rawResult = await statement.executeAsync(parameters); | ||
const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime; | ||
const queryEndTime = +new Date(); | ||
const queryExecutionTime = queryEndTime - queryStartTime; | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, true, queryExecutionTime, rawResult, undefined); | ||
await broadcasterResult.wait(); | ||
if (maxQueryExecutionTime && | ||
queryExecutionTime > maxQueryExecutionTime) { | ||
this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this); | ||
} | ||
const result = new QueryResult(); | ||
result.affected = rawResult.changes; | ||
result.records = await rawResult.getAllAsync(); | ||
result.raw = query.startsWith("INSERT INTO") | ||
? rawResult.lastInsertRowId | ||
: result.records; | ||
return useStructuredResult ? result : result.raw; | ||
} | ||
catch (err) { | ||
this.driver.connection.logger.logQueryError(err, query, parameters, this); | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, false, 0, undefined, err); | ||
await broadcasterResult.wait(); | ||
throw new QueryFailedError(query, parameters, err); | ||
} | ||
finally { | ||
await statement.finalizeAsync(); | ||
} | ||
} | ||
@@ -164,0 +59,0 @@ } |
@@ -5,3 +5,2 @@ import { BaseDataSourceOptions } from "../../data-source/BaseDataSourceOptions"; | ||
* MongoDB specific connection options. | ||
* Synced with http://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html | ||
*/ | ||
@@ -42,6 +41,2 @@ export interface MongoConnectionOptions extends BaseDataSourceOptions { | ||
/** | ||
* Specifies whether to force dispatch all operations to the specified host. Default: false | ||
*/ | ||
readonly directConnection?: boolean; | ||
/** | ||
* The driver object | ||
@@ -52,234 +47,208 @@ * This defaults to require("mongodb") | ||
/** | ||
* Use ssl connection (needs to have a mongod server with ssl support). Default: false | ||
* MongoClientOptions | ||
* Synced with https://mongodb.github.io/node-mongodb-native/5.9/interfaces/MongoClientOptions.html | ||
*/ | ||
readonly ssl?: boolean; | ||
/** | ||
* Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher). | ||
* Default: true | ||
* The name of the application that created this MongoClient instance. | ||
* MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. | ||
* It is also recorded in the slow query log and profile collections | ||
*/ | ||
readonly sslValidate?: boolean; | ||
readonly appName?: string; | ||
/** | ||
* Array of valid certificates either as Buffers or Strings | ||
* (needs to have a mongod server with ssl support, 2.4 or higher). | ||
* Specify the authentication mechanism that MongoDB will use to authenticate the connection. | ||
*/ | ||
readonly sslCA?: string | Buffer; | ||
readonly authMechanism?: string; | ||
/** | ||
* String or buffer containing the certificate we wish to present | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Specify the database name associated with the user’s credentials. | ||
*/ | ||
readonly sslCert?: string | Buffer; | ||
readonly authSource?: string; | ||
/** | ||
* String or buffer containing the certificate private key we wish to present | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Optionally enable in-use auto encryption | ||
*/ | ||
readonly sslKey?: string; | ||
readonly autoEncryption?: any; | ||
/** | ||
* String or buffer containing the certificate password | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Verifies the certificate `cert` is issued to `hostname`. | ||
*/ | ||
readonly sslPass?: string | Buffer; | ||
readonly checkServerIdentity?: Function; | ||
/** | ||
* SSL Certificate revocation list binary buffer | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* An array or comma-delimited string of compressors to enable network | ||
* compression for communication between this client and a mongod/mongos instance. | ||
*/ | ||
readonly sslCRL?: string | Buffer; | ||
readonly compressors?: string | string[]; | ||
/** | ||
* Reconnect on error. Default: true | ||
* The time in milliseconds to attempt a connection before timing out. | ||
*/ | ||
readonly autoReconnect?: boolean; | ||
readonly connectTimeoutMS?: number; | ||
/** | ||
* TCP Socket NoDelay option. Default: true | ||
* Allow a driver to force a Single topology type with a connection string containing one host | ||
*/ | ||
readonly noDelay?: boolean; | ||
readonly directConnection?: boolean; | ||
/** | ||
* The number of milliseconds to wait before initiating keepAlive on the TCP socket. Default: 30000 | ||
* IP family | ||
*/ | ||
readonly keepAlive?: number; | ||
/** | ||
* TCP Connection timeout setting. Default: 30000 | ||
*/ | ||
readonly connectTimeoutMS?: number; | ||
/** | ||
* Version of IP stack. Can be 4, 6. | ||
* If undefined, will attempt to connect with IPv6, and will fall back to IPv4 on failure | ||
*/ | ||
readonly family?: number; | ||
/** | ||
* TCP Socket timeout setting. Default: 360000 | ||
* Force server to assign `_id` values instead of driver | ||
*/ | ||
readonly socketTimeoutMS?: number; | ||
readonly forceServerObjectId?: boolean; | ||
/** | ||
* Server attempt to reconnect #times. Default 30 | ||
* serialize will not emit undefined fields | ||
* note that the driver sets this to `false` | ||
*/ | ||
readonly reconnectTries?: number; | ||
readonly ignoreUndefined?: boolean; | ||
/** | ||
* Server will wait #milliseconds between retries. Default 1000 | ||
* @deprecated TCP Connection keep alive enabled. Will not be able to turn off in the future. | ||
*/ | ||
readonly reconnectInterval?: number; | ||
readonly keepAlive?: boolean; | ||
/** | ||
* Control if high availability monitoring runs for Replicaset or Mongos proxies. Default true | ||
* @deprecated The number of milliseconds to wait before initiating keepAlive on the TCP socket. | ||
* Will not be configurable in the future. | ||
*/ | ||
readonly ha?: boolean; | ||
readonly keepAliveInitialDelay?: number; | ||
/** | ||
* The High availability period for replicaset inquiry. Default: 10000 | ||
* The size (in milliseconds) of the latency window for selecting among multiple suitable MongoDB instances. | ||
*/ | ||
readonly haInterval?: number; | ||
readonly localThresholdMS?: number; | ||
/** | ||
* The name of the replicaset to connect to | ||
* Specifies, in seconds, how stale a secondary can be before the client stops using it for read operations. | ||
*/ | ||
readonly replicaSet?: string; | ||
readonly maxStalenessSeconds?: number; | ||
/** | ||
* Sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms). | ||
* Default: 15 | ||
* The minimum number of connections in the connection pool. | ||
*/ | ||
readonly acceptableLatencyMS?: number; | ||
readonly minPoolSize?: number; | ||
/** | ||
* Sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms). | ||
* Default: 15 | ||
* Enable command monitoring for this client | ||
*/ | ||
readonly secondaryAcceptableLatencyMS?: number; | ||
readonly monitorCommands?: boolean; | ||
/** | ||
* Sets if the driver should connect even if no primary is available. Default: false | ||
* TCP Connection no delay | ||
*/ | ||
readonly connectWithNoPrimary?: boolean; | ||
readonly noDelay?: boolean; | ||
/** | ||
* If the database authentication is dependent on another databaseName. | ||
* A primary key factory function for generation of custom `_id` keys | ||
*/ | ||
readonly authSource?: string; | ||
readonly pkFactory?: any; | ||
/** | ||
* The write concern. | ||
* when deserializing a Binary will return it as a node.js Buffer instance. | ||
*/ | ||
readonly w?: string | number; | ||
readonly promoteBuffers?: boolean; | ||
/** | ||
* The write concern timeout value. | ||
* when deserializing a Long will fit it into a Number if it's smaller than 53 bits. | ||
*/ | ||
readonly wtimeout?: number; | ||
/** | ||
* Specify a journal write concern. Default: false | ||
*/ | ||
readonly j?: boolean; | ||
/** | ||
* Force server to assign _id values instead of driver. Default: false | ||
*/ | ||
readonly forceServerObjectId?: boolean; | ||
/** | ||
* Serialize functions on any object. Default: false | ||
*/ | ||
readonly serializeFunctions?: boolean; | ||
/** | ||
* Specify if the BSON serializer should ignore undefined fields. Default: false | ||
*/ | ||
readonly ignoreUndefined?: boolean; | ||
/** | ||
* Return document results as raw BSON buffers. Default: false | ||
*/ | ||
readonly raw?: boolean; | ||
/** | ||
* Promotes Long values to number if they fit inside the 53 bits resolution. Default: true | ||
*/ | ||
readonly promoteLongs?: boolean; | ||
/** | ||
* Promotes Binary BSON values to native Node Buffers. Default: false | ||
* when deserializing will promote BSON values to their Node.js closest equivalent types. | ||
*/ | ||
readonly promoteBuffers?: boolean; | ||
/** | ||
* Promotes BSON values to native types where possible, set to false to only receive wrapper types. Default: true | ||
*/ | ||
readonly promoteValues?: boolean; | ||
/** | ||
* Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. Default: false | ||
* Enabling the raw option will return a Node.js Buffer which is allocated using allocUnsafe API | ||
*/ | ||
readonly domainsEnabled?: boolean; | ||
readonly raw?: boolean; | ||
/** | ||
* Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, | ||
* default is -1 which is unlimited. | ||
* Specify a read concern for the collection (only MongoDB 3.2 or higher supported) | ||
*/ | ||
readonly bufferMaxEntries?: number; | ||
readonly readConcern?: any; | ||
/** | ||
* The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, | ||
* ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). | ||
* Specifies the read preferences for this connection | ||
*/ | ||
readonly readPreference?: ReadPreference | string; | ||
/** | ||
* A primary key factory object for generation of custom _id keys. | ||
* Specifies the tags document as a comma-separated list of colon-separated key-value pairs. | ||
*/ | ||
readonly pkFactory?: any; | ||
readonly readPreferenceTags?: any[]; | ||
/** | ||
* A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible. | ||
* Specifies the name of the replica set, if the mongod is a member of a replica set. | ||
*/ | ||
readonly promiseLibrary?: any; | ||
readonly replicaSet?: string; | ||
/** | ||
* Specify a read concern for the collection. (only MongoDB 3.2 or higher supported). | ||
* Enable retryable writes. | ||
*/ | ||
readonly readConcern?: any; | ||
readonly retryWrites?: boolean; | ||
/** | ||
* Specify a maxStalenessSeconds value for secondary reads, minimum is 90 seconds | ||
* serialize the javascript functions | ||
*/ | ||
readonly maxStalenessSeconds?: number; | ||
readonly serializeFunctions?: boolean; | ||
/** | ||
* Specify the log level used by the driver logger (error/warn/info/debug). | ||
* The time in milliseconds to attempt a send or receive on a socket before the attempt times out. | ||
*/ | ||
readonly loggerLevel?: "error" | "warn" | "info" | "debug"; | ||
readonly socketTimeoutMS?: number; | ||
/** | ||
* Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function | ||
* Default: true | ||
* @deprecated A boolean to enable or disables TLS/SSL for the connection. | ||
* (The ssl option is equivalent to the tls option.) | ||
*/ | ||
readonly checkServerIdentity?: boolean | Function; | ||
readonly ssl?: boolean; | ||
/** | ||
* Validate MongoClient passed in options for correctness. Default: false | ||
* @deprecated SSL Root Certificate file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCAFile instead. | ||
*/ | ||
readonly validateOptions?: boolean | any; | ||
readonly sslCA?: string; | ||
/** | ||
* The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections | ||
* @deprecated SSL Certificate revocation list file path. | ||
* | ||
* Will be removed in the next major version. | ||
*/ | ||
readonly appname?: string; | ||
readonly sslCRL?: string; | ||
/** | ||
* Sets the authentication mechanism that MongoDB will use to authenticate the connection | ||
* @deprecated SSL Certificate file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFile instead. | ||
*/ | ||
readonly authMechanism?: string; | ||
readonly sslCert?: string; | ||
/** | ||
* Type of compression to use: snappy or zlib | ||
* @deprecated SSL Key file file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFile instead. | ||
*/ | ||
readonly compression?: any; | ||
readonly sslKey?: string; | ||
/** | ||
* Specify a file sync write concern. Default: false | ||
* @deprecated SSL Certificate pass phrase. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFilePassword instead. | ||
*/ | ||
readonly fsync?: boolean; | ||
readonly sslPass?: string; | ||
/** | ||
* Read preference tags | ||
* @deprecated Validate mongod server certificate against Certificate Authority | ||
* | ||
* Will be removed in the next major version. Please use tlsAllowInvalidCertificates instead. | ||
*/ | ||
readonly readPreferenceTags?: any[]; | ||
readonly sslValidate?: boolean; | ||
/** | ||
* The number of retries for a tailable cursor. Default: 5 | ||
* Enables or disables TLS/SSL for the connection. | ||
*/ | ||
readonly numberOfRetries?: number; | ||
readonly tls?: boolean; | ||
/** | ||
* Enable auto reconnecting for single server instances. Default: true | ||
* Bypasses validation of the certificates presented by the mongod/mongos instance | ||
*/ | ||
readonly auto_reconnect?: boolean; | ||
readonly tlsAllowInvalidCertificates?: boolean; | ||
/** | ||
* Enable command monitoring for this client. Default: false | ||
* Specifies the location of a local .pem file that contains the root certificate chain from the Certificate Authority. | ||
*/ | ||
readonly monitorCommands?: boolean; | ||
readonly tlsCAFile?: string; | ||
/** | ||
* If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections | ||
* Specifies the location of a local .pem file that contains the client's TLS/SSL certificate and key. | ||
*/ | ||
readonly minSize?: number; | ||
readonly tlsCertificateKeyFile?: string; | ||
/** | ||
* Determines whether or not to use the new url parser. Default: false | ||
* Specifies the password to de-crypt the tlsCertificateKeyFile. | ||
*/ | ||
readonly useNewUrlParser?: boolean; | ||
readonly tlsCertificateKeyFilePassword?: string; | ||
/** | ||
* Determines whether or not to use the new Server Discovery and Monitoring engine. Default: false | ||
* https://github.com/mongodb/node-mongodb-native/releases/tag/v3.2.1 | ||
* @deprecated The write concern w value | ||
* | ||
* Please use the `writeConcern` option instead | ||
*/ | ||
readonly useUnifiedTopology?: boolean; | ||
readonly w?: string | number; | ||
/** | ||
* Automatic Client-Side Field Level Encryption configuration. | ||
* A MongoDB WriteConcern, which describes the level of acknowledgement | ||
* requested from MongoDB for write operations. | ||
*/ | ||
readonly autoEncryption?: any; | ||
readonly writeConcern?: any; | ||
/** | ||
* Enables or disables the ability to retry writes upon encountering transient network errors. | ||
* @deprecated The write concern timeout | ||
* | ||
* Please use the `writeConcern` option instead | ||
*/ | ||
readonly retryWrites?: boolean; | ||
readonly wtimeoutMS?: number; | ||
} |
@@ -92,9 +92,8 @@ import { Driver } from "../Driver"; | ||
maxAliasLength?: number; | ||
cteCapabilities: CteCapabilities; | ||
/** | ||
* Valid mongo connection options | ||
* NOTE: Keep sync with MongoConnectionOptions | ||
* Sync with http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html | ||
* NOTE: Keep in sync with MongoConnectionOptions | ||
*/ | ||
protected validOptionNames: string[]; | ||
cteCapabilities: CteCapabilities; | ||
constructor(connection: DataSource); | ||
@@ -101,0 +100,0 @@ /** |
@@ -80,2 +80,5 @@ import { ConnectionIsNotSetError } from "../../error/ConnectionIsNotSetError"; | ||
}; | ||
this.cteCapabilities = { | ||
enabled: false, | ||
}; | ||
// ------------------------------------------------------------------------- | ||
@@ -86,73 +89,59 @@ // Protected Properties | ||
* Valid mongo connection options | ||
* NOTE: Keep sync with MongoConnectionOptions | ||
* Sync with http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html | ||
* NOTE: Keep in sync with MongoConnectionOptions | ||
*/ | ||
this.validOptionNames = [ | ||
"poolSize", | ||
"appName", | ||
"authMechanism", | ||
"authSource", | ||
"autoEncryption", | ||
"checkServerIdentity", | ||
"compressors", | ||
"connectTimeoutMS", | ||
"directConnection", | ||
"family", | ||
"forceServerObjectId", | ||
"ignoreUndefined", | ||
"keepAlive", | ||
"keepAliveInitialDelay", | ||
"localThresholdMS", | ||
"maxStalenessSeconds", | ||
"minPoolSize", | ||
"monitorCommands", | ||
"noDelay", | ||
"pkFactory", | ||
"promoteBuffers", | ||
"promoteLongs", | ||
"promoteValues", | ||
"raw", | ||
"readConcern", | ||
"readPreference", | ||
"readPreferenceTags", | ||
"replicaSet", | ||
"retryWrites", | ||
"serializeFunctions", | ||
"socketTimeoutMS", | ||
"ssl", | ||
"sslValidate", | ||
"sslCA", | ||
"sslCRL", | ||
"sslCert", | ||
"sslKey", | ||
"sslPass", | ||
"sslCRL", | ||
"autoReconnect", | ||
"noDelay", | ||
"keepAlive", | ||
"keepAliveInitialDelay", | ||
"connectTimeoutMS", | ||
"family", | ||
"socketTimeoutMS", | ||
"reconnectTries", | ||
"reconnectInterval", | ||
"ha", | ||
"haInterval", | ||
"replicaSet", | ||
"secondaryAcceptableLatencyMS", | ||
"acceptableLatencyMS", | ||
"connectWithNoPrimary", | ||
"authSource", | ||
"sslValidate", | ||
"tls", | ||
"tlsAllowInvalidCertificates", | ||
"tlsCAFile", | ||
"tlsCertificateKeyFile", | ||
"tlsCertificateKeyFilePassword", | ||
"w", | ||
"wtimeout", | ||
"j", | ||
"writeConcern", | ||
"forceServerObjectId", | ||
"serializeFunctions", | ||
"ignoreUndefined", | ||
"raw", | ||
"bufferMaxEntries", | ||
"readPreference", | ||
"pkFactory", | ||
"promiseLibrary", | ||
"readConcern", | ||
"maxStalenessSeconds", | ||
"loggerLevel", | ||
// Do not overwrite BaseDataSourceOptions.logger | ||
// "logger", | ||
"promoteValues", | ||
"promoteBuffers", | ||
"promoteLongs", | ||
"domainsEnabled", | ||
"checkServerIdentity", | ||
"validateOptions", | ||
"wtimeoutMS", | ||
// Undocumented deprecated options | ||
// todo: remove next major version | ||
"appname", | ||
// omit auth - we are building url from username and password | ||
// "auth" | ||
"authMechanism", | ||
"compression", | ||
"fsync", | ||
"readPreferenceTags", | ||
"numberOfRetries", | ||
"auto_reconnect", | ||
"minSize", | ||
"monitorCommands", | ||
"j", | ||
"useNewUrlParser", | ||
"useUnifiedTopology", | ||
"autoEncryption", | ||
"retryWrites", | ||
"directConnection", | ||
"wtimeout", | ||
]; | ||
this.cteCapabilities = { | ||
enabled: false, | ||
}; | ||
this.options = connection.options; | ||
@@ -385,6 +374,6 @@ // validate options to make sure everything is correct and driver will be able to establish connection | ||
options.host + portUrlPart || | ||
"127.0.0.1" + portUrlPart}/${options.database || ""}?replicaSet=${options.replicaSet}${options.tls ? "&tls=true" : ""}`; | ||
"127.0.0.1" + portUrlPart}/${options.database || ""}`; | ||
} | ||
else { | ||
connectionString = `${schemaUrlPart}://${credentialsUrlPart}${options.host || "127.0.0.1"}${portUrlPart}/${options.database || ""}${options.tls ? "?tls=true" : ""}`; | ||
connectionString = `${schemaUrlPart}://${credentialsUrlPart}${options.host || "127.0.0.1"}${portUrlPart}/${options.database || ""}`; | ||
} | ||
@@ -398,11 +387,14 @@ return connectionString; | ||
const mongoOptions = {}; | ||
for (let index = 0; index < this.validOptionNames.length; index++) { | ||
const optionName = this.validOptionNames[index]; | ||
if (options.extra && optionName in options.extra) { | ||
mongoOptions[optionName] = options.extra[optionName]; | ||
} | ||
else if (optionName in options) { | ||
for (const optionName of this.validOptionNames) { | ||
if (optionName in options) { | ||
mongoOptions[optionName] = options[optionName]; | ||
} | ||
} | ||
mongoOptions.driverInfo = { | ||
name: "TypeORM", | ||
}; | ||
if ("poolSize" in options) { | ||
mongoOptions["maxPoolSize"] = options["poolSize"]; | ||
} | ||
Object.assign(mongoOptions, options.extra); | ||
return mongoOptions; | ||
@@ -409,0 +401,0 @@ } |
@@ -558,3 +558,3 @@ import { ConnectionIsNotSetError } from "../../error/ConnectionIsNotSetError"; | ||
value = value | ||
.substr(1, value.length - 2) | ||
.slice(1, -1) | ||
.split(",") | ||
@@ -565,6 +565,4 @@ .map((val) => { | ||
val = val.slice(1, -1); | ||
// replace double escaped backslash to single escaped e.g. \\\\ -> \\ | ||
val = val.replace(/(\\\\)/g, "\\"); | ||
// replace escaped double quotes to non-escaped e.g. \"asd\" -> "asd" | ||
return val.replace(/(\\")/g, '"'); | ||
// replace escaped backslash and double quotes | ||
return val.replace(/\\(\\|")/g, "$1"); | ||
}); | ||
@@ -571,0 +569,0 @@ // convert to number if that exists in possible enum options |
@@ -47,3 +47,3 @@ import { DriverPackageNotInstalledError } from "../../error/DriverPackageNotInstalledError"; | ||
"smallint", | ||
"int", // alias for "integer" | ||
"int", // typeorm alias for "integer" | ||
"integer", | ||
@@ -53,6 +53,6 @@ "bigint", | ||
"decimal", | ||
"dec", // alias for "decimal" | ||
"dec", // typeorm alias for "decimal" | ||
"real", | ||
"double", | ||
"float", | ||
"float", // database alias for "real" / "double" | ||
"date", | ||
@@ -63,13 +63,13 @@ "time", | ||
"boolean", | ||
"char", // not officially supported | ||
"char", // not officially supported, in SAP HANA Cloud: alias for "nchar" | ||
"nchar", // not officially supported | ||
"varchar", // deprecated | ||
"varchar", // in SAP HANA Cloud: alias for "nvarchar" | ||
"nvarchar", | ||
"text", // deprecated | ||
"alphanum", // deprecated | ||
"shorttext", // deprecated | ||
"text", // removed in SAP HANA Cloud | ||
"alphanum", // removed in SAP HANA Cloud | ||
"shorttext", // removed in SAP HANA Cloud | ||
"array", | ||
"varbinary", | ||
"blob", | ||
"clob", // deprecated | ||
"clob", // in SAP HANA Cloud: alias for "nclob" | ||
"nclob", | ||
@@ -430,2 +430,12 @@ "st_geometry", | ||
} | ||
else if (column.type === "float") { | ||
const length = typeof column.length === "string" | ||
? parseInt(column.length) | ||
: column.length; | ||
// https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/4ee2f261e9c44003807d08ccc2e249ac.html | ||
if (length && length < 25) { | ||
return "real"; | ||
} | ||
return "double"; | ||
} | ||
else if (column.type === String) { | ||
@@ -453,5 +463,17 @@ return "nvarchar"; | ||
} | ||
else { | ||
return column.type || ""; | ||
if (DriverUtils.isReleaseVersionOrGreater(this, "4.0")) { | ||
// SAP HANA Cloud deprecated / removed these data types | ||
if (column.type === "varchar" || | ||
column.type === "alphanum" || | ||
column.type === "shorttext") { | ||
return "nvarchar"; | ||
} | ||
else if (column.type === "text" || column.type === "clob") { | ||
return "nclob"; | ||
} | ||
else if (column.type === "char") { | ||
return "nchar"; | ||
} | ||
} | ||
return column.type || ""; | ||
} | ||
@@ -575,20 +597,7 @@ /** | ||
const tableColumn = tableColumns.find((c) => c.name === columnMetadata.databaseName); | ||
if (!tableColumn) | ||
return false; // we don't need new columns, we only need exist and changed | ||
// console.log("table:", columnMetadata.entityMetadata.tableName); | ||
// console.log("name:", tableColumn.name, columnMetadata.databaseName); | ||
// console.log("type:", tableColumn.type, _this.normalizeType(columnMetadata)); | ||
// console.log("length:", tableColumn.length, _this.getColumnLength(columnMetadata)); | ||
// console.log("width:", tableColumn.width, columnMetadata.width); | ||
// console.log("precision:", tableColumn.precision, columnMetadata.precision); | ||
// console.log("scale:", tableColumn.scale, columnMetadata.scale); | ||
// console.log("default:", tableColumn.default, columnMetadata.default); | ||
// console.log("isPrimary:", tableColumn.isPrimary, columnMetadata.isPrimary); | ||
// console.log("isNullable:", tableColumn.isNullable, columnMetadata.isNullable); | ||
// console.log("isUnique:", tableColumn.isUnique, _this.normalizeIsUnique(columnMetadata)); | ||
// console.log("isGenerated:", tableColumn.isGenerated, columnMetadata.isGenerated); | ||
// console.log((columnMetadata.generationStrategy !== "uuid" && tableColumn.isGenerated !== columnMetadata.isGenerated)); | ||
// console.log("=========================================="); | ||
const normalizeDefault = this.normalizeDefault(columnMetadata); | ||
const hanaNullComapatibleDefault = normalizeDefault == null ? undefined : normalizeDefault; | ||
if (!tableColumn) { | ||
// we don't need new columns, we only need exist and changed | ||
return false; | ||
} | ||
const normalizedDefault = this.normalizeDefault(columnMetadata); | ||
return (tableColumn.name !== columnMetadata.databaseName || | ||
@@ -604,3 +613,3 @@ tableColumn.type !== this.normalizeType(columnMetadata) || | ||
(!tableColumn.isGenerated && | ||
hanaNullComapatibleDefault !== tableColumn.default) || // we included check for generated here, because generated columns already can have default values | ||
normalizedDefault !== tableColumn.default) || // we included check for generated here, because generated columns already can have default values | ||
tableColumn.isPrimary !== columnMetadata.isPrimary || | ||
@@ -630,3 +639,3 @@ tableColumn.isNullable !== columnMetadata.isNullable || | ||
isFullTextColumnTypeSupported() { | ||
return true; | ||
return !DriverUtils.isReleaseVersionOrGreater(this, "4.0"); | ||
} | ||
@@ -633,0 +642,0 @@ /** |
@@ -132,2 +132,3 @@ /*! | ||
export * from "./driver/sqlserver/MssqlParameter"; | ||
export * from "./subscriber/event/QueryEvent"; | ||
export { ConnectionOptionsReader } from "./connection/ConnectionOptionsReader"; | ||
@@ -134,0 +135,0 @@ export { ConnectionOptions } from "./connection/ConnectionOptions"; |
@@ -135,2 +135,3 @@ /*! | ||
export * from "./driver/sqlserver/MssqlParameter"; | ||
export * from "./subscriber/event/QueryEvent"; | ||
// export * from "./data-source"; | ||
@@ -137,0 +138,0 @@ export { ConnectionOptionsReader } from "./connection/ConnectionOptionsReader"; |
@@ -241,3 +241,3 @@ import { Table } from "../schema-builder/table/Table"; | ||
successMigrations.push(migration); | ||
this.connection.logger.logSchemaBuild(`Migration ${migration.name} has been ${this.fake ? "(fake)" : ""} executed successfully.`); | ||
this.connection.logger.logSchemaBuild(`Migration ${migration.name} has been ${this.fake ? "(fake) " : ""}executed successfully.`); | ||
}); | ||
@@ -314,3 +314,3 @@ } | ||
await this.deleteExecutedMigration(queryRunner, migrationToRevert); | ||
this.connection.logger.logSchemaBuild(`Migration ${migrationToRevert.name} has been ${this.fake ? "(fake)" : ""} reverted successfully.`); | ||
this.connection.logger.logSchemaBuild(`Migration ${migrationToRevert.name} has been ${this.fake ? "(fake) " : ""}reverted successfully.`); | ||
// commit transaction if we started it | ||
@@ -317,0 +317,0 @@ if (transactionStartedByUs) |
@@ -351,3 +351,2 @@ import { v4 as uuidv4 } from "uuid"; | ||
query += updatePart.join(", "); | ||
query += " "; | ||
} | ||
@@ -359,3 +358,3 @@ if (Array.isArray(overwrite) && | ||
query += overwrite | ||
.map((column) => `${tableName}.${this.escape(column)} IS DISTINCT FROM EXCLUDED.${this.escape(column)}`) | ||
.map((column) => `${this.escape(this.alias)}.${this.escape(column)} IS DISTINCT FROM EXCLUDED.${this.escape(column)}`) | ||
.join(" OR "); | ||
@@ -564,3 +563,4 @@ query += ") "; | ||
else if (value === null && | ||
this.connection.driver.options.type === "spanner") { | ||
(this.connection.driver.options.type === "spanner" || | ||
this.connection.driver.options.type === "oracle")) { | ||
expression += "NULL"; | ||
@@ -567,0 +567,0 @@ // support for SQL expressions in queries |
@@ -39,3 +39,3 @@ import { EntityManager } from "../../entity-manager/EntityManager"; | ||
/** | ||
* The duration of the query execution. | ||
* The duration of the query execution, in milliseconds. | ||
*/ | ||
@@ -42,0 +42,0 @@ executionTime?: number; |
@@ -97,3 +97,3 @@ "use strict"; | ||
upSqls.push(" await queryRunner.query(`" + | ||
upQuery.query.replace(new RegExp("`", "g"), "\\`") + | ||
upQuery.query.replaceAll("`", "\\`") + | ||
"`" + | ||
@@ -105,3 +105,3 @@ MigrationGenerateCommand.queryParams(upQuery.parameters) + | ||
downSqls.push(" await queryRunner.query(`" + | ||
downQuery.query.replace(new RegExp("`", "g"), "\\`") + | ||
downQuery.query.replaceAll("`", "\\`") + | ||
"`" + | ||
@@ -108,0 +108,0 @@ MigrationGenerateCommand.queryParams(downQuery.parameters) + |
@@ -340,3 +340,3 @@ "use strict"; | ||
value = value | ||
.substr(1, value.length - 2) | ||
.slice(1, -1) | ||
.split(",") | ||
@@ -347,6 +347,4 @@ .map((val) => { | ||
val = val.slice(1, -1); | ||
// replace double escaped backslash to single escaped e.g. \\\\ -> \\ | ||
val = val.replace(/(\\\\)/g, "\\"); | ||
// replace escaped double quotes to non-escaped e.g. \"asd\" -> "asd" | ||
return val.replace(/(\\")/g, '"'); | ||
// replace escaped backslash and double quotes | ||
return val.replace(/\\(\\|")/g, "$1"); | ||
}); | ||
@@ -353,0 +351,0 @@ // convert to number if that exists in possible enum options |
@@ -16,3 +16,3 @@ "use strict"; | ||
const PostgresDriver_1 = require("./postgres/PostgresDriver"); | ||
const ExpoDriver_1 = require("./expo/ExpoDriver"); | ||
const ExpoDriverFactory_1 = require("./expo/ExpoDriverFactory"); | ||
const AuroraMysqlDriver_1 = require("./aurora-mysql/AuroraMysqlDriver"); | ||
@@ -63,3 +63,3 @@ const AuroraPostgresDriver_1 = require("./aurora-postgres/AuroraPostgresDriver"); | ||
case "expo": | ||
return new ExpoDriver_1.ExpoDriver(connection); | ||
return new ExpoDriverFactory_1.ExpoDriverFactory(connection).create(); | ||
case "aurora-mysql": | ||
@@ -66,0 +66,0 @@ return new AuroraMysqlDriver_1.AuroraMysqlDriver(connection); |
@@ -5,18 +5,8 @@ import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver"; | ||
import { DataSource } from "../../data-source/DataSource"; | ||
import { ReplicationMode } from "../types/ReplicationMode"; | ||
export declare class ExpoDriver extends AbstractSqliteDriver { | ||
options: ExpoConnectionOptions; | ||
constructor(connection: DataSource); | ||
/** | ||
* Closes connection with database. | ||
*/ | ||
disconnect(): Promise<void>; | ||
/** | ||
* Creates a query runner used to execute database queries. | ||
*/ | ||
createQueryRunner(mode: ReplicationMode): QueryRunner; | ||
/** | ||
* Creates connection with the database. | ||
*/ | ||
protected createDatabaseConnection(): Promise<void>; | ||
createQueryRunner(): QueryRunner; | ||
protected createDatabaseConnection(): Promise<any>; | ||
} |
@@ -7,34 +7,12 @@ "use strict"; | ||
class ExpoDriver extends AbstractSqliteDriver_1.AbstractSqliteDriver { | ||
// ------------------------------------------------------------------------- | ||
// Constructor | ||
// ------------------------------------------------------------------------- | ||
constructor(connection) { | ||
super(connection); | ||
this.database = this.options.database; | ||
// load sqlite package | ||
this.sqlite = this.options.driver; | ||
} | ||
// ------------------------------------------------------------------------- | ||
// Public Methods | ||
// ------------------------------------------------------------------------- | ||
/** | ||
* Closes connection with database. | ||
*/ | ||
async disconnect() { | ||
return new Promise((ok, fail) => { | ||
try { | ||
this.queryRunner = undefined; | ||
this.databaseConnection._db.close(); | ||
this.databaseConnection = undefined; | ||
ok(); | ||
} | ||
catch (error) { | ||
fail(error); | ||
} | ||
}); | ||
this.queryRunner = undefined; | ||
await this.databaseConnection.closeAsync(); | ||
this.databaseConnection = undefined; | ||
} | ||
/** | ||
* Creates a query runner used to execute database queries. | ||
*/ | ||
createQueryRunner(mode) { | ||
createQueryRunner() { | ||
if (!this.queryRunner) | ||
@@ -44,30 +22,6 @@ this.queryRunner = new ExpoQueryRunner_1.ExpoQueryRunner(this); | ||
} | ||
// ------------------------------------------------------------------------- | ||
// Protected Methods | ||
// ------------------------------------------------------------------------- | ||
/** | ||
* Creates connection with the database. | ||
*/ | ||
createDatabaseConnection() { | ||
return new Promise((ok, fail) => { | ||
try { | ||
const databaseConnection = this.sqlite.openDatabase(this.options.database); | ||
/* | ||
// we need to enable foreign keys in sqlite to make sure all foreign key related features | ||
// working properly. this also makes onDelete work with sqlite. | ||
*/ | ||
databaseConnection.transaction((tsx) => { | ||
tsx.executeSql(`PRAGMA foreign_keys = ON`, [], (t, result) => { | ||
ok(databaseConnection); | ||
}, (t, err) => { | ||
fail({ transaction: t, error: err }); | ||
}); | ||
}, (err) => { | ||
fail(err); | ||
}); | ||
} | ||
catch (error) { | ||
fail(error); | ||
} | ||
}); | ||
async createDatabaseConnection() { | ||
this.databaseConnection = await this.sqlite.openDatabaseAsync(this.options.database); | ||
await this.databaseConnection.runAsync("PRAGMA foreign_keys = ON"); | ||
return this.databaseConnection; | ||
} | ||
@@ -74,0 +28,0 @@ } |
import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"; | ||
import { ExpoDriver } from "./ExpoDriver"; | ||
/** | ||
* Runs queries on a single sqlite database connection. | ||
*/ | ||
export declare class ExpoQueryRunner extends AbstractSqliteQueryRunner { | ||
/** | ||
* Database driver used by connection. | ||
*/ | ||
driver: ExpoDriver; | ||
/** | ||
* Database transaction object | ||
*/ | ||
private transaction?; | ||
constructor(driver: ExpoDriver); | ||
/** | ||
* Starts transaction. Within Expo, all database operations happen in a | ||
* transaction context, so issuing a `BEGIN TRANSACTION` command is | ||
* redundant and will result in the following error: | ||
* | ||
* `Error: Error code 1: cannot start a transaction within a transaction` | ||
* | ||
* Instead, we keep track of a `Transaction` object in `this.transaction` | ||
* and continue using the same object until we wish to commit the | ||
* transaction. | ||
*/ | ||
startTransaction(): Promise<void>; | ||
/** | ||
* Commits transaction. | ||
* Error will be thrown if transaction was not started. | ||
* Since Expo will automatically commit the transaction once all the | ||
* callbacks of the transaction object have been completed, "committing" a | ||
* transaction in this driver's context means that we delete the transaction | ||
* object and set the stage for the next transaction. | ||
*/ | ||
commitTransaction(): Promise<void>; | ||
/** | ||
* Rollbacks transaction. | ||
* Error will be thrown if transaction was not started. | ||
* This method's functionality is identical to `commitTransaction()` because | ||
* the transaction lifecycle is handled within the Expo transaction object. | ||
* Issuing separate statements for `COMMIT` or `ROLLBACK` aren't necessary. | ||
*/ | ||
rollbackTransaction(): Promise<void>; | ||
/** | ||
* Called before migrations are run. | ||
*/ | ||
beforeMigration(): Promise<void>; | ||
/** | ||
* Called after migrations are run. | ||
*/ | ||
afterMigration(): Promise<void>; | ||
/** | ||
* Executes a given SQL query. | ||
*/ | ||
query(query: string, parameters?: any[], useStructuredResult?: boolean): Promise<any>; | ||
} |
@@ -7,13 +7,6 @@ "use strict"; | ||
const AbstractSqliteQueryRunner_1 = require("../sqlite-abstract/AbstractSqliteQueryRunner"); | ||
const TransactionNotStartedError_1 = require("../../error/TransactionNotStartedError"); | ||
const Broadcaster_1 = require("../../subscriber/Broadcaster"); | ||
const QueryResult_1 = require("../../query-runner/QueryResult"); | ||
const BroadcasterResult_1 = require("../../subscriber/BroadcasterResult"); | ||
/** | ||
* Runs queries on a single sqlite database connection. | ||
*/ | ||
class ExpoQueryRunner extends AbstractSqliteQueryRunner_1.AbstractSqliteQueryRunner { | ||
// ------------------------------------------------------------------------- | ||
// Constructor | ||
// ------------------------------------------------------------------------- | ||
constructor(driver) { | ||
@@ -25,143 +18,45 @@ super(); | ||
} | ||
/** | ||
* Starts transaction. Within Expo, all database operations happen in a | ||
* transaction context, so issuing a `BEGIN TRANSACTION` command is | ||
* redundant and will result in the following error: | ||
* | ||
* `Error: Error code 1: cannot start a transaction within a transaction` | ||
* | ||
* Instead, we keep track of a `Transaction` object in `this.transaction` | ||
* and continue using the same object until we wish to commit the | ||
* transaction. | ||
*/ | ||
async startTransaction() { | ||
this.isTransactionActive = true; | ||
try { | ||
await this.broadcaster.broadcast("BeforeTransactionStart"); | ||
} | ||
catch (err) { | ||
this.isTransactionActive = false; | ||
throw err; | ||
} | ||
this.transactionDepth += 1; | ||
await this.broadcaster.broadcast("AfterTransactionStart"); | ||
} | ||
/** | ||
* Commits transaction. | ||
* Error will be thrown if transaction was not started. | ||
* Since Expo will automatically commit the transaction once all the | ||
* callbacks of the transaction object have been completed, "committing" a | ||
* transaction in this driver's context means that we delete the transaction | ||
* object and set the stage for the next transaction. | ||
*/ | ||
async commitTransaction() { | ||
if (!this.isTransactionActive && | ||
typeof this.transaction === "undefined") | ||
throw new TransactionNotStartedError_1.TransactionNotStartedError(); | ||
await this.broadcaster.broadcast("BeforeTransactionCommit"); | ||
this.transaction = undefined; | ||
this.isTransactionActive = false; | ||
this.transactionDepth -= 1; | ||
await this.broadcaster.broadcast("AfterTransactionCommit"); | ||
} | ||
/** | ||
* Rollbacks transaction. | ||
* Error will be thrown if transaction was not started. | ||
* This method's functionality is identical to `commitTransaction()` because | ||
* the transaction lifecycle is handled within the Expo transaction object. | ||
* Issuing separate statements for `COMMIT` or `ROLLBACK` aren't necessary. | ||
*/ | ||
async rollbackTransaction() { | ||
if (!this.isTransactionActive && | ||
typeof this.transaction === "undefined") | ||
throw new TransactionNotStartedError_1.TransactionNotStartedError(); | ||
await this.broadcaster.broadcast("BeforeTransactionRollback"); | ||
this.transaction = undefined; | ||
this.isTransactionActive = false; | ||
this.transactionDepth -= 1; | ||
await this.broadcaster.broadcast("AfterTransactionRollback"); | ||
} | ||
/** | ||
* Called before migrations are run. | ||
*/ | ||
async beforeMigration() { | ||
const databaseConnection = await this.connect(); | ||
return new Promise((ok, fail) => { | ||
databaseConnection.exec([{ sql: "PRAGMA foreign_keys = OFF", args: [] }], false, (err) => (err ? fail(err) : ok())); | ||
}); | ||
await this.query("PRAGMA foreign_keys = OFF"); | ||
} | ||
/** | ||
* Called after migrations are run. | ||
*/ | ||
async afterMigration() { | ||
const databaseConnection = await this.connect(); | ||
return new Promise((ok, fail) => { | ||
databaseConnection.exec([{ sql: "PRAGMA foreign_keys = ON", args: [] }], false, (err) => (err ? fail(err) : ok())); | ||
}); | ||
await this.query("PRAGMA foreign_keys = ON"); | ||
} | ||
/** | ||
* Executes a given SQL query. | ||
*/ | ||
async query(query, parameters, useStructuredResult = false) { | ||
if (this.isReleased) | ||
throw new QueryRunnerAlreadyReleasedError_1.QueryRunnerAlreadyReleasedError(); | ||
return new Promise(async (ok, fail) => { | ||
const databaseConnection = await this.connect(); | ||
const broadcasterResult = new BroadcasterResult_1.BroadcasterResult(); | ||
this.driver.connection.logger.logQuery(query, parameters, this); | ||
this.broadcaster.broadcastBeforeQueryEvent(broadcasterResult, query, parameters); | ||
const queryStartTime = +new Date(); | ||
// All Expo SQL queries are executed in a transaction context | ||
databaseConnection.transaction(async (transaction) => { | ||
if (typeof this.transaction === "undefined") { | ||
await this.startTransaction(); | ||
this.transaction = transaction; | ||
} | ||
this.transaction.executeSql(query, parameters, async (t, raw) => { | ||
// log slow queries if maxQueryExecution time is set | ||
const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime; | ||
const queryEndTime = +new Date(); | ||
const queryExecutionTime = queryEndTime - queryStartTime; | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, true, queryExecutionTime, raw, undefined); | ||
await broadcasterResult.wait(); | ||
if (maxQueryExecutionTime && | ||
queryExecutionTime > maxQueryExecutionTime) { | ||
this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this); | ||
} | ||
const result = new QueryResult_1.QueryResult(); | ||
if (raw?.hasOwnProperty("rowsAffected")) { | ||
result.affected = raw.rowsAffected; | ||
} | ||
if (raw?.hasOwnProperty("rows")) { | ||
const resultSet = []; | ||
for (let i = 0; i < raw.rows.length; i++) { | ||
resultSet.push(raw.rows.item(i)); | ||
} | ||
result.raw = resultSet; | ||
result.records = resultSet; | ||
} | ||
// return id of inserted row, if query was insert statement. | ||
if (query.startsWith("INSERT INTO")) { | ||
result.raw = raw.insertId; | ||
} | ||
if (useStructuredResult) { | ||
ok(result); | ||
} | ||
else { | ||
ok(result.raw); | ||
} | ||
}, async (t, err) => { | ||
this.driver.connection.logger.logQueryError(err, query, parameters, this); | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, false, undefined, undefined, err); | ||
await broadcasterResult.wait(); | ||
fail(new QueryFailedError_1.QueryFailedError(query, parameters, err)); | ||
}); | ||
}, async (err) => { | ||
await this.rollbackTransaction(); | ||
fail(err); | ||
}, () => { | ||
this.isTransactionActive = false; | ||
this.transaction = undefined; | ||
}); | ||
}); | ||
const databaseConnection = await this.connect(); | ||
const broadcasterResult = new BroadcasterResult_1.BroadcasterResult(); | ||
this.driver.connection.logger.logQuery(query, parameters, this); | ||
this.broadcaster.broadcastBeforeQueryEvent(broadcasterResult, query, parameters); | ||
const queryStartTime = +new Date(); | ||
const statement = await databaseConnection.prepareAsync(query); | ||
try { | ||
const rawResult = await statement.executeAsync(parameters); | ||
const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime; | ||
const queryEndTime = +new Date(); | ||
const queryExecutionTime = queryEndTime - queryStartTime; | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, true, queryExecutionTime, rawResult, undefined); | ||
await broadcasterResult.wait(); | ||
if (maxQueryExecutionTime && | ||
queryExecutionTime > maxQueryExecutionTime) { | ||
this.driver.connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this); | ||
} | ||
const result = new QueryResult_1.QueryResult(); | ||
result.affected = rawResult.changes; | ||
result.records = await rawResult.getAllAsync(); | ||
result.raw = query.startsWith("INSERT INTO") | ||
? rawResult.lastInsertRowId | ||
: result.records; | ||
return useStructuredResult ? result : result.raw; | ||
} | ||
catch (err) { | ||
this.driver.connection.logger.logQueryError(err, query, parameters, this); | ||
this.broadcaster.broadcastAfterQueryEvent(broadcasterResult, query, parameters, false, 0, undefined, err); | ||
await broadcasterResult.wait(); | ||
throw new QueryFailedError_1.QueryFailedError(query, parameters, err); | ||
} | ||
finally { | ||
await statement.finalizeAsync(); | ||
} | ||
} | ||
@@ -168,0 +63,0 @@ } |
@@ -5,3 +5,2 @@ import { BaseDataSourceOptions } from "../../data-source/BaseDataSourceOptions"; | ||
* MongoDB specific connection options. | ||
* Synced with http://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html | ||
*/ | ||
@@ -42,6 +41,2 @@ export interface MongoConnectionOptions extends BaseDataSourceOptions { | ||
/** | ||
* Specifies whether to force dispatch all operations to the specified host. Default: false | ||
*/ | ||
readonly directConnection?: boolean; | ||
/** | ||
* The driver object | ||
@@ -52,234 +47,208 @@ * This defaults to require("mongodb") | ||
/** | ||
* Use ssl connection (needs to have a mongod server with ssl support). Default: false | ||
* MongoClientOptions | ||
* Synced with https://mongodb.github.io/node-mongodb-native/5.9/interfaces/MongoClientOptions.html | ||
*/ | ||
readonly ssl?: boolean; | ||
/** | ||
* Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher). | ||
* Default: true | ||
* The name of the application that created this MongoClient instance. | ||
* MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. | ||
* It is also recorded in the slow query log and profile collections | ||
*/ | ||
readonly sslValidate?: boolean; | ||
readonly appName?: string; | ||
/** | ||
* Array of valid certificates either as Buffers or Strings | ||
* (needs to have a mongod server with ssl support, 2.4 or higher). | ||
* Specify the authentication mechanism that MongoDB will use to authenticate the connection. | ||
*/ | ||
readonly sslCA?: string | Buffer; | ||
readonly authMechanism?: string; | ||
/** | ||
* String or buffer containing the certificate we wish to present | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Specify the database name associated with the user’s credentials. | ||
*/ | ||
readonly sslCert?: string | Buffer; | ||
readonly authSource?: string; | ||
/** | ||
* String or buffer containing the certificate private key we wish to present | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Optionally enable in-use auto encryption | ||
*/ | ||
readonly sslKey?: string; | ||
readonly autoEncryption?: any; | ||
/** | ||
* String or buffer containing the certificate password | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* Verifies the certificate `cert` is issued to `hostname`. | ||
*/ | ||
readonly sslPass?: string | Buffer; | ||
readonly checkServerIdentity?: Function; | ||
/** | ||
* SSL Certificate revocation list binary buffer | ||
* (needs to have a mongod server with ssl support, 2.4 or higher) | ||
* An array or comma-delimited string of compressors to enable network | ||
* compression for communication between this client and a mongod/mongos instance. | ||
*/ | ||
readonly sslCRL?: string | Buffer; | ||
readonly compressors?: string | string[]; | ||
/** | ||
* Reconnect on error. Default: true | ||
* The time in milliseconds to attempt a connection before timing out. | ||
*/ | ||
readonly autoReconnect?: boolean; | ||
readonly connectTimeoutMS?: number; | ||
/** | ||
* TCP Socket NoDelay option. Default: true | ||
* Allow a driver to force a Single topology type with a connection string containing one host | ||
*/ | ||
readonly noDelay?: boolean; | ||
readonly directConnection?: boolean; | ||
/** | ||
* The number of milliseconds to wait before initiating keepAlive on the TCP socket. Default: 30000 | ||
* IP family | ||
*/ | ||
readonly keepAlive?: number; | ||
/** | ||
* TCP Connection timeout setting. Default: 30000 | ||
*/ | ||
readonly connectTimeoutMS?: number; | ||
/** | ||
* Version of IP stack. Can be 4, 6. | ||
* If undefined, will attempt to connect with IPv6, and will fall back to IPv4 on failure | ||
*/ | ||
readonly family?: number; | ||
/** | ||
* TCP Socket timeout setting. Default: 360000 | ||
* Force server to assign `_id` values instead of driver | ||
*/ | ||
readonly socketTimeoutMS?: number; | ||
readonly forceServerObjectId?: boolean; | ||
/** | ||
* Server attempt to reconnect #times. Default 30 | ||
* serialize will not emit undefined fields | ||
* note that the driver sets this to `false` | ||
*/ | ||
readonly reconnectTries?: number; | ||
readonly ignoreUndefined?: boolean; | ||
/** | ||
* Server will wait #milliseconds between retries. Default 1000 | ||
* @deprecated TCP Connection keep alive enabled. Will not be able to turn off in the future. | ||
*/ | ||
readonly reconnectInterval?: number; | ||
readonly keepAlive?: boolean; | ||
/** | ||
* Control if high availability monitoring runs for Replicaset or Mongos proxies. Default true | ||
* @deprecated The number of milliseconds to wait before initiating keepAlive on the TCP socket. | ||
* Will not be configurable in the future. | ||
*/ | ||
readonly ha?: boolean; | ||
readonly keepAliveInitialDelay?: number; | ||
/** | ||
* The High availability period for replicaset inquiry. Default: 10000 | ||
* The size (in milliseconds) of the latency window for selecting among multiple suitable MongoDB instances. | ||
*/ | ||
readonly haInterval?: number; | ||
readonly localThresholdMS?: number; | ||
/** | ||
* The name of the replicaset to connect to | ||
* Specifies, in seconds, how stale a secondary can be before the client stops using it for read operations. | ||
*/ | ||
readonly replicaSet?: string; | ||
readonly maxStalenessSeconds?: number; | ||
/** | ||
* Sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms). | ||
* Default: 15 | ||
* The minimum number of connections in the connection pool. | ||
*/ | ||
readonly acceptableLatencyMS?: number; | ||
readonly minPoolSize?: number; | ||
/** | ||
* Sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms). | ||
* Default: 15 | ||
* Enable command monitoring for this client | ||
*/ | ||
readonly secondaryAcceptableLatencyMS?: number; | ||
readonly monitorCommands?: boolean; | ||
/** | ||
* Sets if the driver should connect even if no primary is available. Default: false | ||
* TCP Connection no delay | ||
*/ | ||
readonly connectWithNoPrimary?: boolean; | ||
readonly noDelay?: boolean; | ||
/** | ||
* If the database authentication is dependent on another databaseName. | ||
* A primary key factory function for generation of custom `_id` keys | ||
*/ | ||
readonly authSource?: string; | ||
readonly pkFactory?: any; | ||
/** | ||
* The write concern. | ||
* when deserializing a Binary will return it as a node.js Buffer instance. | ||
*/ | ||
readonly w?: string | number; | ||
readonly promoteBuffers?: boolean; | ||
/** | ||
* The write concern timeout value. | ||
* when deserializing a Long will fit it into a Number if it's smaller than 53 bits. | ||
*/ | ||
readonly wtimeout?: number; | ||
/** | ||
* Specify a journal write concern. Default: false | ||
*/ | ||
readonly j?: boolean; | ||
/** | ||
* Force server to assign _id values instead of driver. Default: false | ||
*/ | ||
readonly forceServerObjectId?: boolean; | ||
/** | ||
* Serialize functions on any object. Default: false | ||
*/ | ||
readonly serializeFunctions?: boolean; | ||
/** | ||
* Specify if the BSON serializer should ignore undefined fields. Default: false | ||
*/ | ||
readonly ignoreUndefined?: boolean; | ||
/** | ||
* Return document results as raw BSON buffers. Default: false | ||
*/ | ||
readonly raw?: boolean; | ||
/** | ||
* Promotes Long values to number if they fit inside the 53 bits resolution. Default: true | ||
*/ | ||
readonly promoteLongs?: boolean; | ||
/** | ||
* Promotes Binary BSON values to native Node Buffers. Default: false | ||
* when deserializing will promote BSON values to their Node.js closest equivalent types. | ||
*/ | ||
readonly promoteBuffers?: boolean; | ||
/** | ||
* Promotes BSON values to native types where possible, set to false to only receive wrapper types. Default: true | ||
*/ | ||
readonly promoteValues?: boolean; | ||
/** | ||
* Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. Default: false | ||
* Enabling the raw option will return a Node.js Buffer which is allocated using allocUnsafe API | ||
*/ | ||
readonly domainsEnabled?: boolean; | ||
readonly raw?: boolean; | ||
/** | ||
* Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, | ||
* default is -1 which is unlimited. | ||
* Specify a read concern for the collection (only MongoDB 3.2 or higher supported) | ||
*/ | ||
readonly bufferMaxEntries?: number; | ||
readonly readConcern?: any; | ||
/** | ||
* The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, | ||
* ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). | ||
* Specifies the read preferences for this connection | ||
*/ | ||
readonly readPreference?: ReadPreference | string; | ||
/** | ||
* A primary key factory object for generation of custom _id keys. | ||
* Specifies the tags document as a comma-separated list of colon-separated key-value pairs. | ||
*/ | ||
readonly pkFactory?: any; | ||
readonly readPreferenceTags?: any[]; | ||
/** | ||
* A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible. | ||
* Specifies the name of the replica set, if the mongod is a member of a replica set. | ||
*/ | ||
readonly promiseLibrary?: any; | ||
readonly replicaSet?: string; | ||
/** | ||
* Specify a read concern for the collection. (only MongoDB 3.2 or higher supported). | ||
* Enable retryable writes. | ||
*/ | ||
readonly readConcern?: any; | ||
readonly retryWrites?: boolean; | ||
/** | ||
* Specify a maxStalenessSeconds value for secondary reads, minimum is 90 seconds | ||
* serialize the javascript functions | ||
*/ | ||
readonly maxStalenessSeconds?: number; | ||
readonly serializeFunctions?: boolean; | ||
/** | ||
* Specify the log level used by the driver logger (error/warn/info/debug). | ||
* The time in milliseconds to attempt a send or receive on a socket before the attempt times out. | ||
*/ | ||
readonly loggerLevel?: "error" | "warn" | "info" | "debug"; | ||
readonly socketTimeoutMS?: number; | ||
/** | ||
* Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function | ||
* Default: true | ||
* @deprecated A boolean to enable or disables TLS/SSL for the connection. | ||
* (The ssl option is equivalent to the tls option.) | ||
*/ | ||
readonly checkServerIdentity?: boolean | Function; | ||
readonly ssl?: boolean; | ||
/** | ||
* Validate MongoClient passed in options for correctness. Default: false | ||
* @deprecated SSL Root Certificate file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCAFile instead. | ||
*/ | ||
readonly validateOptions?: boolean | any; | ||
readonly sslCA?: string; | ||
/** | ||
* The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections | ||
* @deprecated SSL Certificate revocation list file path. | ||
* | ||
* Will be removed in the next major version. | ||
*/ | ||
readonly appname?: string; | ||
readonly sslCRL?: string; | ||
/** | ||
* Sets the authentication mechanism that MongoDB will use to authenticate the connection | ||
* @deprecated SSL Certificate file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFile instead. | ||
*/ | ||
readonly authMechanism?: string; | ||
readonly sslCert?: string; | ||
/** | ||
* Type of compression to use: snappy or zlib | ||
* @deprecated SSL Key file file path. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFile instead. | ||
*/ | ||
readonly compression?: any; | ||
readonly sslKey?: string; | ||
/** | ||
* Specify a file sync write concern. Default: false | ||
* @deprecated SSL Certificate pass phrase. | ||
* | ||
* Will be removed in the next major version. Please use tlsCertificateKeyFilePassword instead. | ||
*/ | ||
readonly fsync?: boolean; | ||
readonly sslPass?: string; | ||
/** | ||
* Read preference tags | ||
* @deprecated Validate mongod server certificate against Certificate Authority | ||
* | ||
* Will be removed in the next major version. Please use tlsAllowInvalidCertificates instead. | ||
*/ | ||
readonly readPreferenceTags?: any[]; | ||
readonly sslValidate?: boolean; | ||
/** | ||
* The number of retries for a tailable cursor. Default: 5 | ||
* Enables or disables TLS/SSL for the connection. | ||
*/ | ||
readonly numberOfRetries?: number; | ||
readonly tls?: boolean; | ||
/** | ||
* Enable auto reconnecting for single server instances. Default: true | ||
* Bypasses validation of the certificates presented by the mongod/mongos instance | ||
*/ | ||
readonly auto_reconnect?: boolean; | ||
readonly tlsAllowInvalidCertificates?: boolean; | ||
/** | ||
* Enable command monitoring for this client. Default: false | ||
* Specifies the location of a local .pem file that contains the root certificate chain from the Certificate Authority. | ||
*/ | ||
readonly monitorCommands?: boolean; | ||
readonly tlsCAFile?: string; | ||
/** | ||
* If present, the connection pool will be initialized with minSize connections, and will never dip below minSize connections | ||
* Specifies the location of a local .pem file that contains the client's TLS/SSL certificate and key. | ||
*/ | ||
readonly minSize?: number; | ||
readonly tlsCertificateKeyFile?: string; | ||
/** | ||
* Determines whether or not to use the new url parser. Default: false | ||
* Specifies the password to de-crypt the tlsCertificateKeyFile. | ||
*/ | ||
readonly useNewUrlParser?: boolean; | ||
readonly tlsCertificateKeyFilePassword?: string; | ||
/** | ||
* Determines whether or not to use the new Server Discovery and Monitoring engine. Default: false | ||
* https://github.com/mongodb/node-mongodb-native/releases/tag/v3.2.1 | ||
* @deprecated The write concern w value | ||
* | ||
* Please use the `writeConcern` option instead | ||
*/ | ||
readonly useUnifiedTopology?: boolean; | ||
readonly w?: string | number; | ||
/** | ||
* Automatic Client-Side Field Level Encryption configuration. | ||
* A MongoDB WriteConcern, which describes the level of acknowledgement | ||
* requested from MongoDB for write operations. | ||
*/ | ||
readonly autoEncryption?: any; | ||
readonly writeConcern?: any; | ||
/** | ||
* Enables or disables the ability to retry writes upon encountering transient network errors. | ||
* @deprecated The write concern timeout | ||
* | ||
* Please use the `writeConcern` option instead | ||
*/ | ||
readonly retryWrites?: boolean; | ||
readonly wtimeoutMS?: number; | ||
} |
@@ -92,9 +92,8 @@ import { Driver } from "../Driver"; | ||
maxAliasLength?: number; | ||
cteCapabilities: CteCapabilities; | ||
/** | ||
* Valid mongo connection options | ||
* NOTE: Keep sync with MongoConnectionOptions | ||
* Sync with http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html | ||
* NOTE: Keep in sync with MongoConnectionOptions | ||
*/ | ||
protected validOptionNames: string[]; | ||
cteCapabilities: CteCapabilities; | ||
constructor(connection: DataSource); | ||
@@ -101,0 +100,0 @@ /** |
@@ -83,2 +83,5 @@ "use strict"; | ||
}; | ||
this.cteCapabilities = { | ||
enabled: false, | ||
}; | ||
// ------------------------------------------------------------------------- | ||
@@ -89,73 +92,59 @@ // Protected Properties | ||
* Valid mongo connection options | ||
* NOTE: Keep sync with MongoConnectionOptions | ||
* Sync with http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html | ||
* NOTE: Keep in sync with MongoConnectionOptions | ||
*/ | ||
this.validOptionNames = [ | ||
"poolSize", | ||
"appName", | ||
"authMechanism", | ||
"authSource", | ||
"autoEncryption", | ||
"checkServerIdentity", | ||
"compressors", | ||
"connectTimeoutMS", | ||
"directConnection", | ||
"family", | ||
"forceServerObjectId", | ||
"ignoreUndefined", | ||
"keepAlive", | ||
"keepAliveInitialDelay", | ||
"localThresholdMS", | ||
"maxStalenessSeconds", | ||
"minPoolSize", | ||
"monitorCommands", | ||
"noDelay", | ||
"pkFactory", | ||
"promoteBuffers", | ||
"promoteLongs", | ||
"promoteValues", | ||
"raw", | ||
"readConcern", | ||
"readPreference", | ||
"readPreferenceTags", | ||
"replicaSet", | ||
"retryWrites", | ||
"serializeFunctions", | ||
"socketTimeoutMS", | ||
"ssl", | ||
"sslValidate", | ||
"sslCA", | ||
"sslCRL", | ||
"sslCert", | ||
"sslKey", | ||
"sslPass", | ||
"sslCRL", | ||
"autoReconnect", | ||
"noDelay", | ||
"keepAlive", | ||
"keepAliveInitialDelay", | ||
"connectTimeoutMS", | ||
"family", | ||
"socketTimeoutMS", | ||
"reconnectTries", | ||
"reconnectInterval", | ||
"ha", | ||
"haInterval", | ||
"replicaSet", | ||
"secondaryAcceptableLatencyMS", | ||
"acceptableLatencyMS", | ||
"connectWithNoPrimary", | ||
"authSource", | ||
"sslValidate", | ||
"tls", | ||
"tlsAllowInvalidCertificates", | ||
"tlsCAFile", | ||
"tlsCertificateKeyFile", | ||
"tlsCertificateKeyFilePassword", | ||
"w", | ||
"wtimeout", | ||
"j", | ||
"writeConcern", | ||
"forceServerObjectId", | ||
"serializeFunctions", | ||
"ignoreUndefined", | ||
"raw", | ||
"bufferMaxEntries", | ||
"readPreference", | ||
"pkFactory", | ||
"promiseLibrary", | ||
"readConcern", | ||
"maxStalenessSeconds", | ||
"loggerLevel", | ||
// Do not overwrite BaseDataSourceOptions.logger | ||
// "logger", | ||
"promoteValues", | ||
"promoteBuffers", | ||
"promoteLongs", | ||
"domainsEnabled", | ||
"checkServerIdentity", | ||
"validateOptions", | ||
"wtimeoutMS", | ||
// Undocumented deprecated options | ||
// todo: remove next major version | ||
"appname", | ||
// omit auth - we are building url from username and password | ||
// "auth" | ||
"authMechanism", | ||
"compression", | ||
"fsync", | ||
"readPreferenceTags", | ||
"numberOfRetries", | ||
"auto_reconnect", | ||
"minSize", | ||
"monitorCommands", | ||
"j", | ||
"useNewUrlParser", | ||
"useUnifiedTopology", | ||
"autoEncryption", | ||
"retryWrites", | ||
"directConnection", | ||
"wtimeout", | ||
]; | ||
this.cteCapabilities = { | ||
enabled: false, | ||
}; | ||
this.options = connection.options; | ||
@@ -388,6 +377,6 @@ // validate options to make sure everything is correct and driver will be able to establish connection | ||
options.host + portUrlPart || | ||
"127.0.0.1" + portUrlPart}/${options.database || ""}?replicaSet=${options.replicaSet}${options.tls ? "&tls=true" : ""}`; | ||
"127.0.0.1" + portUrlPart}/${options.database || ""}`; | ||
} | ||
else { | ||
connectionString = `${schemaUrlPart}://${credentialsUrlPart}${options.host || "127.0.0.1"}${portUrlPart}/${options.database || ""}${options.tls ? "?tls=true" : ""}`; | ||
connectionString = `${schemaUrlPart}://${credentialsUrlPart}${options.host || "127.0.0.1"}${portUrlPart}/${options.database || ""}`; | ||
} | ||
@@ -401,11 +390,14 @@ return connectionString; | ||
const mongoOptions = {}; | ||
for (let index = 0; index < this.validOptionNames.length; index++) { | ||
const optionName = this.validOptionNames[index]; | ||
if (options.extra && optionName in options.extra) { | ||
mongoOptions[optionName] = options.extra[optionName]; | ||
} | ||
else if (optionName in options) { | ||
for (const optionName of this.validOptionNames) { | ||
if (optionName in options) { | ||
mongoOptions[optionName] = options[optionName]; | ||
} | ||
} | ||
mongoOptions.driverInfo = { | ||
name: "TypeORM", | ||
}; | ||
if ("poolSize" in options) { | ||
mongoOptions["maxPoolSize"] = options["poolSize"]; | ||
} | ||
Object.assign(mongoOptions, options.extra); | ||
return mongoOptions; | ||
@@ -412,0 +404,0 @@ } |
@@ -561,3 +561,3 @@ "use strict"; | ||
value = value | ||
.substr(1, value.length - 2) | ||
.slice(1, -1) | ||
.split(",") | ||
@@ -568,6 +568,4 @@ .map((val) => { | ||
val = val.slice(1, -1); | ||
// replace double escaped backslash to single escaped e.g. \\\\ -> \\ | ||
val = val.replace(/(\\\\)/g, "\\"); | ||
// replace escaped double quotes to non-escaped e.g. \"asd\" -> "asd" | ||
return val.replace(/(\\")/g, '"'); | ||
// replace escaped backslash and double quotes | ||
return val.replace(/\\(\\|")/g, "$1"); | ||
}); | ||
@@ -574,0 +572,0 @@ // convert to number if that exists in possible enum options |
@@ -50,3 +50,3 @@ "use strict"; | ||
"smallint", | ||
"int", // alias for "integer" | ||
"int", // typeorm alias for "integer" | ||
"integer", | ||
@@ -56,6 +56,6 @@ "bigint", | ||
"decimal", | ||
"dec", // alias for "decimal" | ||
"dec", // typeorm alias for "decimal" | ||
"real", | ||
"double", | ||
"float", | ||
"float", // database alias for "real" / "double" | ||
"date", | ||
@@ -66,13 +66,13 @@ "time", | ||
"boolean", | ||
"char", // not officially supported | ||
"char", // not officially supported, in SAP HANA Cloud: alias for "nchar" | ||
"nchar", // not officially supported | ||
"varchar", // deprecated | ||
"varchar", // in SAP HANA Cloud: alias for "nvarchar" | ||
"nvarchar", | ||
"text", // deprecated | ||
"alphanum", // deprecated | ||
"shorttext", // deprecated | ||
"text", // removed in SAP HANA Cloud | ||
"alphanum", // removed in SAP HANA Cloud | ||
"shorttext", // removed in SAP HANA Cloud | ||
"array", | ||
"varbinary", | ||
"blob", | ||
"clob", // deprecated | ||
"clob", // in SAP HANA Cloud: alias for "nclob" | ||
"nclob", | ||
@@ -433,2 +433,12 @@ "st_geometry", | ||
} | ||
else if (column.type === "float") { | ||
const length = typeof column.length === "string" | ||
? parseInt(column.length) | ||
: column.length; | ||
// https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/4ee2f261e9c44003807d08ccc2e249ac.html | ||
if (length && length < 25) { | ||
return "real"; | ||
} | ||
return "double"; | ||
} | ||
else if (column.type === String) { | ||
@@ -456,5 +466,17 @@ return "nvarchar"; | ||
} | ||
else { | ||
return column.type || ""; | ||
if (DriverUtils_1.DriverUtils.isReleaseVersionOrGreater(this, "4.0")) { | ||
// SAP HANA Cloud deprecated / removed these data types | ||
if (column.type === "varchar" || | ||
column.type === "alphanum" || | ||
column.type === "shorttext") { | ||
return "nvarchar"; | ||
} | ||
else if (column.type === "text" || column.type === "clob") { | ||
return "nclob"; | ||
} | ||
else if (column.type === "char") { | ||
return "nchar"; | ||
} | ||
} | ||
return column.type || ""; | ||
} | ||
@@ -578,20 +600,7 @@ /** | ||
const tableColumn = tableColumns.find((c) => c.name === columnMetadata.databaseName); | ||
if (!tableColumn) | ||
return false; // we don't need new columns, we only need exist and changed | ||
// console.log("table:", columnMetadata.entityMetadata.tableName); | ||
// console.log("name:", tableColumn.name, columnMetadata.databaseName); | ||
// console.log("type:", tableColumn.type, _this.normalizeType(columnMetadata)); | ||
// console.log("length:", tableColumn.length, _this.getColumnLength(columnMetadata)); | ||
// console.log("width:", tableColumn.width, columnMetadata.width); | ||
// console.log("precision:", tableColumn.precision, columnMetadata.precision); | ||
// console.log("scale:", tableColumn.scale, columnMetadata.scale); | ||
// console.log("default:", tableColumn.default, columnMetadata.default); | ||
// console.log("isPrimary:", tableColumn.isPrimary, columnMetadata.isPrimary); | ||
// console.log("isNullable:", tableColumn.isNullable, columnMetadata.isNullable); | ||
// console.log("isUnique:", tableColumn.isUnique, _this.normalizeIsUnique(columnMetadata)); | ||
// console.log("isGenerated:", tableColumn.isGenerated, columnMetadata.isGenerated); | ||
// console.log((columnMetadata.generationStrategy !== "uuid" && tableColumn.isGenerated !== columnMetadata.isGenerated)); | ||
// console.log("=========================================="); | ||
const normalizeDefault = this.normalizeDefault(columnMetadata); | ||
const hanaNullComapatibleDefault = normalizeDefault == null ? undefined : normalizeDefault; | ||
if (!tableColumn) { | ||
// we don't need new columns, we only need exist and changed | ||
return false; | ||
} | ||
const normalizedDefault = this.normalizeDefault(columnMetadata); | ||
return (tableColumn.name !== columnMetadata.databaseName || | ||
@@ -607,3 +616,3 @@ tableColumn.type !== this.normalizeType(columnMetadata) || | ||
(!tableColumn.isGenerated && | ||
hanaNullComapatibleDefault !== tableColumn.default) || // we included check for generated here, because generated columns already can have default values | ||
normalizedDefault !== tableColumn.default) || // we included check for generated here, because generated columns already can have default values | ||
tableColumn.isPrimary !== columnMetadata.isPrimary || | ||
@@ -633,3 +642,3 @@ tableColumn.isNullable !== columnMetadata.isNullable || | ||
isFullTextColumnTypeSupported() { | ||
return true; | ||
return !DriverUtils_1.DriverUtils.isReleaseVersionOrGreater(this, "4.0"); | ||
} | ||
@@ -636,0 +645,0 @@ /** |
@@ -132,2 +132,3 @@ /*! | ||
export * from "./driver/sqlserver/MssqlParameter"; | ||
export * from "./subscriber/event/QueryEvent"; | ||
export { ConnectionOptionsReader } from "./connection/ConnectionOptionsReader"; | ||
@@ -134,0 +135,0 @@ export { ConnectionOptions } from "./connection/ConnectionOptions"; |
@@ -139,2 +139,3 @@ "use strict"; | ||
tslib_1.__exportStar(require("./driver/sqlserver/MssqlParameter"), exports); | ||
tslib_1.__exportStar(require("./subscriber/event/QueryEvent"), exports); | ||
// export * from "./data-source"; | ||
@@ -141,0 +142,0 @@ var ConnectionOptionsReader_1 = require("./connection/ConnectionOptionsReader"); |
@@ -244,3 +244,3 @@ "use strict"; | ||
successMigrations.push(migration); | ||
this.connection.logger.logSchemaBuild(`Migration ${migration.name} has been ${this.fake ? "(fake)" : ""} executed successfully.`); | ||
this.connection.logger.logSchemaBuild(`Migration ${migration.name} has been ${this.fake ? "(fake) " : ""}executed successfully.`); | ||
}); | ||
@@ -317,3 +317,3 @@ } | ||
await this.deleteExecutedMigration(queryRunner, migrationToRevert); | ||
this.connection.logger.logSchemaBuild(`Migration ${migrationToRevert.name} has been ${this.fake ? "(fake)" : ""} reverted successfully.`); | ||
this.connection.logger.logSchemaBuild(`Migration ${migrationToRevert.name} has been ${this.fake ? "(fake) " : ""}reverted successfully.`); | ||
// commit transaction if we started it | ||
@@ -320,0 +320,0 @@ if (transactionStartedByUs) |
@@ -1,1 +0,1 @@ | ||
{ "name": "typeorm", "version": "0.3.22-dev.fb06662", "private": false, "description": "Data-Mapper ORM for TypeScript and ES2021+. Supports MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB databases.", "homepage": "https://typeorm.io", "bugs": { "url": "https://github.com/typeorm/typeorm/issues" }, "repository": { "type": "git", "url": "https://github.com/typeorm/typeorm.git" }, "funding": "https://opencollective.com/typeorm", "license": "MIT", "author": { "name": "Umed Khudoiberdiev", "email": "pleerock.me@gmail.com" }, "exports": { ".": { "types": "./index.d.ts", "node": { "import": "./index.mjs", "require": "./index.js", "types": "./index.d.ts" }, "browser": { "require": "./index.js", "import": "./browser/index.js", "default": "./index.js" } }, "./browser": { "types": "./index.d.ts", "default": "./browser/index.js" }, "./*.js": "./*.js", "./*": { "require": "./*.js", "import": "./*" } }, "main": "./index.js", "module": "./index.mjs", "browser": { "./browser/connection/ConnectionOptionsReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/connection/options-reader/ConnectionOptionsXmlReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/connection/options-reader/ConnectionOptionsYmlReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/driver/aurora-data-api/AuroraDataApiDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/better-sqlite3/BetterSqlite3Driver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/cockroachdb/CockroachDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/MongoDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/MongoQueryRunner.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/bson.typings.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/typings.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mysql/MysqlDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/oracle/OracleDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/postgres/PostgresDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sap/SapDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sqlite/SqliteDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sqlserver/SqlServerDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/entity-manager/MongoEntityManager.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/logger/FileLogger.js": "./browser/platform/BrowserFileLoggerDummy.js", "./browser/platform/PlatformTools.js": "./browser/platform/BrowserPlatformTools.js", "./browser/repository/MongoRepository.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/util/DirectoryExportedClassesLoader.js": "./browser/platform/BrowserDirectoryExportedClassesLoader.js", "./index.js": "./browser/index.js", "./index.mjs": "./browser/index.js" }, "types": "./index.d.ts", "bin": { "typeorm": "./cli.js", "typeorm-ts-node-commonjs": "./cli-ts-node-commonjs.js", "typeorm-ts-node-esm": "./cli-ts-node-esm.js" }, "scripts": { "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", "compile": "rimraf ./build && tsc", "format": "prettier --cache --write \"./**/*.ts\"", "format:ci": "prettier --check \"./**/*.ts\"", "lint": "eslint .", "pack": "gulp pack", "package": "gulp package", "test": "npm run compile && npm run test:fast --", "test:ci": "mocha --bail", "test:fast": "mocha", "watch": "tsc --watch" }, "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", "sql-highlight": "^6.0.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" }, "devDependencies": { "@eslint/js": "^9.22.0", "@sap/hana-client": "^2.24.21", "@tsconfig/node16": "^16.1.3", "@types/chai": "^4.3.20", "@types/chai-as-promised": "^7.1.8", "@types/debug": "^4.1.12", "@types/gulp-rename": "^2.0.6", "@types/gulp-sourcemaps": "^0.0.38", "@types/mocha": "^10.0.10", "@types/node": "^16.18.126", "@types/sha.js": "^2.4.4", "@types/sinon": "^10.0.20", "@types/sinon-chai": "^4.0.0", "@types/source-map-support": "^0.5.10", "@types/yargs": "^17.0.33", "better-sqlite3": "^8.7.0", "chai": "^4.5.0", "chai-as-promised": "^7.1.2", "class-transformer": "^0.5.1", "conventional-changelog-angular": "^7.0.0", "conventional-changelog-cli": "^5.0.0", "eslint": "^9.22.0", "globals": "^16.0.0", "gulp": "^4.0.2", "gulp-rename": "^2.0.0", "gulp-replace": "^1.1.4", "gulp-shell": "^0.8.0", "gulp-sourcemaps": "^3.0.0", "gulp-typescript": "^6.0.0-alpha.1", "gulpclass": "^0.2.0", "hdb-pool": "^0.1.6", "mocha": "^10.8.2", "mongodb": "^6.15.0", "mssql": "^11.0.1", "mysql": "^2.18.1", "mysql2": "^3.14.0", "nyc": "^17.1.0", "oracledb": "^6.8.0", "pg": "^8.14.1", "pg-query-stream": "^4.8.1", "prettier": "^2.8.8", "redis": "^4.7.0", "remap-istanbul": "^0.13.0", "rimraf": "^5.0.10", "sinon": "^15.2.0", "sinon-chai": "^3.7.0", "source-map-support": "^0.5.21", "sql.js": "^1.13.0", "sqlite3": "^5.1.7", "ts-node": "^10.9.2", "typescript": "^5.8.2", "typescript-eslint": "^8.27.0" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "peerDependenciesMeta": { "@google-cloud/spanner": { "optional": true }, "@sap/hana-client": { "optional": true }, "better-sqlite3": { "optional": true }, "hdb-pool": { "optional": true }, "ioredis": { "optional": true }, "mongodb": { "optional": true }, "mssql": { "optional": true }, "mysql2": { "optional": true }, "oracledb": { "optional": true }, "pg": { "optional": true }, "pg-native": { "optional": true }, "pg-query-stream": { "optional": true }, "redis": { "optional": true }, "sql.js": { "optional": true }, "sqlite3": { "optional": true }, "ts-node": { "optional": true }, "typeorm-aurora-data-api-driver": { "optional": true } }, "engines": { "node": ">=16.13.0" }, "collective": { "type": "opencollective", "url": "https://opencollective.com/typeorm", "logo": "https://opencollective.com/opencollective/logo.txt" }, "readmeFilename": "README.md", "tags": [ "orm", "typescript", "typescript-orm", "mariadb", "mariadb-orm", "mysql", "mysql-orm", "oracle", "oracle-orm", "postgresql", "postgresql-orm", "sap-hana", "sap-hana-orm", "spanner", "cloud-spanner", "cloud-spanner-orm", "sqlite", "sqlite-orm", "sql-server", "sql-server-orm" ] } | ||
{ "name": "typeorm", "version": "0.3.23-dev.6c5668b", "private": false, "description": "Data-Mapper ORM for TypeScript and ES2021+. Supports MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB databases.", "homepage": "https://typeorm.io", "bugs": { "url": "https://github.com/typeorm/typeorm/issues" }, "repository": { "type": "git", "url": "https://github.com/typeorm/typeorm.git" }, "funding": "https://opencollective.com/typeorm", "license": "MIT", "author": { "name": "Umed Khudoiberdiev", "email": "pleerock.me@gmail.com" }, "exports": { ".": { "types": "./index.d.ts", "node": { "import": "./index.mjs", "require": "./index.js", "types": "./index.d.ts" }, "browser": { "require": "./index.js", "import": "./browser/index.js", "default": "./index.js" } }, "./browser": { "types": "./index.d.ts", "default": "./browser/index.js" }, "./*.js": "./*.js", "./*": { "require": "./*.js", "import": "./*" } }, "main": "./index.js", "module": "./index.mjs", "browser": { "./browser/connection/ConnectionOptionsReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/connection/options-reader/ConnectionOptionsXmlReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/connection/options-reader/ConnectionOptionsYmlReader.js": "./browser/platform/BrowserConnectionOptionsReaderDummy.js", "./browser/driver/aurora-data-api/AuroraDataApiDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/better-sqlite3/BetterSqlite3Driver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/cockroachdb/CockroachDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/MongoDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/MongoQueryRunner.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/bson.typings.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mongodb/typings.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/mysql/MysqlDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/oracle/OracleDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/postgres/PostgresDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sap/SapDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sqlite/SqliteDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sqlserver/SqlServerDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/entity-manager/MongoEntityManager.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/logger/FileLogger.js": "./browser/platform/BrowserFileLoggerDummy.js", "./browser/platform/PlatformTools.js": "./browser/platform/BrowserPlatformTools.js", "./browser/repository/MongoRepository.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/util/DirectoryExportedClassesLoader.js": "./browser/platform/BrowserDirectoryExportedClassesLoader.js", "./index.js": "./browser/index.js", "./index.mjs": "./browser/index.js" }, "types": "./index.d.ts", "bin": { "typeorm": "./cli.js", "typeorm-ts-node-commonjs": "./cli-ts-node-commonjs.js", "typeorm-ts-node-esm": "./cli-ts-node-esm.js" }, "scripts": { "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1", "compile": "rimraf ./build && tsc", "format": "prettier --cache --write \"./**/*.ts\"", "format:ci": "prettier --check \"./**/*.ts\"", "lint": "eslint .", "pack": "gulp pack", "package": "gulp package", "test": "npm run compile && npm run test:fast --", "test:ci": "mocha --bail", "test:fast": "mocha", "watch": "tsc --watch" }, "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", "sql-highlight": "^6.0.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" }, "devDependencies": { "@eslint/js": "^9.22.0", "@sap/hana-client": "^2.24.21", "@tsconfig/node16": "^16.1.3", "@types/chai": "^4.3.20", "@types/chai-as-promised": "^7.1.8", "@types/debug": "^4.1.12", "@types/gulp-rename": "^2.0.6", "@types/gulp-sourcemaps": "^0.0.38", "@types/mocha": "^10.0.10", "@types/node": "^16.18.126", "@types/sha.js": "^2.4.4", "@types/sinon": "^10.0.20", "@types/sinon-chai": "^4.0.0", "@types/source-map-support": "^0.5.10", "@types/yargs": "^17.0.33", "better-sqlite3": "^8.7.0", "chai": "^4.5.0", "chai-as-promised": "^7.1.2", "class-transformer": "^0.5.1", "conventional-changelog-angular": "^7.0.0", "conventional-changelog-cli": "^5.0.0", "eslint": "^9.22.0", "globals": "^16.0.0", "gulp": "^4.0.2", "gulp-rename": "^2.0.0", "gulp-replace": "^1.1.4", "gulp-shell": "^0.8.0", "gulp-sourcemaps": "^3.0.0", "gulp-typescript": "^6.0.0-alpha.1", "gulpclass": "^0.2.0", "hdb-pool": "^0.1.6", "mocha": "^10.8.2", "mongodb": "^6.15.0", "mssql": "^11.0.1", "mysql": "^2.18.1", "mysql2": "^3.14.0", "nyc": "^17.1.0", "oracledb": "^6.8.0", "pg": "^8.14.1", "pg-query-stream": "^4.8.1", "prettier": "^2.8.8", "redis": "^4.7.0", "remap-istanbul": "^0.13.0", "rimraf": "^5.0.10", "sinon": "^15.2.0", "sinon-chai": "^3.7.0", "source-map-support": "^0.5.21", "sql.js": "^1.13.0", "sqlite3": "^5.1.7", "ts-node": "^10.9.2", "typescript": "^5.8.2", "typescript-eslint": "^8.27.0" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "peerDependenciesMeta": { "@google-cloud/spanner": { "optional": true }, "@sap/hana-client": { "optional": true }, "better-sqlite3": { "optional": true }, "hdb-pool": { "optional": true }, "ioredis": { "optional": true }, "mongodb": { "optional": true }, "mssql": { "optional": true }, "mysql2": { "optional": true }, "oracledb": { "optional": true }, "pg": { "optional": true }, "pg-native": { "optional": true }, "pg-query-stream": { "optional": true }, "redis": { "optional": true }, "sql.js": { "optional": true }, "sqlite3": { "optional": true }, "ts-node": { "optional": true }, "typeorm-aurora-data-api-driver": { "optional": true } }, "engines": { "node": ">=16.13.0" }, "collective": { "type": "opencollective", "url": "https://opencollective.com/typeorm", "logo": "https://opencollective.com/opencollective/logo.txt" }, "readmeFilename": "README.md", "tags": [ "orm", "typescript", "typescript-orm", "mariadb", "mariadb-orm", "mysql", "mysql-orm", "oracle", "oracle-orm", "postgresql", "postgresql-orm", "sap-hana", "sap-hana-orm", "spanner", "cloud-spanner", "cloud-spanner-orm", "sqlite", "sqlite-orm", "sql-server", "sql-server-orm" ] } |
@@ -354,3 +354,2 @@ "use strict"; | ||
query += updatePart.join(", "); | ||
query += " "; | ||
} | ||
@@ -362,3 +361,3 @@ if (Array.isArray(overwrite) && | ||
query += overwrite | ||
.map((column) => `${tableName}.${this.escape(column)} IS DISTINCT FROM EXCLUDED.${this.escape(column)}`) | ||
.map((column) => `${this.escape(this.alias)}.${this.escape(column)} IS DISTINCT FROM EXCLUDED.${this.escape(column)}`) | ||
.join(" OR "); | ||
@@ -567,3 +566,4 @@ query += ") "; | ||
else if (value === null && | ||
this.connection.driver.options.type === "spanner") { | ||
(this.connection.driver.options.type === "spanner" || | ||
this.connection.driver.options.type === "oracle")) { | ||
expression += "NULL"; | ||
@@ -570,0 +570,0 @@ // support for SQL expressions in queries |
@@ -39,3 +39,3 @@ import { EntityManager } from "../../entity-manager/EntityManager"; | ||
/** | ||
* The duration of the query execution. | ||
* The duration of the query execution, in milliseconds. | ||
*/ | ||
@@ -42,0 +42,0 @@ executionTime?: number; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
20462788
0.11%3014
0.6%189612
0.11%25
-7.41%55
-5.17%